mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
sync Aro dependency
ref: 0c8c251e336148413ceca7b345c0b6f7255b009b
This commit is contained in:
parent
c327489d21
commit
145ddb8104
13037
deps/aro/Builtins/BuiltinFunction.zig
vendored
13037
deps/aro/Builtins/BuiltinFunction.zig
vendored
File diff suppressed because it is too large
Load Diff
487
deps/aro/CharInfo.zig
vendored
487
deps/aro/CharInfo.zig
vendored
@ -1,487 +0,0 @@
|
||||
//! This module provides functions for classifying characters according to
|
||||
//! various C standards. All classification routines *do not* consider
|
||||
//! characters from the basic character set; it is assumed those will be
|
||||
//! checked separately
|
||||
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
/// C11 Standard Annex D
|
||||
pub fn isC11IdChar(codepoint: u21) bool {
|
||||
assert(codepoint > 0x7F);
|
||||
return switch (codepoint) {
|
||||
// 1
|
||||
0x00A8,
|
||||
0x00AA,
|
||||
0x00AD,
|
||||
0x00AF,
|
||||
0x00B2...0x00B5,
|
||||
0x00B7...0x00BA,
|
||||
0x00BC...0x00BE,
|
||||
0x00C0...0x00D6,
|
||||
0x00D8...0x00F6,
|
||||
0x00F8...0x00FF,
|
||||
|
||||
// 2
|
||||
0x0100...0x167F,
|
||||
0x1681...0x180D,
|
||||
0x180F...0x1FFF,
|
||||
|
||||
// 3
|
||||
0x200B...0x200D,
|
||||
0x202A...0x202E,
|
||||
0x203F...0x2040,
|
||||
0x2054,
|
||||
0x2060...0x206F,
|
||||
|
||||
// 4
|
||||
0x2070...0x218F,
|
||||
0x2460...0x24FF,
|
||||
0x2776...0x2793,
|
||||
0x2C00...0x2DFF,
|
||||
0x2E80...0x2FFF,
|
||||
|
||||
// 5
|
||||
0x3004...0x3007,
|
||||
0x3021...0x302F,
|
||||
0x3031...0x303F,
|
||||
|
||||
// 6
|
||||
0x3040...0xD7FF,
|
||||
|
||||
// 7
|
||||
0xF900...0xFD3D,
|
||||
0xFD40...0xFDCF,
|
||||
0xFDF0...0xFE44,
|
||||
0xFE47...0xFFFD,
|
||||
|
||||
// 8
|
||||
0x10000...0x1FFFD,
|
||||
0x20000...0x2FFFD,
|
||||
0x30000...0x3FFFD,
|
||||
0x40000...0x4FFFD,
|
||||
0x50000...0x5FFFD,
|
||||
0x60000...0x6FFFD,
|
||||
0x70000...0x7FFFD,
|
||||
0x80000...0x8FFFD,
|
||||
0x90000...0x9FFFD,
|
||||
0xA0000...0xAFFFD,
|
||||
0xB0000...0xBFFFD,
|
||||
0xC0000...0xCFFFD,
|
||||
0xD0000...0xDFFFD,
|
||||
0xE0000...0xEFFFD,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// C99 Standard Annex D
|
||||
pub fn isC99IdChar(codepoint: u21) bool {
|
||||
assert(codepoint > 0x7F);
|
||||
return switch (codepoint) {
|
||||
// Latin
|
||||
0x00AA,
|
||||
0x00BA,
|
||||
0x00C0...0x00D6,
|
||||
0x00D8...0x00F6,
|
||||
0x00F8...0x01F5,
|
||||
0x01FA...0x0217,
|
||||
0x0250...0x02A8,
|
||||
0x1E00...0x1E9B,
|
||||
0x1EA0...0x1EF9,
|
||||
0x207F,
|
||||
|
||||
// Greek
|
||||
0x0386,
|
||||
0x0388...0x038A,
|
||||
0x038C,
|
||||
0x038E...0x03A1,
|
||||
0x03A3...0x03CE,
|
||||
0x03D0...0x03D6,
|
||||
0x03DA,
|
||||
0x03DC,
|
||||
0x03DE,
|
||||
0x03E0,
|
||||
0x03E2...0x03F3,
|
||||
0x1F00...0x1F15,
|
||||
0x1F18...0x1F1D,
|
||||
0x1F20...0x1F45,
|
||||
0x1F48...0x1F4D,
|
||||
0x1F50...0x1F57,
|
||||
0x1F59,
|
||||
0x1F5B,
|
||||
0x1F5D,
|
||||
0x1F5F...0x1F7D,
|
||||
0x1F80...0x1FB4,
|
||||
0x1FB6...0x1FBC,
|
||||
0x1FC2...0x1FC4,
|
||||
0x1FC6...0x1FCC,
|
||||
0x1FD0...0x1FD3,
|
||||
0x1FD6...0x1FDB,
|
||||
0x1FE0...0x1FEC,
|
||||
0x1FF2...0x1FF4,
|
||||
0x1FF6...0x1FFC,
|
||||
|
||||
// Cyrillic
|
||||
0x0401...0x040C,
|
||||
0x040E...0x044F,
|
||||
0x0451...0x045C,
|
||||
0x045E...0x0481,
|
||||
0x0490...0x04C4,
|
||||
0x04C7...0x04C8,
|
||||
0x04CB...0x04CC,
|
||||
0x04D0...0x04EB,
|
||||
0x04EE...0x04F5,
|
||||
0x04F8...0x04F9,
|
||||
|
||||
// Armenian
|
||||
0x0531...0x0556,
|
||||
0x0561...0x0587,
|
||||
|
||||
// Hebrew
|
||||
0x05B0...0x05B9,
|
||||
0x05BB...0x05BD,
|
||||
0x05BF,
|
||||
0x05C1...0x05C2,
|
||||
0x05D0...0x05EA,
|
||||
0x05F0...0x05F2,
|
||||
|
||||
// Arabic
|
||||
0x0621...0x063A,
|
||||
0x0640...0x0652,
|
||||
0x0670...0x06B7,
|
||||
0x06BA...0x06BE,
|
||||
0x06C0...0x06CE,
|
||||
0x06D0...0x06DC,
|
||||
0x06E5...0x06E8,
|
||||
0x06EA...0x06ED,
|
||||
|
||||
// Devanagari
|
||||
0x0901...0x0903,
|
||||
0x0905...0x0939,
|
||||
0x093E...0x094D,
|
||||
0x0950...0x0952,
|
||||
0x0958...0x0963,
|
||||
|
||||
// Bengali
|
||||
0x0981...0x0983,
|
||||
0x0985...0x098C,
|
||||
0x098F...0x0990,
|
||||
0x0993...0x09A8,
|
||||
0x09AA...0x09B0,
|
||||
0x09B2,
|
||||
0x09B6...0x09B9,
|
||||
0x09BE...0x09C4,
|
||||
0x09C7...0x09C8,
|
||||
0x09CB...0x09CD,
|
||||
0x09DC...0x09DD,
|
||||
0x09DF...0x09E3,
|
||||
0x09F0...0x09F1,
|
||||
|
||||
// Gurmukhi
|
||||
0x0A02,
|
||||
0x0A05...0x0A0A,
|
||||
0x0A0F...0x0A10,
|
||||
0x0A13...0x0A28,
|
||||
0x0A2A...0x0A30,
|
||||
0x0A32...0x0A33,
|
||||
0x0A35...0x0A36,
|
||||
0x0A38...0x0A39,
|
||||
0x0A3E...0x0A42,
|
||||
0x0A47...0x0A48,
|
||||
0x0A4B...0x0A4D,
|
||||
0x0A59...0x0A5C,
|
||||
0x0A5E,
|
||||
0x0A74,
|
||||
|
||||
// Gujarati
|
||||
0x0A81...0x0A83,
|
||||
0x0A85...0x0A8B,
|
||||
0x0A8D,
|
||||
0x0A8F...0x0A91,
|
||||
0x0A93...0x0AA8,
|
||||
0x0AAA...0x0AB0,
|
||||
0x0AB2...0x0AB3,
|
||||
0x0AB5...0x0AB9,
|
||||
0x0ABD...0x0AC5,
|
||||
0x0AC7...0x0AC9,
|
||||
0x0ACB...0x0ACD,
|
||||
0x0AD0,
|
||||
0x0AE0,
|
||||
|
||||
// Oriya
|
||||
0x0B01...0x0B03,
|
||||
0x0B05...0x0B0C,
|
||||
0x0B0F...0x0B10,
|
||||
0x0B13...0x0B28,
|
||||
0x0B2A...0x0B30,
|
||||
0x0B32...0x0B33,
|
||||
0x0B36...0x0B39,
|
||||
0x0B3E...0x0B43,
|
||||
0x0B47...0x0B48,
|
||||
0x0B4B...0x0B4D,
|
||||
0x0B5C...0x0B5D,
|
||||
0x0B5F...0x0B61,
|
||||
|
||||
// Tamil
|
||||
0x0B82...0x0B83,
|
||||
0x0B85...0x0B8A,
|
||||
0x0B8E...0x0B90,
|
||||
0x0B92...0x0B95,
|
||||
0x0B99...0x0B9A,
|
||||
0x0B9C,
|
||||
0x0B9E...0x0B9F,
|
||||
0x0BA3...0x0BA4,
|
||||
0x0BA8...0x0BAA,
|
||||
0x0BAE...0x0BB5,
|
||||
0x0BB7...0x0BB9,
|
||||
0x0BBE...0x0BC2,
|
||||
0x0BC6...0x0BC8,
|
||||
0x0BCA...0x0BCD,
|
||||
|
||||
// Telugu
|
||||
0x0C01...0x0C03,
|
||||
0x0C05...0x0C0C,
|
||||
0x0C0E...0x0C10,
|
||||
0x0C12...0x0C28,
|
||||
0x0C2A...0x0C33,
|
||||
0x0C35...0x0C39,
|
||||
0x0C3E...0x0C44,
|
||||
0x0C46...0x0C48,
|
||||
0x0C4A...0x0C4D,
|
||||
0x0C60...0x0C61,
|
||||
|
||||
// Kannada
|
||||
0x0C82...0x0C83,
|
||||
0x0C85...0x0C8C,
|
||||
0x0C8E...0x0C90,
|
||||
0x0C92...0x0CA8,
|
||||
0x0CAA...0x0CB3,
|
||||
0x0CB5...0x0CB9,
|
||||
0x0CBE...0x0CC4,
|
||||
0x0CC6...0x0CC8,
|
||||
0x0CCA...0x0CCD,
|
||||
0x0CDE,
|
||||
0x0CE0...0x0CE1,
|
||||
|
||||
// Malayalam
|
||||
0x0D02...0x0D03,
|
||||
0x0D05...0x0D0C,
|
||||
0x0D0E...0x0D10,
|
||||
0x0D12...0x0D28,
|
||||
0x0D2A...0x0D39,
|
||||
0x0D3E...0x0D43,
|
||||
0x0D46...0x0D48,
|
||||
0x0D4A...0x0D4D,
|
||||
0x0D60...0x0D61,
|
||||
|
||||
// Thai (excluding digits 0x0E50...0x0E59; originally 0x0E01...0x0E3A and 0x0E40...0x0E5B
|
||||
0x0E01...0x0E3A,
|
||||
0x0E40...0x0E4F,
|
||||
0x0E5A...0x0E5B,
|
||||
|
||||
// Lao
|
||||
0x0E81...0x0E82,
|
||||
0x0E84,
|
||||
0x0E87...0x0E88,
|
||||
0x0E8A,
|
||||
0x0E8D,
|
||||
0x0E94...0x0E97,
|
||||
0x0E99...0x0E9F,
|
||||
0x0EA1...0x0EA3,
|
||||
0x0EA5,
|
||||
0x0EA7,
|
||||
0x0EAA...0x0EAB,
|
||||
0x0EAD...0x0EAE,
|
||||
0x0EB0...0x0EB9,
|
||||
0x0EBB...0x0EBD,
|
||||
0x0EC0...0x0EC4,
|
||||
0x0EC6,
|
||||
0x0EC8...0x0ECD,
|
||||
0x0EDC...0x0EDD,
|
||||
|
||||
// Tibetan
|
||||
0x0F00,
|
||||
0x0F18...0x0F19,
|
||||
0x0F35,
|
||||
0x0F37,
|
||||
0x0F39,
|
||||
0x0F3E...0x0F47,
|
||||
0x0F49...0x0F69,
|
||||
0x0F71...0x0F84,
|
||||
0x0F86...0x0F8B,
|
||||
0x0F90...0x0F95,
|
||||
0x0F97,
|
||||
0x0F99...0x0FAD,
|
||||
0x0FB1...0x0FB7,
|
||||
0x0FB9,
|
||||
|
||||
// Georgian
|
||||
0x10A0...0x10C5,
|
||||
0x10D0...0x10F6,
|
||||
|
||||
// Hiragana
|
||||
0x3041...0x3093,
|
||||
0x309B...0x309C,
|
||||
|
||||
// Katakana
|
||||
0x30A1...0x30F6,
|
||||
0x30FB...0x30FC,
|
||||
|
||||
// Bopomofo
|
||||
0x3105...0x312C,
|
||||
|
||||
// CJK Unified Ideographs
|
||||
0x4E00...0x9FA5,
|
||||
|
||||
// Hangul
|
||||
0xAC00...0xD7A3,
|
||||
|
||||
// Digits
|
||||
0x0660...0x0669,
|
||||
0x06F0...0x06F9,
|
||||
0x0966...0x096F,
|
||||
0x09E6...0x09EF,
|
||||
0x0A66...0x0A6F,
|
||||
0x0AE6...0x0AEF,
|
||||
0x0B66...0x0B6F,
|
||||
0x0BE7...0x0BEF,
|
||||
0x0C66...0x0C6F,
|
||||
0x0CE6...0x0CEF,
|
||||
0x0D66...0x0D6F,
|
||||
0x0E50...0x0E59,
|
||||
0x0ED0...0x0ED9,
|
||||
0x0F20...0x0F33,
|
||||
|
||||
// Special characters
|
||||
0x00B5,
|
||||
0x00B7,
|
||||
0x02B0...0x02B8,
|
||||
0x02BB,
|
||||
0x02BD...0x02C1,
|
||||
0x02D0...0x02D1,
|
||||
0x02E0...0x02E4,
|
||||
0x037A,
|
||||
0x0559,
|
||||
0x093D,
|
||||
0x0B3D,
|
||||
0x1FBE,
|
||||
0x203F...0x2040,
|
||||
0x2102,
|
||||
0x2107,
|
||||
0x210A...0x2113,
|
||||
0x2115,
|
||||
0x2118...0x211D,
|
||||
0x2124,
|
||||
0x2126,
|
||||
0x2128,
|
||||
0x212A...0x2131,
|
||||
0x2133...0x2138,
|
||||
0x2160...0x2182,
|
||||
0x3005...0x3007,
|
||||
0x3021...0x3029,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// C11 standard Annex D
|
||||
pub fn isC11DisallowedInitialIdChar(codepoint: u21) bool {
|
||||
assert(codepoint > 0x7F);
|
||||
return switch (codepoint) {
|
||||
0x0300...0x036F,
|
||||
0x1DC0...0x1DFF,
|
||||
0x20D0...0x20FF,
|
||||
0xFE20...0xFE2F,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// These are "digit" characters; C99 disallows them as the first
|
||||
/// character of an identifier
|
||||
pub fn isC99DisallowedInitialIDChar(codepoint: u21) bool {
|
||||
assert(codepoint > 0x7F);
|
||||
return switch (codepoint) {
|
||||
0x0660...0x0669,
|
||||
0x06F0...0x06F9,
|
||||
0x0966...0x096F,
|
||||
0x09E6...0x09EF,
|
||||
0x0A66...0x0A6F,
|
||||
0x0AE6...0x0AEF,
|
||||
0x0B66...0x0B6F,
|
||||
0x0BE7...0x0BEF,
|
||||
0x0C66...0x0C6F,
|
||||
0x0CE6...0x0CEF,
|
||||
0x0D66...0x0D6F,
|
||||
0x0E50...0x0E59,
|
||||
0x0ED0...0x0ED9,
|
||||
0x0F20...0x0F33,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isInvisible(codepoint: u21) bool {
|
||||
assert(codepoint > 0x7F);
|
||||
return switch (codepoint) {
|
||||
0x00ad, // SOFT HYPHEN
|
||||
0x200b, // ZERO WIDTH SPACE
|
||||
0x200c, // ZERO WIDTH NON-JOINER
|
||||
0x200d, // ZERO WIDTH JOINER
|
||||
0x2060, // WORD JOINER
|
||||
0x2061, // FUNCTION APPLICATION
|
||||
0x2062, // INVISIBLE TIMES
|
||||
0x2063, // INVISIBLE SEPARATOR
|
||||
0x2064, // INVISIBLE PLUS
|
||||
0xfeff, // ZERO WIDTH NO-BREAK SPACE
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// Checks for identifier characters which resemble non-identifier characters
|
||||
pub fn homoglyph(codepoint: u21) ?u21 {
|
||||
assert(codepoint > 0x7F);
|
||||
return switch (codepoint) {
|
||||
0x01c3 => '!', // LATIN LETTER RETROFLEX CLICK
|
||||
0x037e => ';', // GREEK QUESTION MARK
|
||||
0x2212 => '-', // MINUS SIGN
|
||||
0x2215 => '/', // DIVISION SLASH
|
||||
0x2216 => '\\', // SET MINUS
|
||||
0x2217 => '*', // ASTERISK OPERATOR
|
||||
0x2223 => '|', // DIVIDES
|
||||
0x2227 => '^', // LOGICAL AND
|
||||
0x2236 => ':', // RATIO
|
||||
0x223c => '~', // TILDE OPERATOR
|
||||
0xa789 => ':', // MODIFIER LETTER COLON
|
||||
0xff01 => '!', // FULLWIDTH EXCLAMATION MARK
|
||||
0xff03 => '#', // FULLWIDTH NUMBER SIGN
|
||||
0xff04 => '$', // FULLWIDTH DOLLAR SIGN
|
||||
0xff05 => '%', // FULLWIDTH PERCENT SIGN
|
||||
0xff06 => '&', // FULLWIDTH AMPERSAND
|
||||
0xff08 => '(', // FULLWIDTH LEFT PARENTHESIS
|
||||
0xff09 => ')', // FULLWIDTH RIGHT PARENTHESIS
|
||||
0xff0a => '*', // FULLWIDTH ASTERISK
|
||||
0xff0b => '+', // FULLWIDTH ASTERISK
|
||||
0xff0c => ',', // FULLWIDTH COMMA
|
||||
0xff0d => '-', // FULLWIDTH HYPHEN-MINUS
|
||||
0xff0e => '.', // FULLWIDTH FULL STOP
|
||||
0xff0f => '/', // FULLWIDTH SOLIDUS
|
||||
0xff1a => ':', // FULLWIDTH COLON
|
||||
0xff1b => ';', // FULLWIDTH SEMICOLON
|
||||
0xff1c => '<', // FULLWIDTH LESS-THAN SIGN
|
||||
0xff1d => '=', // FULLWIDTH EQUALS SIGN
|
||||
0xff1e => '>', // FULLWIDTH GREATER-THAN SIGN
|
||||
0xff1f => '?', // FULLWIDTH QUESTION MARK
|
||||
0xff20 => '@', // FULLWIDTH COMMERCIAL AT
|
||||
0xff3b => '[', // FULLWIDTH LEFT SQUARE BRACKET
|
||||
0xff3c => '\\', // FULLWIDTH REVERSE SOLIDUS
|
||||
0xff3d => ']', // FULLWIDTH RIGHT SQUARE BRACKET
|
||||
0xff3e => '^', // FULLWIDTH CIRCUMFLEX ACCENT
|
||||
0xff5b => '{', // FULLWIDTH LEFT CURLY BRACKET
|
||||
0xff5c => '|', // FULLWIDTH VERTICAL LINE
|
||||
0xff5d => '}', // FULLWIDTH RIGHT CURLY BRACKET
|
||||
0xff5e => '~', // FULLWIDTH TILDE
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
298
deps/aro/CharLiteral.zig
vendored
298
deps/aro/CharLiteral.zig
vendored
@ -1,298 +0,0 @@
|
||||
const std = @import("std");
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Type = @import("Type.zig");
|
||||
const Diagnostics = @import("Diagnostics.zig");
|
||||
const Tokenizer = @import("Tokenizer.zig");
|
||||
const mem = std.mem;
|
||||
|
||||
pub const Item = union(enum) {
|
||||
/// decoded escape
|
||||
value: u32,
|
||||
/// Char literal in the source text is not utf8 encoded
|
||||
improperly_encoded: []const u8,
|
||||
/// 1 or more unescaped bytes
|
||||
utf8_text: std.unicode.Utf8View,
|
||||
};
|
||||
|
||||
const CharDiagnostic = struct {
|
||||
tag: Diagnostics.Tag,
|
||||
extra: Diagnostics.Message.Extra,
|
||||
};
|
||||
|
||||
pub const Kind = enum {
|
||||
char,
|
||||
wide,
|
||||
utf_8,
|
||||
utf_16,
|
||||
utf_32,
|
||||
|
||||
pub fn classify(id: Tokenizer.Token.Id) Kind {
|
||||
return switch (id) {
|
||||
.char_literal,
|
||||
.string_literal,
|
||||
=> .char,
|
||||
.char_literal_utf_8,
|
||||
.string_literal_utf_8,
|
||||
=> .utf_8,
|
||||
.char_literal_wide,
|
||||
.string_literal_wide,
|
||||
=> .wide,
|
||||
.char_literal_utf_16,
|
||||
.string_literal_utf_16,
|
||||
=> .utf_16,
|
||||
.char_literal_utf_32,
|
||||
.string_literal_utf_32,
|
||||
=> .utf_32,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
/// Largest unicode codepoint that can be represented by this character kind
|
||||
/// May be smaller than the largest value that can be represented.
|
||||
/// For example u8 char literals may only specify 0-127 via literals or
|
||||
/// character escapes, but may specify up to \xFF via hex escapes.
|
||||
pub fn maxCodepoint(kind: Kind, comp: *const Compilation) u21 {
|
||||
return @intCast(switch (kind) {
|
||||
.char => std.math.maxInt(u7),
|
||||
.wide => @min(0x10FFFF, comp.types.wchar.maxInt(comp)),
|
||||
.utf_8 => std.math.maxInt(u7),
|
||||
.utf_16 => std.math.maxInt(u16),
|
||||
.utf_32 => 0x10FFFF,
|
||||
});
|
||||
}
|
||||
|
||||
/// Largest integer that can be represented by this character kind
|
||||
pub fn maxInt(kind: Kind, comp: *const Compilation) u32 {
|
||||
return @intCast(switch (kind) {
|
||||
.char, .utf_8 => std.math.maxInt(u8),
|
||||
.wide => comp.types.wchar.maxInt(comp),
|
||||
.utf_16 => std.math.maxInt(u16),
|
||||
.utf_32 => std.math.maxInt(u32),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn charLiteralType(kind: Kind, comp: *const Compilation) Type {
|
||||
return switch (kind) {
|
||||
.char => Type.int,
|
||||
.wide => comp.types.wchar,
|
||||
.utf_8 => .{ .specifier = .uchar },
|
||||
.utf_16 => comp.types.uint_least16_t,
|
||||
.utf_32 => comp.types.uint_least32_t,
|
||||
};
|
||||
}
|
||||
|
||||
/// Return the actual contents of the string literal with leading / trailing quotes and
|
||||
/// specifiers removed
|
||||
pub fn contentSlice(kind: Kind, delimited: []const u8) []const u8 {
|
||||
const end = delimited.len - 1; // remove trailing quote
|
||||
return switch (kind) {
|
||||
.char => delimited[1..end],
|
||||
.wide => delimited[2..end],
|
||||
.utf_8 => delimited[3..end],
|
||||
.utf_16 => delimited[2..end],
|
||||
.utf_32 => delimited[2..end],
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Parser = struct {
|
||||
literal: []const u8,
|
||||
i: usize = 0,
|
||||
kind: Kind,
|
||||
/// We only want to issue a max of 1 error per char literal
|
||||
errored: bool = false,
|
||||
errors: std.BoundedArray(CharDiagnostic, 4) = .{},
|
||||
comp: *const Compilation,
|
||||
|
||||
pub fn init(literal: []const u8, kind: Kind, comp: *const Compilation) Parser {
|
||||
return .{
|
||||
.literal = literal,
|
||||
.comp = comp,
|
||||
.kind = kind,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn err(self: *Parser, tag: Diagnostics.Tag, extra: Diagnostics.Message.Extra) void {
|
||||
if (self.errored) return;
|
||||
self.errored = true;
|
||||
self.errors.append(.{ .tag = tag, .extra = extra }) catch {};
|
||||
}
|
||||
|
||||
pub fn warn(self: *Parser, tag: Diagnostics.Tag, extra: Diagnostics.Message.Extra) void {
|
||||
if (self.errored) return;
|
||||
self.errors.append(.{ .tag = tag, .extra = extra }) catch {};
|
||||
}
|
||||
|
||||
pub fn next(self: *Parser) ?Item {
|
||||
if (self.i >= self.literal.len) return null;
|
||||
|
||||
const start = self.i;
|
||||
if (self.literal[start] != '\\') {
|
||||
self.i = mem.indexOfScalarPos(u8, self.literal, start + 1, '\\') orelse self.literal.len;
|
||||
const unescaped_slice = self.literal[start..self.i];
|
||||
|
||||
const view = std.unicode.Utf8View.init(unescaped_slice) catch {
|
||||
if (self.kind != .char) {
|
||||
self.err(.illegal_char_encoding_error, .{ .none = {} });
|
||||
} else {
|
||||
self.warn(.illegal_char_encoding_warning, .{ .none = {} });
|
||||
}
|
||||
return .{ .improperly_encoded = self.literal[start..self.i] };
|
||||
};
|
||||
return .{ .utf8_text = view };
|
||||
}
|
||||
switch (self.literal[start + 1]) {
|
||||
'u', 'U' => return self.parseUnicodeEscape(),
|
||||
else => return self.parseEscapedChar(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parseUnicodeEscape(self: *Parser) ?Item {
|
||||
const start = self.i;
|
||||
|
||||
std.debug.assert(self.literal[self.i] == '\\');
|
||||
|
||||
const kind = self.literal[self.i + 1];
|
||||
std.debug.assert(kind == 'u' or kind == 'U');
|
||||
|
||||
self.i += 2;
|
||||
if (self.i >= self.literal.len or !std.ascii.isHex(self.literal[self.i])) {
|
||||
self.err(.missing_hex_escape, .{ .ascii = @intCast(kind) });
|
||||
return null;
|
||||
}
|
||||
const expected_len: usize = if (kind == 'u') 4 else 8;
|
||||
var overflowed = false;
|
||||
var count: usize = 0;
|
||||
var val: u32 = 0;
|
||||
|
||||
for (self.literal[self.i..], 0..) |c, i| {
|
||||
if (i == expected_len) break;
|
||||
|
||||
const char = std.fmt.charToDigit(c, 16) catch {
|
||||
break;
|
||||
};
|
||||
|
||||
val, const overflow = @shlWithOverflow(val, 4);
|
||||
overflowed = overflowed or overflow != 0;
|
||||
val |= char;
|
||||
count += 1;
|
||||
}
|
||||
self.i += expected_len;
|
||||
|
||||
if (overflowed) {
|
||||
self.err(.escape_sequence_overflow, .{ .unsigned = start });
|
||||
return null;
|
||||
}
|
||||
|
||||
if (count != expected_len) {
|
||||
self.err(.incomplete_universal_character, .{ .none = {} });
|
||||
return null;
|
||||
}
|
||||
|
||||
if (val > std.math.maxInt(u21) or !std.unicode.utf8ValidCodepoint(@intCast(val))) {
|
||||
self.err(.invalid_universal_character, .{ .unsigned = start });
|
||||
return null;
|
||||
}
|
||||
|
||||
if (val > self.kind.maxCodepoint(self.comp)) {
|
||||
self.err(.char_too_large, .{ .none = {} });
|
||||
}
|
||||
|
||||
if (val < 0xA0 and (val != '$' and val != '@' and val != '`')) {
|
||||
const is_error = !self.comp.langopts.standard.atLeast(.c2x);
|
||||
if (val >= 0x20 and val <= 0x7F) {
|
||||
if (is_error) {
|
||||
self.err(.ucn_basic_char_error, .{ .ascii = @intCast(val) });
|
||||
} else {
|
||||
self.warn(.ucn_basic_char_warning, .{ .ascii = @intCast(val) });
|
||||
}
|
||||
} else {
|
||||
if (is_error) {
|
||||
self.err(.ucn_control_char_error, .{ .none = {} });
|
||||
} else {
|
||||
self.warn(.ucn_control_char_warning, .{ .none = {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.warn(.c89_ucn_in_literal, .{ .none = {} });
|
||||
return .{ .value = val };
|
||||
}
|
||||
|
||||
fn parseEscapedChar(self: *Parser) Item {
|
||||
self.i += 1;
|
||||
const c = self.literal[self.i];
|
||||
defer if (c != 'x' and (c < '0' or c > '7')) {
|
||||
self.i += 1;
|
||||
};
|
||||
|
||||
switch (c) {
|
||||
'\n' => unreachable, // removed by line splicing
|
||||
'\r' => unreachable, // removed by line splicing
|
||||
'\'', '\"', '\\', '?' => return .{ .value = c },
|
||||
'n' => return .{ .value = '\n' },
|
||||
'r' => return .{ .value = '\r' },
|
||||
't' => return .{ .value = '\t' },
|
||||
'a' => return .{ .value = 0x07 },
|
||||
'b' => return .{ .value = 0x08 },
|
||||
'e', 'E' => {
|
||||
self.warn(.non_standard_escape_char, .{ .invalid_escape = .{ .char = c, .offset = @intCast(self.i) } });
|
||||
return .{ .value = 0x1B };
|
||||
},
|
||||
'(', '{', '[', '%' => {
|
||||
self.warn(.non_standard_escape_char, .{ .invalid_escape = .{ .char = c, .offset = @intCast(self.i) } });
|
||||
return .{ .value = c };
|
||||
},
|
||||
'f' => return .{ .value = 0x0C },
|
||||
'v' => return .{ .value = 0x0B },
|
||||
'x' => return .{ .value = self.parseNumberEscape(.hex) },
|
||||
'0'...'7' => return .{ .value = self.parseNumberEscape(.octal) },
|
||||
'u', 'U' => unreachable, // handled by parseUnicodeEscape
|
||||
else => {
|
||||
self.warn(.unknown_escape_sequence, .{ .invalid_escape = .{ .char = c, .offset = @intCast(self.i) } });
|
||||
return .{ .value = c };
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn parseNumberEscape(self: *Parser, base: EscapeBase) u32 {
|
||||
var val: u32 = 0;
|
||||
var count: usize = 0;
|
||||
var overflowed = false;
|
||||
defer self.i += count;
|
||||
const slice = switch (base) {
|
||||
.octal => self.literal[self.i..@min(self.literal.len, self.i + 3)], // max 3 chars
|
||||
.hex => blk: {
|
||||
self.i += 1;
|
||||
break :blk self.literal[self.i..]; // skip over 'x'; could have an arbitrary number of chars
|
||||
},
|
||||
};
|
||||
for (slice) |c| {
|
||||
const char = std.fmt.charToDigit(c, @intFromEnum(base)) catch break;
|
||||
val, const overflow = @shlWithOverflow(val, base.log2());
|
||||
if (overflow != 0) overflowed = true;
|
||||
val += char;
|
||||
count += 1;
|
||||
}
|
||||
if (overflowed or val > self.kind.maxInt(self.comp)) {
|
||||
self.err(.escape_sequence_overflow, .{ .unsigned = 0 });
|
||||
}
|
||||
if (count == 0) {
|
||||
std.debug.assert(base == .hex);
|
||||
self.err(.missing_hex_escape, .{ .ascii = 'x' });
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
const EscapeBase = enum(u8) {
|
||||
octal = 8,
|
||||
hex = 16,
|
||||
|
||||
fn log2(base: EscapeBase) u4 {
|
||||
return switch (base) {
|
||||
.octal => 3,
|
||||
.hex => 4,
|
||||
};
|
||||
}
|
||||
};
|
||||
108
deps/aro/Codegen_legacy.zig
vendored
108
deps/aro/Codegen_legacy.zig
vendored
@ -1,108 +0,0 @@
|
||||
const std = @import("std");
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Tree = @import("Tree.zig");
|
||||
const NodeIndex = Tree.NodeIndex;
|
||||
const Object = @import("Object.zig");
|
||||
const x86_64 = @import("codegen/x86_64.zig");
|
||||
|
||||
const Codegen = @This();
|
||||
|
||||
comp: *Compilation,
|
||||
tree: Tree,
|
||||
obj: *Object,
|
||||
node_tag: []const Tree.Tag,
|
||||
node_data: []const Tree.Node.Data,
|
||||
|
||||
pub const Error = Compilation.Error || error{CodegenFailed};
|
||||
|
||||
/// Generate tree to an object file.
|
||||
/// Caller is responsible for flushing and freeing the returned object.
|
||||
pub fn generateTree(comp: *Compilation, tree: Tree) Compilation.Error!*Object {
|
||||
var c = Codegen{
|
||||
.comp = comp,
|
||||
.tree = tree,
|
||||
.obj = try Object.create(comp),
|
||||
.node_tag = tree.nodes.items(.tag),
|
||||
.node_data = tree.nodes.items(.data),
|
||||
};
|
||||
errdefer c.obj.deinit();
|
||||
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
for (tree.root_decls) |decl| {
|
||||
switch (node_tags[@intFromEnum(decl)]) {
|
||||
// these produce no code
|
||||
.static_assert,
|
||||
.typedef,
|
||||
.struct_decl_two,
|
||||
.union_decl_two,
|
||||
.enum_decl_two,
|
||||
.struct_decl,
|
||||
.union_decl,
|
||||
.enum_decl,
|
||||
.struct_forward_decl,
|
||||
.union_forward_decl,
|
||||
.enum_forward_decl,
|
||||
=> {},
|
||||
|
||||
// define symbol
|
||||
.fn_proto,
|
||||
.static_fn_proto,
|
||||
.inline_fn_proto,
|
||||
.inline_static_fn_proto,
|
||||
.extern_var,
|
||||
.threadlocal_extern_var,
|
||||
=> {
|
||||
const name = c.tree.tokSlice(c.node_data[@intFromEnum(decl)].decl.name);
|
||||
_ = try c.obj.declareSymbol(.undefined, name, .Strong, .external, 0, 0);
|
||||
},
|
||||
|
||||
// function definition
|
||||
.fn_def,
|
||||
.static_fn_def,
|
||||
.inline_fn_def,
|
||||
.inline_static_fn_def,
|
||||
=> c.genFn(decl) catch |err| switch (err) {
|
||||
error.FatalError => return error.FatalError,
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.CodegenFailed => continue,
|
||||
},
|
||||
|
||||
.@"var",
|
||||
.static_var,
|
||||
.threadlocal_var,
|
||||
.threadlocal_static_var,
|
||||
.implicit_static_var,
|
||||
=> c.genVar(decl) catch |err| switch (err) {
|
||||
error.FatalError => return error.FatalError,
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.CodegenFailed => continue,
|
||||
},
|
||||
|
||||
// TODO
|
||||
.file_scope_asm => {},
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
return c.obj;
|
||||
}
|
||||
|
||||
fn genFn(c: *Codegen, decl: NodeIndex) Error!void {
|
||||
const section: Object.Section = .func;
|
||||
const data = try c.obj.getSection(section);
|
||||
const start_len = data.items.len;
|
||||
switch (c.comp.target.cpu.arch) {
|
||||
.x86_64 => try x86_64.genFn(c, decl, data),
|
||||
else => unreachable,
|
||||
}
|
||||
const name = c.tree.tokSlice(c.node_data[@intFromEnum(decl)].decl.name);
|
||||
_ = try c.obj.declareSymbol(section, name, .Strong, .func, start_len, data.items.len - start_len);
|
||||
}
|
||||
|
||||
fn genVar(c: *Codegen, decl: NodeIndex) Error!void {
|
||||
switch (c.comp.target.cpu.arch) {
|
||||
.x86_64 => try x86_64.genVar(c, decl),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
2935
deps/aro/Diagnostics.zig
vendored
2935
deps/aro/Diagnostics.zig
vendored
File diff suppressed because it is too large
Load Diff
180
deps/aro/Interner.zig
vendored
180
deps/aro/Interner.zig
vendored
@ -1,180 +0,0 @@
|
||||
const Interner = @This();
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const Value = @import("Value.zig");
|
||||
|
||||
map: std.ArrayHashMapUnmanaged(Key, void, KeyContext, false) = .{},
|
||||
|
||||
const KeyContext = struct {
|
||||
pub fn eql(_: @This(), a: Key, b: Key, _: usize) bool {
|
||||
return b.eql(a);
|
||||
}
|
||||
|
||||
pub fn hash(_: @This(), a: Key) u32 {
|
||||
return a.hash();
|
||||
}
|
||||
};
|
||||
|
||||
pub const Key = union(enum) {
|
||||
int: u16,
|
||||
float: u16,
|
||||
ptr,
|
||||
noreturn,
|
||||
void,
|
||||
func,
|
||||
array: struct {
|
||||
len: u64,
|
||||
child: Ref,
|
||||
},
|
||||
vector: struct {
|
||||
len: u32,
|
||||
child: Ref,
|
||||
},
|
||||
value: Value,
|
||||
record: struct {
|
||||
/// Pointer to user data, value used for hash and equality check.
|
||||
user_ptr: *anyopaque,
|
||||
/// TODO make smaller if Value is made smaller
|
||||
elements: []const Ref,
|
||||
},
|
||||
|
||||
pub fn hash(key: Key) u32 {
|
||||
var hasher = std.hash.Wyhash.init(0);
|
||||
switch (key) {
|
||||
.value => |val| {
|
||||
std.hash.autoHash(&hasher, val.tag);
|
||||
switch (val.tag) {
|
||||
.unavailable => unreachable,
|
||||
.nullptr_t => std.hash.autoHash(&hasher, @as(u64, 0)),
|
||||
.int => std.hash.autoHash(&hasher, val.data.int),
|
||||
.float => std.hash.autoHash(&hasher, @as(u64, @bitCast(val.data.float))),
|
||||
.bytes => std.hash.autoHashStrat(&hasher, val.data.bytes, .Shallow),
|
||||
}
|
||||
},
|
||||
.record => |info| {
|
||||
std.hash.autoHash(&hasher, @intFromPtr(info.user_ptr));
|
||||
},
|
||||
inline else => |info| {
|
||||
std.hash.autoHash(&hasher, info);
|
||||
},
|
||||
}
|
||||
return @truncate(hasher.final());
|
||||
}
|
||||
|
||||
pub fn eql(a: Key, b: Key) bool {
|
||||
const KeyTag = std.meta.Tag(Key);
|
||||
const a_tag: KeyTag = a;
|
||||
const b_tag: KeyTag = b;
|
||||
if (a_tag != b_tag) return false;
|
||||
switch (a) {
|
||||
.value => |a_info| {
|
||||
const b_info = b.value;
|
||||
if (a_info.tag != b_info.tag) return false;
|
||||
switch (a_info.tag) {
|
||||
.unavailable => unreachable,
|
||||
.nullptr_t => return true,
|
||||
.int => return a_info.data.int == b_info.data.int,
|
||||
.float => return a_info.data.float == b_info.data.float,
|
||||
.bytes => return a_info.data.bytes.start == b_info.data.bytes.start and a_info.data.bytes.end == b_info.data.bytes.end,
|
||||
}
|
||||
},
|
||||
.record => |a_info| {
|
||||
return a_info.user_ptr == b.record.user_ptr;
|
||||
},
|
||||
inline else => |a_info, tag| {
|
||||
const b_info = @field(b, @tagName(tag));
|
||||
return std.meta.eql(a_info, b_info);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn toRef(key: Key) ?Ref {
|
||||
switch (key) {
|
||||
.int => |bits| switch (bits) {
|
||||
1 => return .i1,
|
||||
8 => return .i8,
|
||||
16 => return .i16,
|
||||
32 => return .i32,
|
||||
64 => return .i64,
|
||||
128 => return .i128,
|
||||
else => {},
|
||||
},
|
||||
.float => |bits| switch (bits) {
|
||||
16 => return .f16,
|
||||
32 => return .f32,
|
||||
64 => return .f64,
|
||||
80 => return .f80,
|
||||
128 => return .f128,
|
||||
else => unreachable,
|
||||
},
|
||||
.ptr => return .ptr,
|
||||
.func => return .func,
|
||||
.noreturn => return .noreturn,
|
||||
.void => return .void,
|
||||
else => {},
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Ref = enum(u32) {
|
||||
const max = std.math.maxInt(u32);
|
||||
|
||||
ptr = max - 0,
|
||||
noreturn = max - 1,
|
||||
void = max - 2,
|
||||
i1 = max - 3,
|
||||
i8 = max - 4,
|
||||
i16 = max - 5,
|
||||
i32 = max - 6,
|
||||
i64 = max - 7,
|
||||
i128 = max - 8,
|
||||
f16 = max - 9,
|
||||
f32 = max - 10,
|
||||
f64 = max - 11,
|
||||
f80 = max - 12,
|
||||
f128 = max - 13,
|
||||
func = max - 14,
|
||||
_,
|
||||
};
|
||||
|
||||
pub fn deinit(ip: *Interner, gpa: Allocator) void {
|
||||
ip.map.deinit(gpa);
|
||||
}
|
||||
|
||||
pub fn put(ip: *Interner, gpa: Allocator, key: Key) !Ref {
|
||||
if (key.toRef()) |some| return some;
|
||||
const gop = try ip.map.getOrPut(gpa, key);
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
pub fn has(ip: *Interner, key: Key) ?Ref {
|
||||
if (key.toRef()) |some| return some;
|
||||
if (ip.map.getIndex(key)) |index| {
|
||||
return @enumFromInt(index);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn get(ip: Interner, ref: Ref) Key {
|
||||
switch (ref) {
|
||||
.ptr => return .ptr,
|
||||
.func => return .func,
|
||||
.noreturn => return .noreturn,
|
||||
.void => return .void,
|
||||
.i1 => return .{ .int = 1 },
|
||||
.i8 => return .{ .int = 8 },
|
||||
.i16 => return .{ .int = 16 },
|
||||
.i32 => return .{ .int = 32 },
|
||||
.i64 => return .{ .int = 64 },
|
||||
.i128 => return .{ .int = 128 },
|
||||
.f16 => return .{ .float = 16 },
|
||||
.f32 => return .{ .float = 32 },
|
||||
.f64 => return .{ .float = 64 },
|
||||
.f80 => return .{ .float = 80 },
|
||||
.f128 => return .{ .float = 128 },
|
||||
else => {},
|
||||
}
|
||||
return ip.map.keys()[@intFromEnum(ref)];
|
||||
}
|
||||
3
deps/aro/README.md
vendored
3
deps/aro/README.md
vendored
@ -1,4 +1,7 @@
|
||||
<img src="https://aro.vexu.eu/aro-logo.svg" alt="Aro" width="120px"/>
|
||||
|
||||
# Aro
|
||||
|
||||
A C compiler with the goal of providing fast compilation and low memory usage with good diagnostics.
|
||||
|
||||
Aro is included as an alternative C frontend in the [Zig compiler](https://github.com/ziglang/zig)
|
||||
|
||||
633
deps/aro/Value.zig
vendored
633
deps/aro/Value.zig
vendored
@ -1,633 +0,0 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Type = @import("Type.zig");
|
||||
|
||||
const Value = @This();
|
||||
|
||||
pub const ByteRange = struct {
|
||||
start: u32,
|
||||
end: u32,
|
||||
|
||||
pub fn len(self: ByteRange) u32 {
|
||||
return self.end - self.start;
|
||||
}
|
||||
|
||||
pub fn trim(self: ByteRange, amount: u32) ByteRange {
|
||||
std.debug.assert(self.start <= self.end - amount);
|
||||
return .{ .start = self.start, .end = self.end - amount };
|
||||
}
|
||||
|
||||
pub fn slice(self: ByteRange, all_bytes: []const u8, comptime size: Compilation.CharUnitSize) []const size.Type() {
|
||||
switch (size) {
|
||||
inline else => |sz| {
|
||||
const aligned: []align(@alignOf(sz.Type())) const u8 = @alignCast(all_bytes[self.start..self.end]);
|
||||
return std.mem.bytesAsSlice(sz.Type(), aligned);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dumpString(range: ByteRange, ty: Type, comp: *const Compilation, strings: []const u8, w: anytype) !void {
|
||||
const size: Compilation.CharUnitSize = @enumFromInt(ty.elemType().sizeof(comp).?);
|
||||
const without_null = range.trim(@intFromEnum(size));
|
||||
switch (size) {
|
||||
inline .@"1", .@"2" => |sz| {
|
||||
const data_slice = without_null.slice(strings, sz);
|
||||
const formatter = if (sz == .@"1") std.zig.fmtEscapes(data_slice) else std.unicode.fmtUtf16le(data_slice);
|
||||
try w.print("\"{}\"", .{formatter});
|
||||
},
|
||||
.@"4" => {
|
||||
try w.writeByte('"');
|
||||
const data_slice = without_null.slice(strings, .@"4");
|
||||
var buf: [4]u8 = undefined;
|
||||
for (data_slice) |item| {
|
||||
if (item <= std.math.maxInt(u21) and std.unicode.utf8ValidCodepoint(@intCast(item))) {
|
||||
const codepoint: u21 = @intCast(item);
|
||||
const written = std.unicode.utf8Encode(codepoint, &buf) catch unreachable;
|
||||
try w.print("{s}", .{buf[0..written]});
|
||||
} else {
|
||||
try w.print("\\x{x}", .{item});
|
||||
}
|
||||
}
|
||||
try w.writeByte('"');
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tag: Tag = .unavailable,
|
||||
data: union {
|
||||
none: void,
|
||||
int: u64,
|
||||
float: f64,
|
||||
bytes: ByteRange,
|
||||
} = .{ .none = {} },
|
||||
|
||||
const Tag = enum {
|
||||
unavailable,
|
||||
nullptr_t,
|
||||
/// int is used to store integer, boolean and pointer values
|
||||
int,
|
||||
float,
|
||||
bytes,
|
||||
};
|
||||
|
||||
pub fn zero(v: Value) Value {
|
||||
return switch (v.tag) {
|
||||
.int => int(0),
|
||||
.float => float(0),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn one(v: Value) Value {
|
||||
return switch (v.tag) {
|
||||
.int => int(1),
|
||||
.float => float(1),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn int(v: anytype) Value {
|
||||
if (@TypeOf(v) == comptime_int or @typeInfo(@TypeOf(v)).Int.signedness == .unsigned)
|
||||
return .{ .tag = .int, .data = .{ .int = v } }
|
||||
else
|
||||
return .{ .tag = .int, .data = .{ .int = @bitCast(@as(i64, v)) } };
|
||||
}
|
||||
|
||||
pub fn float(v: anytype) Value {
|
||||
return .{ .tag = .float, .data = .{ .float = v } };
|
||||
}
|
||||
|
||||
pub fn bytes(start: u32, end: u32) Value {
|
||||
return .{ .tag = .bytes, .data = .{ .bytes = .{ .start = start, .end = end } } };
|
||||
}
|
||||
|
||||
pub fn signExtend(v: Value, old_ty: Type, comp: *Compilation) i64 {
|
||||
const size = old_ty.sizeof(comp).?;
|
||||
return switch (size) {
|
||||
1 => v.getInt(i8),
|
||||
2 => v.getInt(i16),
|
||||
4 => v.getInt(i32),
|
||||
8 => v.getInt(i64),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
/// Number of bits needed to hold `v` which is of type `ty`.
|
||||
/// Asserts that `v` is not negative
|
||||
pub fn minUnsignedBits(v: Value, ty: Type, comp: *const Compilation) usize {
|
||||
assert(v.compare(.gte, Value.int(0), ty, comp));
|
||||
return switch (ty.sizeof(comp).?) {
|
||||
1 => 8 - @clz(v.getInt(u8)),
|
||||
2 => 16 - @clz(v.getInt(u16)),
|
||||
4 => 32 - @clz(v.getInt(u32)),
|
||||
8 => 64 - @clz(v.getInt(u64)),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
test "minUnsignedBits" {
|
||||
const Test = struct {
|
||||
fn checkIntBits(comp: *const Compilation, specifier: Type.Specifier, v: u64, expected: usize) !void {
|
||||
const val = Value.int(v);
|
||||
try std.testing.expectEqual(expected, val.minUnsignedBits(.{ .specifier = specifier }, comp));
|
||||
}
|
||||
};
|
||||
|
||||
var comp = Compilation.init(std.testing.allocator);
|
||||
defer comp.deinit();
|
||||
comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget();
|
||||
|
||||
try Test.checkIntBits(&comp, .int, 0, 0);
|
||||
try Test.checkIntBits(&comp, .int, 1, 1);
|
||||
try Test.checkIntBits(&comp, .int, 2, 2);
|
||||
try Test.checkIntBits(&comp, .int, std.math.maxInt(i8), 7);
|
||||
try Test.checkIntBits(&comp, .int, std.math.maxInt(u8), 8);
|
||||
try Test.checkIntBits(&comp, .int, std.math.maxInt(i16), 15);
|
||||
try Test.checkIntBits(&comp, .int, std.math.maxInt(u16), 16);
|
||||
try Test.checkIntBits(&comp, .int, std.math.maxInt(i32), 31);
|
||||
try Test.checkIntBits(&comp, .uint, std.math.maxInt(u32), 32);
|
||||
try Test.checkIntBits(&comp, .long, std.math.maxInt(i64), 63);
|
||||
try Test.checkIntBits(&comp, .ulong, std.math.maxInt(u64), 64);
|
||||
try Test.checkIntBits(&comp, .long_long, std.math.maxInt(i64), 63);
|
||||
try Test.checkIntBits(&comp, .ulong_long, std.math.maxInt(u64), 64);
|
||||
}
|
||||
|
||||
/// Minimum number of bits needed to represent `v` in 2's complement notation
|
||||
/// Asserts that `v` is negative.
|
||||
pub fn minSignedBits(v: Value, ty: Type, comp: *const Compilation) usize {
|
||||
assert(v.compare(.lt, Value.int(0), ty, comp));
|
||||
return switch (ty.sizeof(comp).?) {
|
||||
1 => 8 - @clz(~v.getInt(u8)) + 1,
|
||||
2 => 16 - @clz(~v.getInt(u16)) + 1,
|
||||
4 => 32 - @clz(~v.getInt(u32)) + 1,
|
||||
8 => 64 - @clz(~v.getInt(u64)) + 1,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
test "minSignedBits" {
|
||||
const Test = struct {
|
||||
fn checkIntBits(comp: *const Compilation, specifier: Type.Specifier, v: i64, expected: usize) !void {
|
||||
const val = Value.int(v);
|
||||
try std.testing.expectEqual(expected, val.minSignedBits(.{ .specifier = specifier }, comp));
|
||||
}
|
||||
};
|
||||
|
||||
var comp = Compilation.init(std.testing.allocator);
|
||||
defer comp.deinit();
|
||||
comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget();
|
||||
|
||||
for ([_]Type.Specifier{ .int, .long, .long_long }) |specifier| {
|
||||
try Test.checkIntBits(&comp, specifier, -1, 1);
|
||||
try Test.checkIntBits(&comp, specifier, -2, 2);
|
||||
try Test.checkIntBits(&comp, specifier, -10, 5);
|
||||
try Test.checkIntBits(&comp, specifier, -101, 8);
|
||||
|
||||
try Test.checkIntBits(&comp, specifier, std.math.minInt(i8), 8);
|
||||
try Test.checkIntBits(&comp, specifier, std.math.minInt(i16), 16);
|
||||
try Test.checkIntBits(&comp, specifier, std.math.minInt(i32), 32);
|
||||
}
|
||||
|
||||
try Test.checkIntBits(&comp, .long, std.math.minInt(i64), 64);
|
||||
try Test.checkIntBits(&comp, .long_long, std.math.minInt(i64), 64);
|
||||
}
|
||||
|
||||
pub const FloatToIntChangeKind = enum {
|
||||
/// value did not change
|
||||
none,
|
||||
/// floating point number too small or large for destination integer type
|
||||
out_of_range,
|
||||
/// tried to convert a NaN or Infinity
|
||||
overflow,
|
||||
/// fractional value was converted to zero
|
||||
nonzero_to_zero,
|
||||
/// fractional part truncated
|
||||
value_changed,
|
||||
};
|
||||
|
||||
fn floatToIntExtra(comptime FloatTy: type, int_ty_signedness: std.builtin.Signedness, int_ty_size: u16, v: *Value) FloatToIntChangeKind {
|
||||
const float_val = v.getFloat(FloatTy);
|
||||
const was_zero = float_val == 0;
|
||||
const had_fraction = std.math.modf(float_val).fpart != 0;
|
||||
|
||||
switch (int_ty_signedness) {
|
||||
inline else => |signedness| switch (int_ty_size) {
|
||||
inline 1, 2, 4, 8 => |bytecount| {
|
||||
const IntTy = std.meta.Int(signedness, bytecount * 8);
|
||||
|
||||
const intVal = std.math.lossyCast(IntTy, float_val);
|
||||
v.* = int(intVal);
|
||||
if (!was_zero and v.isZero()) return .nonzero_to_zero;
|
||||
if (float_val <= std.math.minInt(IntTy) or float_val >= std.math.maxInt(IntTy)) return .out_of_range;
|
||||
if (had_fraction) return .value_changed;
|
||||
return .none;
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the stored value from a float to an integer.
|
||||
/// `.unavailable` value remains unchanged.
|
||||
pub fn floatToInt(v: *Value, old_ty: Type, new_ty: Type, comp: *Compilation) FloatToIntChangeKind {
|
||||
assert(old_ty.isFloat());
|
||||
if (v.tag == .unavailable) return .none;
|
||||
if (new_ty.is(.bool)) {
|
||||
const was_zero = v.isZero();
|
||||
const was_one = v.getFloat(f64) == 1.0;
|
||||
v.toBool();
|
||||
if (was_zero or was_one) return .none;
|
||||
return .value_changed;
|
||||
} else if (new_ty.isUnsignedInt(comp) and v.data.float < 0) {
|
||||
v.* = int(0);
|
||||
return .out_of_range;
|
||||
} else if (!std.math.isFinite(v.data.float)) {
|
||||
v.tag = .unavailable;
|
||||
return .overflow;
|
||||
}
|
||||
const old_size = old_ty.sizeof(comp).?;
|
||||
const new_size: u16 = @intCast(new_ty.sizeof(comp).?);
|
||||
if (new_ty.isUnsignedInt(comp)) switch (old_size) {
|
||||
1 => unreachable, // promoted to int
|
||||
2 => unreachable, // promoted to int
|
||||
4 => return floatToIntExtra(f32, .unsigned, new_size, v),
|
||||
8 => return floatToIntExtra(f64, .unsigned, new_size, v),
|
||||
else => unreachable,
|
||||
} else switch (old_size) {
|
||||
1 => unreachable, // promoted to int
|
||||
2 => unreachable, // promoted to int
|
||||
4 => return floatToIntExtra(f32, .signed, new_size, v),
|
||||
8 => return floatToIntExtra(f64, .signed, new_size, v),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the stored value from an integer to a float.
|
||||
/// `.unavailable` value remains unchanged.
|
||||
pub fn intToFloat(v: *Value, old_ty: Type, new_ty: Type, comp: *Compilation) void {
|
||||
assert(old_ty.isInt());
|
||||
if (v.tag == .unavailable) return;
|
||||
if (!new_ty.isReal() or new_ty.sizeof(comp).? > 8) {
|
||||
v.tag = .unavailable;
|
||||
} else if (old_ty.isUnsignedInt(comp)) {
|
||||
v.* = float(@as(f64, @floatFromInt(v.data.int)));
|
||||
} else {
|
||||
v.* = float(@as(f64, @floatFromInt(@as(i64, @bitCast(v.data.int)))));
|
||||
}
|
||||
}
|
||||
|
||||
/// Truncates or extends bits based on type.
|
||||
/// old_ty is only used for size.
|
||||
pub fn intCast(v: *Value, old_ty: Type, new_ty: Type, comp: *Compilation) void {
|
||||
// assert(old_ty.isInt() and new_ty.isInt());
|
||||
if (v.tag == .unavailable) return;
|
||||
if (new_ty.is(.bool)) return v.toBool();
|
||||
if (!old_ty.isUnsignedInt(comp)) {
|
||||
const size = new_ty.sizeof(comp).?;
|
||||
switch (size) {
|
||||
1 => v.* = int(@as(u8, @truncate(@as(u64, @bitCast(v.signExtend(old_ty, comp)))))),
|
||||
2 => v.* = int(@as(u16, @truncate(@as(u64, @bitCast(v.signExtend(old_ty, comp)))))),
|
||||
4 => v.* = int(@as(u32, @truncate(@as(u64, @bitCast(v.signExtend(old_ty, comp)))))),
|
||||
8 => return,
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the stored value from an integer to a float.
|
||||
/// `.unavailable` value remains unchanged.
|
||||
pub fn floatCast(v: *Value, old_ty: Type, new_ty: Type, comp: *Compilation) void {
|
||||
assert(old_ty.isFloat() and new_ty.isFloat());
|
||||
if (v.tag == .unavailable) return;
|
||||
const size = new_ty.sizeof(comp).?;
|
||||
if (!new_ty.isReal() or size > 8) {
|
||||
v.tag = .unavailable;
|
||||
} else if (size == 32) {
|
||||
v.* = float(@as(f32, @floatCast(v.data.float)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Truncates data.int to one bit
|
||||
pub fn toBool(v: *Value) void {
|
||||
if (v.tag == .unavailable) return;
|
||||
const res = v.getBool();
|
||||
v.* = int(@intFromBool(res));
|
||||
}
|
||||
|
||||
pub fn isZero(v: Value) bool {
|
||||
return switch (v.tag) {
|
||||
.unavailable => false,
|
||||
.nullptr_t => false,
|
||||
.int => v.data.int == 0,
|
||||
.float => v.data.float == 0,
|
||||
.bytes => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getBool(v: Value) bool {
|
||||
return switch (v.tag) {
|
||||
.unavailable => unreachable,
|
||||
.nullptr_t => false,
|
||||
.int => v.data.int != 0,
|
||||
.float => v.data.float != 0,
|
||||
.bytes => true,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getInt(v: Value, comptime T: type) T {
|
||||
if (T == u64) return v.data.int;
|
||||
return if (@typeInfo(T).Int.signedness == .unsigned)
|
||||
@truncate(v.data.int)
|
||||
else
|
||||
@truncate(@as(i64, @bitCast(v.data.int)));
|
||||
}
|
||||
|
||||
pub fn getFloat(v: Value, comptime T: type) T {
|
||||
if (T == f64) return v.data.float;
|
||||
return @floatCast(v.data.float);
|
||||
}
|
||||
|
||||
const bin_overflow = struct {
|
||||
inline fn addInt(comptime T: type, out: *Value, a: Value, b: Value) bool {
|
||||
const a_val = a.getInt(T);
|
||||
const b_val = b.getInt(T);
|
||||
const sum, const overflowed = @addWithOverflow(a_val, b_val);
|
||||
out.* = int(sum);
|
||||
return overflowed != 0;
|
||||
}
|
||||
inline fn addFloat(comptime T: type, aa: Value, bb: Value) Value {
|
||||
const a_val = aa.getFloat(T);
|
||||
const b_val = bb.getFloat(T);
|
||||
return float(a_val + b_val);
|
||||
}
|
||||
|
||||
inline fn subInt(comptime T: type, out: *Value, a: Value, b: Value) bool {
|
||||
const a_val = a.getInt(T);
|
||||
const b_val = b.getInt(T);
|
||||
const difference, const overflowed = @subWithOverflow(a_val, b_val);
|
||||
out.* = int(difference);
|
||||
return overflowed != 0;
|
||||
}
|
||||
inline fn subFloat(comptime T: type, aa: Value, bb: Value) Value {
|
||||
const a_val = aa.getFloat(T);
|
||||
const b_val = bb.getFloat(T);
|
||||
return float(a_val - b_val);
|
||||
}
|
||||
|
||||
inline fn mulInt(comptime T: type, out: *Value, a: Value, b: Value) bool {
|
||||
const a_val = a.getInt(T);
|
||||
const b_val = b.getInt(T);
|
||||
const product, const overflowed = @mulWithOverflow(a_val, b_val);
|
||||
out.* = int(product);
|
||||
return overflowed != 0;
|
||||
}
|
||||
inline fn mulFloat(comptime T: type, aa: Value, bb: Value) Value {
|
||||
const a_val = aa.getFloat(T);
|
||||
const b_val = bb.getFloat(T);
|
||||
return float(a_val * b_val);
|
||||
}
|
||||
|
||||
const FT = fn (*Value, Value, Value, Type, *Compilation) bool;
|
||||
fn getOp(comptime intFunc: anytype, comptime floatFunc: anytype) FT {
|
||||
return struct {
|
||||
fn op(res: *Value, a: Value, b: Value, ty: Type, comp: *Compilation) bool {
|
||||
const size = ty.sizeof(comp).?;
|
||||
if (@TypeOf(floatFunc) != @TypeOf(null) and ty.isFloat()) {
|
||||
res.* = switch (size) {
|
||||
4 => floatFunc(f32, a, b),
|
||||
8 => floatFunc(f64, a, b),
|
||||
else => unreachable,
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ty.isUnsignedInt(comp)) switch (size) {
|
||||
1 => return intFunc(u8, res, a, b),
|
||||
2 => return intFunc(u16, res, a, b),
|
||||
4 => return intFunc(u32, res, a, b),
|
||||
8 => return intFunc(u64, res, a, b),
|
||||
else => unreachable,
|
||||
} else switch (size) {
|
||||
1 => return intFunc(u8, res, a, b),
|
||||
2 => return intFunc(u16, res, a, b),
|
||||
4 => return intFunc(i32, res, a, b),
|
||||
8 => return intFunc(i64, res, a, b),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}.op;
|
||||
}
|
||||
};
|
||||
|
||||
pub const add = bin_overflow.getOp(bin_overflow.addInt, bin_overflow.addFloat);
|
||||
pub const sub = bin_overflow.getOp(bin_overflow.subInt, bin_overflow.subFloat);
|
||||
pub const mul = bin_overflow.getOp(bin_overflow.mulInt, bin_overflow.mulFloat);
|
||||
|
||||
const bin_ops = struct {
|
||||
inline fn divInt(comptime T: type, aa: Value, bb: Value) Value {
|
||||
const a_val = aa.getInt(T);
|
||||
const b_val = bb.getInt(T);
|
||||
return int(@divTrunc(a_val, b_val));
|
||||
}
|
||||
inline fn divFloat(comptime T: type, aa: Value, bb: Value) Value {
|
||||
const a_val = aa.getFloat(T);
|
||||
const b_val = bb.getFloat(T);
|
||||
return float(a_val / b_val);
|
||||
}
|
||||
|
||||
inline fn remInt(comptime T: type, a: Value, b: Value) Value {
|
||||
const a_val = a.getInt(T);
|
||||
const b_val = b.getInt(T);
|
||||
|
||||
if (@typeInfo(T).Int.signedness == .signed) {
|
||||
if (a_val == std.math.minInt(T) and b_val == -1) {
|
||||
return Value{ .tag = .unavailable, .data = .{ .none = {} } };
|
||||
} else {
|
||||
if (b_val > 0) return int(@rem(a_val, b_val));
|
||||
return int(a_val - @divTrunc(a_val, b_val) * b_val);
|
||||
}
|
||||
} else {
|
||||
return int(a_val % b_val);
|
||||
}
|
||||
}
|
||||
|
||||
inline fn orInt(comptime T: type, a: Value, b: Value) Value {
|
||||
const a_val = a.getInt(T);
|
||||
const b_val = b.getInt(T);
|
||||
return int(a_val | b_val);
|
||||
}
|
||||
inline fn xorInt(comptime T: type, a: Value, b: Value) Value {
|
||||
const a_val = a.getInt(T);
|
||||
const b_val = b.getInt(T);
|
||||
return int(a_val ^ b_val);
|
||||
}
|
||||
inline fn andInt(comptime T: type, a: Value, b: Value) Value {
|
||||
const a_val = a.getInt(T);
|
||||
const b_val = b.getInt(T);
|
||||
return int(a_val & b_val);
|
||||
}
|
||||
|
||||
inline fn shl(comptime T: type, a: Value, b: Value) Value {
|
||||
const ShiftT = std.math.Log2Int(T);
|
||||
const info = @typeInfo(T).Int;
|
||||
const UT = std.meta.Int(.unsigned, info.bits);
|
||||
const b_val = b.getInt(T);
|
||||
|
||||
if (b_val > std.math.maxInt(ShiftT)) {
|
||||
return if (info.signedness == .unsigned)
|
||||
int(@as(UT, std.math.maxInt(UT)))
|
||||
else
|
||||
int(@as(T, std.math.minInt(T)));
|
||||
}
|
||||
const amt: ShiftT = @truncate(@as(UT, @bitCast(b_val)));
|
||||
const a_val = a.getInt(T);
|
||||
return int(a_val << amt);
|
||||
}
|
||||
inline fn shr(comptime T: type, a: Value, b: Value) Value {
|
||||
const ShiftT = std.math.Log2Int(T);
|
||||
const UT = std.meta.Int(.unsigned, @typeInfo(T).Int.bits);
|
||||
|
||||
const b_val = b.getInt(T);
|
||||
if (b_val > std.math.maxInt(ShiftT)) return Value.int(0);
|
||||
|
||||
const amt: ShiftT = @truncate(@as(UT, @intCast(b_val)));
|
||||
const a_val = a.getInt(T);
|
||||
return int(a_val >> amt);
|
||||
}
|
||||
|
||||
const FT = fn (Value, Value, Type, *Compilation) Value;
|
||||
fn getOp(comptime intFunc: anytype, comptime floatFunc: anytype) FT {
|
||||
return struct {
|
||||
fn op(a: Value, b: Value, ty: Type, comp: *Compilation) Value {
|
||||
const size = ty.sizeof(comp).?;
|
||||
if (@TypeOf(floatFunc) != @TypeOf(null) and ty.isFloat()) {
|
||||
switch (size) {
|
||||
4 => return floatFunc(f32, a, b),
|
||||
8 => return floatFunc(f64, a, b),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
if (ty.isUnsignedInt(comp)) switch (size) {
|
||||
1 => unreachable, // promoted to int
|
||||
2 => unreachable, // promoted to int
|
||||
4 => return intFunc(u32, a, b),
|
||||
8 => return intFunc(u64, a, b),
|
||||
else => unreachable,
|
||||
} else switch (size) {
|
||||
1 => unreachable, // promoted to int
|
||||
2 => unreachable, // promoted to int
|
||||
4 => return intFunc(i32, a, b),
|
||||
8 => return intFunc(i64, a, b),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}.op;
|
||||
}
|
||||
};
|
||||
|
||||
/// caller guarantees rhs != 0
|
||||
pub const div = bin_ops.getOp(bin_ops.divInt, bin_ops.divFloat);
|
||||
/// caller guarantees rhs != 0
|
||||
/// caller guarantees lhs != std.math.minInt(T) OR rhs != -1
|
||||
pub const rem = bin_ops.getOp(bin_ops.remInt, null);
|
||||
|
||||
pub const bitOr = bin_ops.getOp(bin_ops.orInt, null);
|
||||
pub const bitXor = bin_ops.getOp(bin_ops.xorInt, null);
|
||||
pub const bitAnd = bin_ops.getOp(bin_ops.andInt, null);
|
||||
|
||||
pub const shl = bin_ops.getOp(bin_ops.shl, null);
|
||||
pub const shr = bin_ops.getOp(bin_ops.shr, null);
|
||||
|
||||
pub fn bitNot(v: Value, ty: Type, comp: *Compilation) Value {
|
||||
const size = ty.sizeof(comp).?;
|
||||
var out: Value = undefined;
|
||||
if (ty.isUnsignedInt(comp)) switch (size) {
|
||||
1 => unreachable, // promoted to int
|
||||
2 => unreachable, // promoted to int
|
||||
4 => out = int(~v.getInt(u32)),
|
||||
8 => out = int(~v.getInt(u64)),
|
||||
else => unreachable,
|
||||
} else switch (size) {
|
||||
1 => unreachable, // promoted to int
|
||||
2 => unreachable, // promoted to int
|
||||
4 => out = int(~v.getInt(i32)),
|
||||
8 => out = int(~v.getInt(i64)),
|
||||
else => unreachable,
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
pub fn compare(a: Value, op: std.math.CompareOperator, b: Value, ty: Type, comp: *const Compilation) bool {
|
||||
assert(a.tag == b.tag);
|
||||
if (a.tag == .nullptr_t) {
|
||||
return switch (op) {
|
||||
.eq => true,
|
||||
.neq => false,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
const S = struct {
|
||||
inline fn doICompare(comptime T: type, aa: Value, opp: std.math.CompareOperator, bb: Value) bool {
|
||||
const a_val = aa.getInt(T);
|
||||
const b_val = bb.getInt(T);
|
||||
return std.math.compare(a_val, opp, b_val);
|
||||
}
|
||||
inline fn doFCompare(comptime T: type, aa: Value, opp: std.math.CompareOperator, bb: Value) bool {
|
||||
const a_val = aa.getFloat(T);
|
||||
const b_val = bb.getFloat(T);
|
||||
return std.math.compare(a_val, opp, b_val);
|
||||
}
|
||||
};
|
||||
const size = ty.sizeof(comp).?;
|
||||
switch (a.tag) {
|
||||
.unavailable => return true,
|
||||
.int => if (ty.isUnsignedInt(comp)) switch (size) {
|
||||
1 => return S.doICompare(u8, a, op, b),
|
||||
2 => return S.doICompare(u16, a, op, b),
|
||||
4 => return S.doICompare(u32, a, op, b),
|
||||
8 => return S.doICompare(u64, a, op, b),
|
||||
else => unreachable,
|
||||
} else switch (size) {
|
||||
1 => return S.doICompare(i8, a, op, b),
|
||||
2 => return S.doICompare(i16, a, op, b),
|
||||
4 => return S.doICompare(i32, a, op, b),
|
||||
8 => return S.doICompare(i64, a, op, b),
|
||||
else => unreachable,
|
||||
},
|
||||
.float => switch (size) {
|
||||
4 => return S.doFCompare(f32, a, op, b),
|
||||
8 => return S.doFCompare(f64, a, op, b),
|
||||
else => unreachable,
|
||||
},
|
||||
else => @panic("TODO"),
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn hash(v: Value) u64 {
|
||||
switch (v.tag) {
|
||||
.unavailable => unreachable,
|
||||
.int => return std.hash.Wyhash.hash(0, std.mem.asBytes(&v.data.int)),
|
||||
else => @panic("TODO"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump(v: Value, ty: Type, comp: *Compilation, strings: []const u8, w: anytype) !void {
|
||||
switch (v.tag) {
|
||||
.unavailable => try w.writeAll("unavailable"),
|
||||
.int => if (ty.is(.bool) and comp.langopts.standard.atLeast(.c2x)) {
|
||||
try w.print("{s}", .{if (v.isZero()) "false" else "true"});
|
||||
} else if (ty.isUnsignedInt(comp)) {
|
||||
try w.print("{d}", .{v.data.int});
|
||||
} else {
|
||||
try w.print("{d}", .{v.signExtend(ty, comp)});
|
||||
},
|
||||
.bytes => try v.data.bytes.dumpString(ty, comp, strings, w),
|
||||
// std.fmt does @as instead of @floatCast
|
||||
.float => try w.print("{d}", .{@as(f64, @floatCast(v.data.float))}),
|
||||
else => try w.print("({s})", .{@tagName(v.tag)}),
|
||||
}
|
||||
}
|
||||
38
deps/aro/aro.zig
vendored
Normal file
38
deps/aro/aro.zig
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
pub const CodeGen = @import("aro/CodeGen.zig");
|
||||
pub const Compilation = @import("aro/Compilation.zig");
|
||||
pub const Diagnostics = @import("aro/Diagnostics.zig");
|
||||
pub const Driver = @import("aro/Driver.zig");
|
||||
pub const Parser = @import("aro/Parser.zig");
|
||||
pub const Preprocessor = @import("aro/Preprocessor.zig");
|
||||
pub const Source = @import("aro/Source.zig");
|
||||
pub const Tokenizer = @import("aro/Tokenizer.zig");
|
||||
pub const Toolchain = @import("aro/Toolchain.zig");
|
||||
pub const Tree = @import("aro/Tree.zig");
|
||||
pub const Type = @import("aro/Type.zig");
|
||||
pub const TypeMapper = @import("aro/StringInterner.zig").TypeMapper;
|
||||
pub const target_util = @import("aro/target.zig");
|
||||
pub const Value = @import("aro/Value.zig");
|
||||
|
||||
const backend = @import("backend");
|
||||
pub const Interner = backend.Interner;
|
||||
pub const Ir = backend.Ir;
|
||||
pub const Object = backend.Object;
|
||||
pub const CallingConvention = backend.CallingConvention;
|
||||
|
||||
pub const version_str = backend.version_str;
|
||||
pub const version = backend.version;
|
||||
|
||||
test {
|
||||
_ = @import("aro/Builtins.zig");
|
||||
_ = @import("aro/char_info.zig");
|
||||
_ = @import("aro/Compilation.zig");
|
||||
_ = @import("aro/Driver/Distro.zig");
|
||||
_ = @import("aro/Driver/Filesystem.zig");
|
||||
_ = @import("aro/Driver/GCCVersion.zig");
|
||||
_ = @import("aro/InitList.zig");
|
||||
_ = @import("aro/Preprocessor.zig");
|
||||
_ = @import("aro/target.zig");
|
||||
_ = @import("aro/Tokenizer.zig");
|
||||
_ = @import("aro/toolchains/Linux.zig");
|
||||
_ = @import("aro/Value.zig");
|
||||
}
|
||||
165
deps/aro/Attribute.zig → deps/aro/aro/Attribute.zig
vendored
165
deps/aro/Attribute.zig → deps/aro/aro/Attribute.zig
vendored
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const ZigType = std.builtin.Type;
|
||||
const CallingConvention = @import("lib.zig").CallingConvention;
|
||||
const CallingConvention = @import("backend").CallingConvention;
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Diagnostics = @import("Diagnostics.zig");
|
||||
const Parser = @import("Parser.zig");
|
||||
@ -18,20 +18,20 @@ syntax: Syntax,
|
||||
args: Arguments,
|
||||
|
||||
pub const Syntax = enum {
|
||||
c2x,
|
||||
c23,
|
||||
declspec,
|
||||
gnu,
|
||||
keyword,
|
||||
};
|
||||
|
||||
pub const Kind = enum {
|
||||
c2x,
|
||||
c23,
|
||||
declspec,
|
||||
gnu,
|
||||
|
||||
pub fn toSyntax(kind: Kind) Syntax {
|
||||
return switch (kind) {
|
||||
.c2x => .c2x,
|
||||
.c23 => .c23,
|
||||
.declspec => .declspec,
|
||||
.gnu => .gnu,
|
||||
};
|
||||
@ -57,30 +57,6 @@ pub const ArgumentType = enum {
|
||||
.expression => "an expression",
|
||||
};
|
||||
}
|
||||
|
||||
fn fromType(comptime T: type) ArgumentType {
|
||||
return switch (T) {
|
||||
Value.ByteRange => .string,
|
||||
Identifier => .identifier,
|
||||
u32 => .int,
|
||||
Alignment => .alignment,
|
||||
CallingConvention => .identifier,
|
||||
else => switch (@typeInfo(T)) {
|
||||
.Enum => if (T.opts.enum_kind == .string) .string else .identifier,
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn fromVal(value: Value) ArgumentType {
|
||||
return switch (value.tag) {
|
||||
.int => .int,
|
||||
.bytes => .string,
|
||||
.unavailable => .expression,
|
||||
.float => .float,
|
||||
.nullptr_t => .nullptr_t,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// number of required arguments
|
||||
@ -216,7 +192,7 @@ pub fn wantsAlignment(attr: Tag, idx: usize) bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Value, ty: Type, comp: *Compilation) ?Diagnostics.Message {
|
||||
pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, res: Parser.Result, p: *Parser) !?Diagnostics.Message {
|
||||
switch (attr) {
|
||||
inline else => |tag| {
|
||||
const arg_fields = std.meta.fields(@field(attributes, @tagName(tag)));
|
||||
@ -226,12 +202,12 @@ pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Va
|
||||
inline 0...arg_fields.len - 1 => |arg_i| {
|
||||
if (UnwrapOptional(arg_fields[arg_i].type) != Alignment) unreachable;
|
||||
|
||||
if (val.tag != .int) return Diagnostics.Message{ .tag = .alignas_unavailable };
|
||||
if (val.compare(.lt, Value.int(0), ty, comp)) {
|
||||
return Diagnostics.Message{ .tag = .negative_alignment, .extra = .{ .signed = val.signExtend(ty, comp) } };
|
||||
if (!res.val.is(.int, p.comp)) return Diagnostics.Message{ .tag = .alignas_unavailable };
|
||||
if (res.val.compare(.lt, Value.zero, p.comp)) {
|
||||
return Diagnostics.Message{ .tag = .negative_alignment, .extra = .{ .str = try res.str(p) } };
|
||||
}
|
||||
const requested = std.math.cast(u29, val.data.int) orelse {
|
||||
return Diagnostics.Message{ .tag = .maximum_alignment, .extra = .{ .unsigned = val.data.int } };
|
||||
const requested = res.val.toInt(u29, p.comp) orelse {
|
||||
return Diagnostics.Message{ .tag = .maximum_alignment, .extra = .{ .str = try res.str(p) } };
|
||||
};
|
||||
if (!std.mem.isValidAlign(requested)) return Diagnostics.Message{ .tag = .non_pow2_align };
|
||||
|
||||
@ -247,59 +223,84 @@ pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Va
|
||||
fn diagnoseField(
|
||||
comptime decl: ZigType.Declaration,
|
||||
comptime field: ZigType.StructField,
|
||||
comptime wanted: type,
|
||||
comptime Wanted: type,
|
||||
arguments: *Arguments,
|
||||
val: Value,
|
||||
res: Parser.Result,
|
||||
node: Tree.Node,
|
||||
strings: []const u8,
|
||||
) ?Diagnostics.Message {
|
||||
switch (val.tag) {
|
||||
p: *Parser,
|
||||
) !?Diagnostics.Message {
|
||||
if (res.val.opt_ref == .none) {
|
||||
if (Wanted == Identifier and node.tag == .decl_ref_expr) {
|
||||
@field(@field(arguments, decl.name), field.name) = Identifier{ .tok = node.data.decl_ref };
|
||||
return null;
|
||||
}
|
||||
return invalidArgMsg(Wanted, .expression);
|
||||
}
|
||||
const key = p.comp.interner.get(res.val.ref());
|
||||
switch (key) {
|
||||
.int => {
|
||||
if (@typeInfo(wanted) == .Int) {
|
||||
@field(@field(arguments, decl.name), field.name) = val.getInt(wanted);
|
||||
if (@typeInfo(Wanted) == .Int) {
|
||||
@field(@field(arguments, decl.name), field.name) = res.val.toInt(Wanted, p.comp) orelse return .{
|
||||
.tag = .attribute_int_out_of_range,
|
||||
.extra = .{ .str = try res.str(p) },
|
||||
};
|
||||
return null;
|
||||
}
|
||||
},
|
||||
.bytes => {
|
||||
const bytes = val.data.bytes.trim(1); // remove null terminator
|
||||
if (wanted == Value.ByteRange) {
|
||||
.bytes => |bytes| {
|
||||
if (Wanted == Value) {
|
||||
std.debug.assert(node.tag == .string_literal_expr);
|
||||
if (!node.ty.elemType().is(.char) and !node.ty.elemType().is(.uchar)) {
|
||||
return Diagnostics.Message{
|
||||
return .{
|
||||
.tag = .attribute_requires_string,
|
||||
.extra = .{ .str = decl.name },
|
||||
};
|
||||
}
|
||||
@field(@field(arguments, decl.name), field.name) = bytes;
|
||||
@field(@field(arguments, decl.name), field.name) = try p.removeNull(res.val);
|
||||
return null;
|
||||
} else if (@typeInfo(wanted) == .Enum and @hasDecl(wanted, "opts") and wanted.opts.enum_kind == .string) {
|
||||
const str = bytes.slice(strings, .@"1");
|
||||
if (std.meta.stringToEnum(wanted, str)) |enum_val| {
|
||||
} else if (@typeInfo(Wanted) == .Enum and @hasDecl(Wanted, "opts") and Wanted.opts.enum_kind == .string) {
|
||||
const str = bytes[0 .. bytes.len - 1];
|
||||
if (std.meta.stringToEnum(Wanted, str)) |enum_val| {
|
||||
@field(@field(arguments, decl.name), field.name) = enum_val;
|
||||
return null;
|
||||
} else {
|
||||
@setEvalBranchQuota(3000);
|
||||
return Diagnostics.Message{
|
||||
return .{
|
||||
.tag = .unknown_attr_enum,
|
||||
.extra = .{ .attr_enum = .{ .tag = std.meta.stringToEnum(Tag, decl.name).? } },
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
else => {
|
||||
if (wanted == Identifier and node.tag == .decl_ref_expr) {
|
||||
@field(@field(arguments, decl.name), field.name) = Identifier{ .tok = node.data.decl_ref };
|
||||
return null;
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
return invalidArgMsg(Wanted, switch (key) {
|
||||
.int => .int,
|
||||
.bytes => .string,
|
||||
.float => .float,
|
||||
.null => .nullptr_t,
|
||||
else => unreachable,
|
||||
});
|
||||
}
|
||||
return Diagnostics.Message{
|
||||
|
||||
fn invalidArgMsg(comptime Expected: type, actual: ArgumentType) Diagnostics.Message {
|
||||
return .{
|
||||
.tag = .attribute_arg_invalid,
|
||||
.extra = .{ .attr_arg_type = .{ .expected = ArgumentType.fromType(wanted), .actual = ArgumentType.fromVal(val) } },
|
||||
.extra = .{ .attr_arg_type = .{ .expected = switch (Expected) {
|
||||
Value => .string,
|
||||
Identifier => .identifier,
|
||||
u32 => .int,
|
||||
Alignment => .alignment,
|
||||
CallingConvention => .identifier,
|
||||
else => switch (@typeInfo(Expected)) {
|
||||
.Enum => if (Expected.opts.enum_kind == .string) .string else .identifier,
|
||||
else => unreachable,
|
||||
},
|
||||
}, .actual = actual } },
|
||||
};
|
||||
}
|
||||
|
||||
pub fn diagnose(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Value, node: Tree.Node, strings: []const u8) ?Diagnostics.Message {
|
||||
pub fn diagnose(attr: Tag, arguments: *Arguments, arg_idx: u32, res: Parser.Result, node: Tree.Node, p: *Parser) !?Diagnostics.Message {
|
||||
switch (attr) {
|
||||
inline else => |tag| {
|
||||
const decl = @typeInfo(attributes).Struct.decls[@intFromEnum(tag)];
|
||||
@ -311,7 +312,7 @@ pub fn diagnose(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Value, node
|
||||
const arg_fields = std.meta.fields(@field(attributes, decl.name));
|
||||
switch (arg_idx) {
|
||||
inline 0...arg_fields.len - 1 => |arg_i| {
|
||||
return diagnoseField(decl, arg_fields[arg_i], UnwrapOptional(arg_fields[arg_i].type), arguments, val, node, strings);
|
||||
return diagnoseField(decl, arg_fields[arg_i], UnwrapOptional(arg_fields[arg_i].type), arguments, res, node, p);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
@ -347,7 +348,7 @@ const attributes = struct {
|
||||
size_index: ?u32 = null,
|
||||
};
|
||||
pub const alias = struct {
|
||||
alias: Value.ByteRange,
|
||||
alias: Value,
|
||||
};
|
||||
pub const aligned = struct {
|
||||
alignment: ?Alignment = null,
|
||||
@ -361,7 +362,7 @@ const attributes = struct {
|
||||
position_2: ?u32 = null,
|
||||
};
|
||||
pub const allocate = struct {
|
||||
segname: Value.ByteRange,
|
||||
segname: Value,
|
||||
};
|
||||
pub const allocator = struct {};
|
||||
pub const always_inline = struct {};
|
||||
@ -375,7 +376,7 @@ const attributes = struct {
|
||||
function: Identifier,
|
||||
};
|
||||
pub const code_seg = struct {
|
||||
segname: Value.ByteRange,
|
||||
segname: Value,
|
||||
};
|
||||
pub const cold = struct {};
|
||||
pub const common = struct {};
|
||||
@ -387,7 +388,7 @@ const attributes = struct {
|
||||
function: Identifier,
|
||||
};
|
||||
pub const deprecated = struct {
|
||||
msg: ?Value.ByteRange = null,
|
||||
msg: ?Value = null,
|
||||
__name_tok: TokenIndex,
|
||||
};
|
||||
pub const designated_init = struct {};
|
||||
@ -397,7 +398,7 @@ const attributes = struct {
|
||||
pub const dllexport = struct {};
|
||||
pub const dllimport = struct {};
|
||||
pub const @"error" = struct {
|
||||
msg: Value.ByteRange,
|
||||
msg: Value,
|
||||
__name_tok: TokenIndex,
|
||||
};
|
||||
pub const externally_visible = struct {};
|
||||
@ -423,7 +424,7 @@ const attributes = struct {
|
||||
pub const gnu_inline = struct {};
|
||||
pub const hot = struct {};
|
||||
pub const ifunc = struct {
|
||||
resolver: Value.ByteRange,
|
||||
resolver: Value,
|
||||
};
|
||||
pub const interrupt = struct {};
|
||||
pub const interrupt_handler = struct {};
|
||||
@ -469,8 +470,8 @@ const attributes = struct {
|
||||
pub const no_reorder = struct {};
|
||||
pub const no_sanitize = struct {
|
||||
/// Todo: represent args as union?
|
||||
alignment: Value.ByteRange,
|
||||
object_size: ?Value.ByteRange = null,
|
||||
alignment: Value,
|
||||
object_size: ?Value = null,
|
||||
};
|
||||
pub const no_sanitize_address = struct {};
|
||||
pub const no_sanitize_coverage = struct {};
|
||||
@ -521,7 +522,7 @@ const attributes = struct {
|
||||
},
|
||||
};
|
||||
pub const section = struct {
|
||||
name: Value.ByteRange,
|
||||
name: Value,
|
||||
};
|
||||
pub const selectany = struct {};
|
||||
pub const sentinel = struct {
|
||||
@ -548,15 +549,15 @@ const attributes = struct {
|
||||
};
|
||||
pub const stack_protect = struct {};
|
||||
pub const symver = struct {
|
||||
version: Value.ByteRange, // TODO: validate format "name2@nodename"
|
||||
version: Value, // TODO: validate format "name2@nodename"
|
||||
|
||||
};
|
||||
pub const target = struct {
|
||||
options: Value.ByteRange, // TODO: multiple arguments
|
||||
options: Value, // TODO: multiple arguments
|
||||
|
||||
};
|
||||
pub const target_clones = struct {
|
||||
options: Value.ByteRange, // TODO: multiple arguments
|
||||
options: Value, // TODO: multiple arguments
|
||||
|
||||
};
|
||||
pub const thread = struct {};
|
||||
@ -574,7 +575,7 @@ const attributes = struct {
|
||||
};
|
||||
pub const transparent_union = struct {};
|
||||
pub const unavailable = struct {
|
||||
msg: ?Value.ByteRange = null,
|
||||
msg: ?Value = null,
|
||||
__name_tok: TokenIndex,
|
||||
};
|
||||
pub const uninitialized = struct {};
|
||||
@ -582,7 +583,7 @@ const attributes = struct {
|
||||
pub const unused = struct {};
|
||||
pub const used = struct {};
|
||||
pub const uuid = struct {
|
||||
uuid: Value.ByteRange,
|
||||
uuid: Value,
|
||||
};
|
||||
pub const vector_size = struct {
|
||||
bytes: u32, // TODO: validate "The bytes argument must be a positive power-of-two multiple of the base type size"
|
||||
@ -605,12 +606,12 @@ const attributes = struct {
|
||||
};
|
||||
pub const warn_unused_result = struct {};
|
||||
pub const warning = struct {
|
||||
msg: Value.ByteRange,
|
||||
msg: Value,
|
||||
__name_tok: TokenIndex,
|
||||
};
|
||||
pub const weak = struct {};
|
||||
pub const weakref = struct {
|
||||
target: ?Value.ByteRange = null,
|
||||
target: ?Value = null,
|
||||
};
|
||||
pub const zero_call_used_regs = struct {
|
||||
choice: enum {
|
||||
@ -630,7 +631,7 @@ const attributes = struct {
|
||||
},
|
||||
};
|
||||
pub const asm_label = struct {
|
||||
name: Value.ByteRange,
|
||||
name: Value,
|
||||
};
|
||||
pub const calling_convention = struct {
|
||||
cc: CallingConvention,
|
||||
@ -684,7 +685,7 @@ pub fn fromString(kind: Kind, namespace: ?[]const u8, name: []const u8) ?Tag {
|
||||
tag: Tag,
|
||||
gnu: bool = false,
|
||||
declspec: bool = false,
|
||||
c2x: bool = false,
|
||||
c23: bool = false,
|
||||
};
|
||||
const attribute_names = @import("Attribute/names.def").with(Properties);
|
||||
|
||||
@ -707,7 +708,7 @@ pub fn fromString(kind: Kind, namespace: ?[]const u8, name: []const u8) ?Tag {
|
||||
return null;
|
||||
}
|
||||
|
||||
fn normalize(name: []const u8) []const u8 {
|
||||
pub fn normalize(name: []const u8) []const u8 {
|
||||
if (name.len >= 4 and mem.startsWith(u8, name, "__") and mem.endsWith(u8, name, "__")) {
|
||||
return name[2 .. name.len - 2];
|
||||
}
|
||||
@ -719,7 +720,7 @@ fn ignoredAttrErr(p: *Parser, tok: TokenIndex, attr: Attribute.Tag, context: []c
|
||||
defer p.strings.items.len = strings_top;
|
||||
|
||||
try p.strings.writer().print("attribute '{s}' ignored on {s}", .{ @tagName(attr), context });
|
||||
const str = try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
|
||||
const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
|
||||
try p.errStr(.ignored_attribute, tok, str);
|
||||
}
|
||||
|
||||
@ -1029,7 +1030,11 @@ fn applyTransparentUnion(attr: Attribute, p: *Parser, tok: TokenIndex, ty: Type)
|
||||
const field_size = field.ty.bitSizeof(p.comp).?;
|
||||
if (field_size == first_field_size) continue;
|
||||
const mapper = p.comp.string_interner.getSlowTypeMapper();
|
||||
const str = try std.fmt.allocPrint(p.comp.diag.arena.allocator(), "'{s}' ({d}", .{ mapper.lookup(field.name), field_size });
|
||||
const str = try std.fmt.allocPrint(
|
||||
p.comp.diagnostics.arena.allocator(),
|
||||
"'{s}' ({d}",
|
||||
.{ mapper.lookup(field.name), field_size },
|
||||
);
|
||||
try p.errStr(.transparent_union_size, field.name_tok, str);
|
||||
return p.errExtra(.transparent_union_size_note, fields[0].name_tok, .{ .unsigned = first_field_size });
|
||||
}
|
||||
@ -1,18 +1,18 @@
|
||||
# multiple
|
||||
deprecated
|
||||
.tag = .deprecated
|
||||
.c2x = true
|
||||
.c23 = true
|
||||
.gnu = true
|
||||
.declspec = true
|
||||
|
||||
fallthrough
|
||||
.tag = .fallthrough
|
||||
.c2x = true
|
||||
.c23 = true
|
||||
.gnu = true
|
||||
|
||||
noreturn
|
||||
.tag = .@"noreturn"
|
||||
.c2x = true
|
||||
.c23 = true
|
||||
.gnu = true
|
||||
.declspec = true
|
||||
|
||||
@ -26,22 +26,22 @@ noinline
|
||||
.gnu = true
|
||||
.declspec = true
|
||||
|
||||
# c2x only
|
||||
# c23 only
|
||||
nodiscard
|
||||
.tag = .nodiscard
|
||||
.c2x = true
|
||||
.c23 = true
|
||||
|
||||
reproducible
|
||||
.tag = .reproducible
|
||||
.c2x = true
|
||||
.c23 = true
|
||||
|
||||
unsequenced
|
||||
.tag = .unsequenced
|
||||
.c2x = true
|
||||
.c23 = true
|
||||
|
||||
maybe_unused
|
||||
.tag = .unused
|
||||
.c2x = true
|
||||
.c23 = true
|
||||
|
||||
# gnu only
|
||||
access
|
||||
@ -10,8 +10,6 @@ const Parser = @import("Parser.zig");
|
||||
const Properties = @import("Builtins/Properties.zig");
|
||||
pub const Builtin = @import("Builtins/Builtin.def").with(Properties);
|
||||
|
||||
const Builtins = @This();
|
||||
|
||||
const Expanded = struct {
|
||||
ty: Type,
|
||||
builtin: Builtin,
|
||||
@ -19,6 +17,8 @@ const Expanded = struct {
|
||||
|
||||
const NameToTypeMap = std.StringHashMapUnmanaged(Type);
|
||||
|
||||
const Builtins = @This();
|
||||
|
||||
_name_to_type_map: NameToTypeMap = .{},
|
||||
|
||||
pub fn deinit(b: *Builtins, gpa: std.mem.Allocator) void {
|
||||
@ -355,7 +355,7 @@ test Iterator {
|
||||
test "All builtins" {
|
||||
var comp = Compilation.init(std.testing.allocator);
|
||||
defer comp.deinit();
|
||||
_ = try comp.generateBuiltinMacros();
|
||||
_ = try comp.generateBuiltinMacros(.include_system_defines);
|
||||
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
@ -378,7 +378,7 @@ test "Allocation failures" {
|
||||
fn testOne(allocator: std.mem.Allocator) !void {
|
||||
var comp = Compilation.init(allocator);
|
||||
defer comp.deinit();
|
||||
_ = try comp.generateBuiltinMacros();
|
||||
_ = try comp.generateBuiltinMacros(.include_system_defines);
|
||||
var arena = std.heap.ArenaAllocator.init(comp.gpa);
|
||||
defer arena.deinit();
|
||||
|
||||
187
deps/aro/CodeGen.zig → deps/aro/aro/CodeGen.zig
vendored
187
deps/aro/CodeGen.zig → deps/aro/aro/CodeGen.zig
vendored
@ -1,20 +1,20 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const backend = @import("backend");
|
||||
const Interner = backend.Interner;
|
||||
const Ir = backend.Ir;
|
||||
const Builtins = @import("Builtins.zig");
|
||||
const Builtin = Builtins.Builtin;
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Interner = @import("Interner.zig");
|
||||
const Ir = @import("Ir.zig");
|
||||
const Builder = Ir.Builder;
|
||||
const StringId = @import("StringInterner.zig").StringId;
|
||||
const StrInt = @import("StringInterner.zig");
|
||||
const StringId = StrInt.StringId;
|
||||
const Tree = @import("Tree.zig");
|
||||
const NodeIndex = Tree.NodeIndex;
|
||||
const Type = @import("Type.zig");
|
||||
const Value = @import("Value.zig");
|
||||
|
||||
const CodeGen = @This();
|
||||
|
||||
const WipSwitch = struct {
|
||||
cases: Cases = .{},
|
||||
default: ?Ir.Ref = null,
|
||||
@ -33,6 +33,8 @@ const Symbol = struct {
|
||||
|
||||
const Error = Compilation.Error;
|
||||
|
||||
const CodeGen = @This();
|
||||
|
||||
tree: Tree,
|
||||
comp: *Compilation,
|
||||
builder: Builder,
|
||||
@ -44,6 +46,7 @@ symbols: std.ArrayListUnmanaged(Symbol) = .{},
|
||||
ret_nodes: std.ArrayListUnmanaged(Ir.Inst.Phi.Input) = .{},
|
||||
phi_nodes: std.ArrayListUnmanaged(Ir.Inst.Phi.Input) = .{},
|
||||
record_elem_buf: std.ArrayListUnmanaged(Interner.Ref) = .{},
|
||||
record_cache: std.AutoHashMapUnmanaged(*Type.Record, Interner.Ref) = .{},
|
||||
cond_dummy_ty: ?Interner.Ref = null,
|
||||
bool_invert: bool = false,
|
||||
bool_end_label: Ir.Ref = .none,
|
||||
@ -52,28 +55,40 @@ continue_label: Ir.Ref = undefined,
|
||||
break_label: Ir.Ref = undefined,
|
||||
return_label: Ir.Ref = undefined,
|
||||
|
||||
pub fn generateTree(comp: *Compilation, tree: Tree) Compilation.Error!void {
|
||||
fn fail(c: *CodeGen, comptime fmt: []const u8, args: anytype) error{ FatalError, OutOfMemory } {
|
||||
try c.comp.diagnostics.list.append(c.comp.gpa, .{
|
||||
.tag = .cli_error,
|
||||
.kind = .@"fatal error",
|
||||
.extra = .{ .str = try std.fmt.allocPrint(c.comp.diagnostics.arena.allocator(), fmt, args) },
|
||||
});
|
||||
return error.FatalError;
|
||||
}
|
||||
|
||||
pub fn genIr(tree: Tree) Compilation.Error!Ir {
|
||||
const gpa = tree.comp.gpa;
|
||||
var c = CodeGen{
|
||||
.builder = .{
|
||||
.gpa = comp.gpa,
|
||||
.arena = std.heap.ArenaAllocator.init(comp.gpa),
|
||||
.gpa = tree.comp.gpa,
|
||||
.interner = &tree.comp.interner,
|
||||
.arena = std.heap.ArenaAllocator.init(gpa),
|
||||
},
|
||||
.tree = tree,
|
||||
.comp = comp,
|
||||
.comp = tree.comp,
|
||||
.node_tag = tree.nodes.items(.tag),
|
||||
.node_data = tree.nodes.items(.data),
|
||||
.node_ty = tree.nodes.items(.ty),
|
||||
};
|
||||
defer c.symbols.deinit(c.comp.gpa);
|
||||
defer c.ret_nodes.deinit(c.comp.gpa);
|
||||
defer c.phi_nodes.deinit(c.comp.gpa);
|
||||
defer c.record_elem_buf.deinit(c.comp.gpa);
|
||||
defer c.symbols.deinit(gpa);
|
||||
defer c.ret_nodes.deinit(gpa);
|
||||
defer c.phi_nodes.deinit(gpa);
|
||||
defer c.record_elem_buf.deinit(gpa);
|
||||
defer c.record_cache.deinit(gpa);
|
||||
defer c.builder.deinit();
|
||||
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
for (tree.root_decls) |decl| {
|
||||
c.builder.arena.deinit();
|
||||
c.builder.arena = std.heap.ArenaAllocator.init(comp.gpa);
|
||||
c.builder.arena = std.heap.ArenaAllocator.init(gpa);
|
||||
|
||||
switch (node_tags[@intFromEnum(decl)]) {
|
||||
.static_assert,
|
||||
@ -114,6 +129,7 @@ pub fn generateTree(comp: *Compilation, tree: Tree) Compilation.Error!void {
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
return c.builder.finish();
|
||||
}
|
||||
|
||||
fn genType(c: *CodeGen, base_ty: Type) !Interner.Ref {
|
||||
@ -123,52 +139,48 @@ fn genType(c: *CodeGen, base_ty: Type) !Interner.Ref {
|
||||
.void => return .void,
|
||||
.bool => return .i1,
|
||||
.@"struct" => {
|
||||
key = .{
|
||||
.record = .{
|
||||
.user_ptr = ty.data.record,
|
||||
.elements = undefined, // Not needed for hash lookup.
|
||||
},
|
||||
};
|
||||
if (c.builder.pool.has(key)) |some| return some;
|
||||
if (c.record_cache.get(ty.data.record)) |some| return some;
|
||||
|
||||
const elem_buf_top = c.record_elem_buf.items.len;
|
||||
defer c.record_elem_buf.items.len = elem_buf_top;
|
||||
|
||||
for (ty.data.record.fields) |field| {
|
||||
if (!field.isRegularField()) {
|
||||
return c.comp.diag.fatalNoSrc("TODO lower struct bitfields", .{});
|
||||
return c.fail("TODO lower struct bitfields", .{});
|
||||
}
|
||||
// TODO handle padding bits
|
||||
const field_ref = try c.genType(field.ty);
|
||||
try c.record_elem_buf.append(c.builder.gpa, field_ref);
|
||||
}
|
||||
|
||||
key.record.elements = try c.builder.arena.allocator().dupe(Interner.Ref, c.record_elem_buf.items[elem_buf_top..]);
|
||||
return c.builder.pool.put(c.builder.gpa, key);
|
||||
return c.builder.interner.put(c.builder.gpa, .{
|
||||
.record_ty = c.record_elem_buf.items[elem_buf_top..],
|
||||
});
|
||||
},
|
||||
.@"union" => {
|
||||
return c.comp.diag.fatalNoSrc("TODO lower union types", .{});
|
||||
return c.fail("TODO lower union types", .{});
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
if (ty.isPtr()) return .ptr;
|
||||
if (ty.isFunc()) return .func;
|
||||
if (!ty.isReal()) return c.comp.diag.fatalNoSrc("TODO lower complex types", .{});
|
||||
if (!ty.isReal()) return c.fail("TODO lower complex types", .{});
|
||||
if (ty.isInt()) {
|
||||
const bits = ty.bitSizeof(c.comp).?;
|
||||
key = .{ .int = @intCast(bits) };
|
||||
key = .{ .int_ty = @intCast(bits) };
|
||||
} else if (ty.isFloat()) {
|
||||
const bits = ty.bitSizeof(c.comp).?;
|
||||
key = .{ .float = @intCast(bits) };
|
||||
key = .{ .float_ty = @intCast(bits) };
|
||||
} else if (ty.isArray()) {
|
||||
const elem = try c.genType(ty.elemType());
|
||||
key = .{ .array = .{ .child = elem, .len = ty.arrayLen().? } };
|
||||
key = .{ .array_ty = .{ .child = elem, .len = ty.arrayLen().? } };
|
||||
} else if (ty.specifier == .vector) {
|
||||
const elem = try c.genType(ty.elemType());
|
||||
key = .{ .vector = .{ .child = elem, .len = @intCast(ty.data.array.len) } };
|
||||
key = .{ .vector_ty = .{ .child = elem, .len = @intCast(ty.data.array.len) } };
|
||||
} else if (ty.is(.nullptr_t)) {
|
||||
return c.comp.diag.fatalNoSrc("TODO lower nullptr_t", .{});
|
||||
return c.fail("TODO lower nullptr_t", .{});
|
||||
}
|
||||
return c.builder.pool.put(c.builder.gpa, key);
|
||||
return c.builder.interner.put(c.builder.gpa, key);
|
||||
}
|
||||
|
||||
fn genFn(c: *CodeGen, decl: NodeIndex) Error!void {
|
||||
@ -205,14 +217,7 @@ fn genFn(c: *CodeGen, decl: NodeIndex) Error!void {
|
||||
_ = try c.builder.addInst(.ret, .{ .un = phi }, .noreturn);
|
||||
}
|
||||
|
||||
var res = Ir{
|
||||
.pool = c.builder.pool,
|
||||
.instructions = c.builder.instructions,
|
||||
.arena = c.builder.arena.state,
|
||||
.body = c.builder.body,
|
||||
.strings = c.tree.strings,
|
||||
};
|
||||
res.dump(c.builder.gpa, name, c.comp.diag.color, std.io.getStdOut().writer()) catch {};
|
||||
try c.builder.finishFn(name);
|
||||
}
|
||||
|
||||
fn addUn(c: *CodeGen, tag: Ir.Inst.Tag, operand: Ir.Ref, ty: Type) !Ir.Ref {
|
||||
@ -238,7 +243,7 @@ fn addBranch(c: *CodeGen, cond: Ir.Ref, true_label: Ir.Ref, false_label: Ir.Ref)
|
||||
}
|
||||
|
||||
fn addBoolPhi(c: *CodeGen, value: bool) !void {
|
||||
const val = try c.builder.addConstant(Value.int(@intFromBool(value)), .i1);
|
||||
const val = try c.builder.addConstant((try Value.int(@intFromBool(value), c.comp)).ref(), .i1);
|
||||
try c.phi_nodes.append(c.comp.gpa, .{ .label = c.builder.current_label, .value = val });
|
||||
}
|
||||
|
||||
@ -250,7 +255,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
std.debug.assert(node != .none);
|
||||
const ty = c.node_ty[@intFromEnum(node)];
|
||||
if (c.tree.value_map.get(node)) |val| {
|
||||
return c.builder.addConstant(val, try c.genType(ty));
|
||||
return c.builder.addConstant(val.ref(), try c.genType(ty));
|
||||
}
|
||||
const data = c.node_data[@intFromEnum(node)];
|
||||
switch (c.node_tag[@intFromEnum(node)]) {
|
||||
@ -259,7 +264,6 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
.int_literal,
|
||||
.char_literal,
|
||||
.float_literal,
|
||||
.double_literal,
|
||||
.imaginary_literal,
|
||||
.string_literal_expr,
|
||||
.alignof_expr,
|
||||
@ -301,7 +305,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
const size: u32 = @intCast(ty.sizeof(c.comp).?); // TODO add error in parser
|
||||
const @"align" = ty.alignof(c.comp);
|
||||
const alloc = try c.builder.addAlloc(size, @"align");
|
||||
const name = try c.comp.intern(c.tree.tokSlice(data.decl.name));
|
||||
const name = try StrInt.intern(c.comp, c.tree.tokSlice(data.decl.name));
|
||||
try c.symbols.append(c.comp.gpa, .{ .name = name, .val = alloc });
|
||||
if (data.decl.node != .none) {
|
||||
try c.genInitializer(alloc, ty, data.decl.node);
|
||||
@ -391,7 +395,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
const label = try c.builder.makeLabel("case");
|
||||
try c.builder.startBlock(label);
|
||||
try c.wip_switch.cases.append(c.builder.gpa, .{
|
||||
.val = try c.builder.pool.put(c.builder.gpa, .{ .value = val }),
|
||||
.val = val.ref(),
|
||||
.label = label,
|
||||
});
|
||||
try c.genStmt(data.bin.rhs);
|
||||
@ -453,7 +457,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
const old_continue_label = c.continue_label;
|
||||
defer c.continue_label = old_continue_label;
|
||||
|
||||
const for_decl = data.forDecl(c.tree);
|
||||
const for_decl = data.forDecl(&c.tree);
|
||||
for (for_decl.decls) |decl| try c.genStmt(decl);
|
||||
|
||||
const then_label = try c.builder.makeLabel("for.then");
|
||||
@ -501,7 +505,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
const old_continue_label = c.continue_label;
|
||||
defer c.continue_label = old_continue_label;
|
||||
|
||||
const for_stmt = data.forStmt(c.tree);
|
||||
const for_stmt = data.forStmt(&c.tree);
|
||||
if (for_stmt.init != .none) _ = try c.genExpr(for_stmt.init);
|
||||
|
||||
const then_label = try c.builder.makeLabel("for.then");
|
||||
@ -536,7 +540,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
},
|
||||
.implicit_return => {
|
||||
if (data.return_zero) {
|
||||
const operand = try c.builder.addConstant(Value.int(0), try c.genType(ty));
|
||||
const operand = try c.builder.addConstant(.zero, try c.genType(ty));
|
||||
try c.ret_nodes.append(c.comp.gpa, .{ .value = operand, .label = c.builder.current_label });
|
||||
}
|
||||
// No need to emit a jump since implicit_return is always the last instruction.
|
||||
@ -545,7 +549,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
.goto_stmt,
|
||||
.computed_goto_stmt,
|
||||
.nullptr_literal,
|
||||
=> return c.comp.diag.fatalNoSrc("TODO CodeGen.genStmt {}\n", .{c.node_tag[@intFromEnum(node)]}),
|
||||
=> return c.fail("TODO CodeGen.genStmt {}\n", .{c.node_tag[@intFromEnum(node)]}),
|
||||
.comma_expr => {
|
||||
_ = try c.genExpr(data.bin.lhs);
|
||||
return c.genExpr(data.bin.rhs);
|
||||
@ -635,7 +639,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
},
|
||||
.plus_expr => return c.genExpr(data.un),
|
||||
.negate_expr => {
|
||||
const zero = try c.builder.addConstant(Value.int(0), try c.genType(ty));
|
||||
const zero = try c.builder.addConstant(.zero, try c.genType(ty));
|
||||
const operand = try c.genExpr(data.un);
|
||||
return c.addBin(.sub, zero, operand, ty);
|
||||
},
|
||||
@ -644,14 +648,14 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
return c.addUn(.bit_not, operand, ty);
|
||||
},
|
||||
.bool_not_expr => {
|
||||
const zero = try c.builder.addConstant(Value.int(0), try c.genType(ty));
|
||||
const zero = try c.builder.addConstant(.zero, try c.genType(ty));
|
||||
const operand = try c.genExpr(data.un);
|
||||
return c.addBin(.cmp_ne, zero, operand, ty);
|
||||
},
|
||||
.pre_inc_expr => {
|
||||
const operand = try c.genLval(data.un);
|
||||
const val = try c.addUn(.load, operand, ty);
|
||||
const one = try c.builder.addConstant(Value.int(1), try c.genType(ty));
|
||||
const one = try c.builder.addConstant(.one, try c.genType(ty));
|
||||
const plus_one = try c.addBin(.add, val, one, ty);
|
||||
try c.builder.addStore(operand, plus_one);
|
||||
return plus_one;
|
||||
@ -659,7 +663,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
.pre_dec_expr => {
|
||||
const operand = try c.genLval(data.un);
|
||||
const val = try c.addUn(.load, operand, ty);
|
||||
const one = try c.builder.addConstant(Value.int(1), try c.genType(ty));
|
||||
const one = try c.builder.addConstant(.one, try c.genType(ty));
|
||||
const plus_one = try c.addBin(.sub, val, one, ty);
|
||||
try c.builder.addStore(operand, plus_one);
|
||||
return plus_one;
|
||||
@ -667,7 +671,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
.post_inc_expr => {
|
||||
const operand = try c.genLval(data.un);
|
||||
const val = try c.addUn(.load, operand, ty);
|
||||
const one = try c.builder.addConstant(Value.int(1), try c.genType(ty));
|
||||
const one = try c.builder.addConstant(.one, try c.genType(ty));
|
||||
const plus_one = try c.addBin(.add, val, one, ty);
|
||||
try c.builder.addStore(operand, plus_one);
|
||||
return val;
|
||||
@ -675,7 +679,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
.post_dec_expr => {
|
||||
const operand = try c.genLval(data.un);
|
||||
const val = try c.addUn(.load, operand, ty);
|
||||
const one = try c.builder.addConstant(Value.int(1), try c.genType(ty));
|
||||
const one = try c.builder.addConstant(.one, try c.genType(ty));
|
||||
const plus_one = try c.addBin(.sub, val, one, ty);
|
||||
try c.builder.addStore(operand, plus_one);
|
||||
return val;
|
||||
@ -717,7 +721,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
},
|
||||
.pointer_to_bool, .int_to_bool, .float_to_bool => {
|
||||
const lhs = try c.genExpr(data.cast.operand);
|
||||
const rhs = try c.builder.addConstant(Value.int(0), try c.genType(c.node_ty[@intFromEnum(node)]));
|
||||
const rhs = try c.builder.addConstant(.zero, try c.genType(c.node_ty[@intFromEnum(node)]));
|
||||
return c.builder.addInst(.cmp_ne, .{ .bin = .{ .lhs = lhs, .rhs = rhs } }, .i1);
|
||||
},
|
||||
.bitcast,
|
||||
@ -739,11 +743,11 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
.null_to_pointer,
|
||||
.union_cast,
|
||||
.vector_splat,
|
||||
=> return c.comp.diag.fatalNoSrc("TODO CodeGen gen CastKind {}\n", .{data.cast.kind}),
|
||||
=> return c.fail("TODO CodeGen gen CastKind {}\n", .{data.cast.kind}),
|
||||
},
|
||||
.binary_cond_expr => {
|
||||
if (c.tree.value_map.get(data.if3.cond)) |cond| {
|
||||
if (cond.getBool()) {
|
||||
if (cond.toBool(c.comp)) {
|
||||
c.cond_dummy_ref = try c.genExpr(data.if3.cond);
|
||||
return c.genExpr(c.tree.data[data.if3.body]); // then
|
||||
} else {
|
||||
@ -786,7 +790,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
.cond_dummy_expr => return c.cond_dummy_ref,
|
||||
.cond_expr => {
|
||||
if (c.tree.value_map.get(data.if3.cond)) |cond| {
|
||||
if (cond.getBool()) {
|
||||
if (cond.toBool(c.comp)) {
|
||||
return c.genExpr(c.tree.data[data.if3.body]); // then
|
||||
} else {
|
||||
return c.genExpr(c.tree.data[data.if3.body + 1]); // else
|
||||
@ -826,9 +830,8 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
},
|
||||
.bool_or_expr => {
|
||||
if (c.tree.value_map.get(data.bin.lhs)) |lhs| {
|
||||
const cond = lhs.getBool();
|
||||
if (!cond) {
|
||||
return c.builder.addConstant(Value.int(1), try c.genType(ty));
|
||||
if (!lhs.toBool(c.comp)) {
|
||||
return c.builder.addConstant(.one, try c.genType(ty));
|
||||
}
|
||||
return c.genExpr(data.bin.rhs);
|
||||
}
|
||||
@ -855,9 +858,8 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
},
|
||||
.bool_and_expr => {
|
||||
if (c.tree.value_map.get(data.bin.lhs)) |lhs| {
|
||||
const cond = lhs.getBool();
|
||||
if (!cond) {
|
||||
return c.builder.addConstant(Value.int(0), try c.genType(ty));
|
||||
if (!lhs.toBool(c.comp)) {
|
||||
return c.builder.addConstant(.zero, try c.genType(ty));
|
||||
}
|
||||
return c.genExpr(data.bin.rhs);
|
||||
}
|
||||
@ -884,7 +886,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
},
|
||||
.builtin_choose_expr => {
|
||||
const cond = c.tree.value_map.get(data.if3.cond).?;
|
||||
if (cond.getBool()) {
|
||||
if (cond.toBool(c.comp)) {
|
||||
return c.genExpr(c.tree.data[data.if3.body]);
|
||||
} else {
|
||||
return c.genExpr(c.tree.data[data.if3.body + 1]);
|
||||
@ -949,7 +951,7 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
.real_expr,
|
||||
.sizeof_expr,
|
||||
.special_builtin_call_one,
|
||||
=> return c.comp.diag.fatalNoSrc("TODO CodeGen.genExpr {}\n", .{c.node_tag[@intFromEnum(node)]}),
|
||||
=> return c.fail("TODO CodeGen.genExpr {}\n", .{c.node_tag[@intFromEnum(node)]}),
|
||||
else => unreachable, // Not an expression.
|
||||
}
|
||||
return .none;
|
||||
@ -957,17 +959,17 @@ fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
|
||||
fn genLval(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
std.debug.assert(node != .none);
|
||||
assert(Tree.isLval(c.tree.nodes, c.tree.data, c.tree.value_map, node));
|
||||
assert(c.tree.isLval(node));
|
||||
const data = c.node_data[@intFromEnum(node)];
|
||||
switch (c.node_tag[@intFromEnum(node)]) {
|
||||
.string_literal_expr => {
|
||||
const val = c.tree.value_map.get(node).?;
|
||||
return c.builder.addConstant(val, .ptr);
|
||||
return c.builder.addConstant(val.ref(), .ptr);
|
||||
},
|
||||
.paren_expr => return c.genLval(data.un),
|
||||
.decl_ref_expr => {
|
||||
const slice = c.tree.tokSlice(data.decl_ref);
|
||||
const name = try c.comp.intern(slice);
|
||||
const name = try StrInt.intern(c.comp, slice);
|
||||
var i = c.symbols.items.len;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
@ -992,7 +994,7 @@ fn genLval(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
},
|
||||
.builtin_choose_expr => {
|
||||
const cond = c.tree.value_map.get(data.if3.cond).?;
|
||||
if (cond.getBool()) {
|
||||
if (cond.toBool(c.comp)) {
|
||||
return c.genLval(c.tree.data[data.if3.body]);
|
||||
} else {
|
||||
return c.genLval(c.tree.data[data.if3.body + 1]);
|
||||
@ -1001,7 +1003,10 @@ fn genLval(c: *CodeGen, node: NodeIndex) Error!Ir.Ref {
|
||||
.member_access_expr,
|
||||
.member_access_ptr_expr,
|
||||
.array_access_expr,
|
||||
=> return c.comp.diag.fatalNoSrc("TODO CodeGen.genLval {}\n", .{c.node_tag[@intFromEnum(node)]}),
|
||||
.static_compound_literal_expr,
|
||||
.thread_local_compound_literal_expr,
|
||||
.static_thread_local_compound_literal_expr,
|
||||
=> return c.fail("TODO CodeGen.genLval {}\n", .{c.node_tag[@intFromEnum(node)]}),
|
||||
else => unreachable, // Not an lval expression.
|
||||
}
|
||||
}
|
||||
@ -1019,8 +1024,7 @@ fn genBoolExpr(c: *CodeGen, base: NodeIndex, true_label: Ir.Ref, false_label: Ir
|
||||
switch (c.node_tag[@intFromEnum(node)]) {
|
||||
.bool_or_expr => {
|
||||
if (c.tree.value_map.get(data.bin.lhs)) |lhs| {
|
||||
const cond = lhs.getBool();
|
||||
if (cond) {
|
||||
if (lhs.toBool(c.comp)) {
|
||||
if (true_label == c.bool_end_label) {
|
||||
return c.addBoolPhi(!c.bool_invert);
|
||||
}
|
||||
@ -1033,13 +1037,12 @@ fn genBoolExpr(c: *CodeGen, base: NodeIndex, true_label: Ir.Ref, false_label: Ir
|
||||
try c.genBoolExpr(data.bin.lhs, true_label, new_false_label);
|
||||
try c.builder.startBlock(new_false_label);
|
||||
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(1), ty);
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(.one, ty);
|
||||
return c.genBoolExpr(data.bin.rhs, true_label, false_label);
|
||||
},
|
||||
.bool_and_expr => {
|
||||
if (c.tree.value_map.get(data.bin.lhs)) |lhs| {
|
||||
const cond = lhs.getBool();
|
||||
if (!cond) {
|
||||
if (!lhs.toBool(c.comp)) {
|
||||
if (false_label == c.bool_end_label) {
|
||||
return c.addBoolPhi(c.bool_invert);
|
||||
}
|
||||
@ -1052,14 +1055,14 @@ fn genBoolExpr(c: *CodeGen, base: NodeIndex, true_label: Ir.Ref, false_label: Ir
|
||||
try c.genBoolExpr(data.bin.lhs, new_true_label, false_label);
|
||||
try c.builder.startBlock(new_true_label);
|
||||
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(1), ty);
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(.one, ty);
|
||||
return c.genBoolExpr(data.bin.rhs, true_label, false_label);
|
||||
},
|
||||
.bool_not_expr => {
|
||||
c.bool_invert = !c.bool_invert;
|
||||
defer c.bool_invert = !c.bool_invert;
|
||||
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(0), ty);
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(.zero, ty);
|
||||
return c.genBoolExpr(data.un, false_label, true_label);
|
||||
},
|
||||
.equal_expr => {
|
||||
@ -1102,7 +1105,7 @@ fn genBoolExpr(c: *CodeGen, base: NodeIndex, true_label: Ir.Ref, false_label: Ir
|
||||
},
|
||||
.binary_cond_expr => {
|
||||
if (c.tree.value_map.get(data.if3.cond)) |cond| {
|
||||
if (cond.getBool()) {
|
||||
if (cond.toBool(c.comp)) {
|
||||
return c.genBoolExpr(c.tree.data[data.if3.body], true_label, false_label); // then
|
||||
} else {
|
||||
return c.genBoolExpr(c.tree.data[data.if3.body + 1], true_label, false_label); // else
|
||||
@ -1113,12 +1116,12 @@ fn genBoolExpr(c: *CodeGen, base: NodeIndex, true_label: Ir.Ref, false_label: Ir
|
||||
try c.genBoolExpr(data.if3.cond, true_label, new_false_label);
|
||||
|
||||
try c.builder.startBlock(new_false_label);
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(1), ty);
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(.one, ty);
|
||||
return c.genBoolExpr(c.tree.data[data.if3.body + 1], true_label, false_label); // else
|
||||
},
|
||||
.cond_expr => {
|
||||
if (c.tree.value_map.get(data.if3.cond)) |cond| {
|
||||
if (cond.getBool()) {
|
||||
if (cond.toBool(c.comp)) {
|
||||
return c.genBoolExpr(c.tree.data[data.if3.body], true_label, false_label); // then
|
||||
} else {
|
||||
return c.genBoolExpr(c.tree.data[data.if3.body + 1], true_label, false_label); // else
|
||||
@ -1132,14 +1135,14 @@ fn genBoolExpr(c: *CodeGen, base: NodeIndex, true_label: Ir.Ref, false_label: Ir
|
||||
try c.builder.startBlock(new_true_label);
|
||||
try c.genBoolExpr(c.tree.data[data.if3.body], true_label, false_label); // then
|
||||
try c.builder.startBlock(new_false_label);
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(1), ty);
|
||||
if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(.one, ty);
|
||||
return c.genBoolExpr(c.tree.data[data.if3.body + 1], true_label, false_label); // else
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
if (c.tree.value_map.get(node)) |value| {
|
||||
if (value.getBool()) {
|
||||
if (value.toBool(c.comp)) {
|
||||
if (true_label == c.bool_end_label) {
|
||||
return c.addBoolPhi(!c.bool_invert);
|
||||
}
|
||||
@ -1154,7 +1157,7 @@ fn genBoolExpr(c: *CodeGen, base: NodeIndex, true_label: Ir.Ref, false_label: Ir
|
||||
|
||||
// Assume int operand.
|
||||
const lhs = try c.genExpr(node);
|
||||
const rhs = try c.builder.addConstant(Value.int(0), try c.genType(c.node_ty[@intFromEnum(node)]));
|
||||
const rhs = try c.builder.addConstant(.zero, try c.genType(c.node_ty[@intFromEnum(node)]));
|
||||
const cmp = try c.builder.addInst(.cmp_ne, .{ .bin = .{ .lhs = lhs, .rhs = rhs } }, .i1);
|
||||
if (c.cond_dummy_ty != null) c.cond_dummy_ref = cmp;
|
||||
try c.addBranch(cmp, true_label, false_label);
|
||||
@ -1163,7 +1166,7 @@ fn genBoolExpr(c: *CodeGen, base: NodeIndex, true_label: Ir.Ref, false_label: Ir
|
||||
fn genBuiltinCall(c: *CodeGen, builtin: Builtin, arg_nodes: []const NodeIndex, ty: Type) Error!Ir.Ref {
|
||||
_ = arg_nodes;
|
||||
_ = ty;
|
||||
return c.comp.diag.fatalNoSrc("TODO CodeGen.genBuiltinCall {s}\n", .{Builtin.nameFromTag(builtin.tag).span()});
|
||||
return c.fail("TODO CodeGen.genBuiltinCall {s}\n", .{Builtin.nameFromTag(builtin.tag).span()});
|
||||
}
|
||||
|
||||
fn genCall(c: *CodeGen, fn_node: NodeIndex, arg_nodes: []const NodeIndex, ty: Type) Error!Ir.Ref {
|
||||
@ -1188,7 +1191,7 @@ fn genCall(c: *CodeGen, fn_node: NodeIndex, arg_nodes: []const NodeIndex, ty: Ty
|
||||
},
|
||||
.decl_ref_expr => {
|
||||
const slice = c.tree.tokSlice(c.node_data[cur].decl_ref);
|
||||
const name = try c.comp.intern(slice);
|
||||
const name = try StrInt.intern(c.comp, slice);
|
||||
var i = c.symbols.items.len;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
@ -1254,7 +1257,7 @@ fn genPtrArithmetic(c: *CodeGen, ptr: Ir.Ref, offset: Ir.Ref, offset_ty: Type, t
|
||||
return c.builder.addInst(.add, .{ .bin = .{ .lhs = ptr, .rhs = offset } }, try c.genType(ty));
|
||||
}
|
||||
|
||||
const size_inst = try c.builder.addConstant(Value.int(size), try c.genType(offset_ty));
|
||||
const size_inst = try c.builder.addConstant((try Value.int(size, c.comp)).ref(), try c.genType(offset_ty));
|
||||
const offset_inst = try c.addBin(.mul, offset, size_inst, offset_ty);
|
||||
return c.addBin(.add, ptr, offset_inst, offset_ty);
|
||||
}
|
||||
@ -1269,12 +1272,12 @@ fn genInitializer(c: *CodeGen, ptr: Ir.Ref, dest_ty: Type, initializer: NodeInde
|
||||
.union_init_expr,
|
||||
.array_filler_expr,
|
||||
.default_init_expr,
|
||||
=> return c.comp.diag.fatalNoSrc("TODO CodeGen.genInitializer {}\n", .{c.node_tag[@intFromEnum(initializer)]}),
|
||||
=> return c.fail("TODO CodeGen.genInitializer {}\n", .{c.node_tag[@intFromEnum(initializer)]}),
|
||||
.string_literal_expr => {
|
||||
const val = c.tree.value_map.get(initializer).?;
|
||||
const str_ptr = try c.builder.addConstant(val, .ptr);
|
||||
const str_ptr = try c.builder.addConstant(val.ref(), .ptr);
|
||||
if (dest_ty.isArray()) {
|
||||
return c.comp.diag.fatalNoSrc("TODO memcpy\n", .{});
|
||||
return c.fail("TODO memcpy\n", .{});
|
||||
} else {
|
||||
try c.builder.addStore(ptr, str_ptr);
|
||||
}
|
||||
@ -1288,5 +1291,5 @@ fn genInitializer(c: *CodeGen, ptr: Ir.Ref, dest_ty: Type, initializer: NodeInde
|
||||
|
||||
fn genVar(c: *CodeGen, decl: NodeIndex) Error!void {
|
||||
_ = decl;
|
||||
return c.comp.diag.fatalNoSrc("TODO CodeGen.genVar\n", .{});
|
||||
return c.fail("TODO CodeGen.genVar\n", .{});
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const mem = std.mem;
|
||||
const Allocator = mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const EpochSeconds = std.time.epoch.EpochSeconds;
|
||||
const mem = std.mem;
|
||||
const Interner = @import("backend").Interner;
|
||||
const Builtins = @import("Builtins.zig");
|
||||
const Builtin = Builtins.Builtin;
|
||||
const Diagnostics = @import("Diagnostics.zig");
|
||||
@ -12,18 +13,16 @@ const Tokenizer = @import("Tokenizer.zig");
|
||||
const Token = Tokenizer.Token;
|
||||
const Type = @import("Type.zig");
|
||||
const Pragma = @import("Pragma.zig");
|
||||
const StringInterner = @import("StringInterner.zig");
|
||||
const StrInt = @import("StringInterner.zig");
|
||||
const record_layout = @import("record_layout.zig");
|
||||
const target_util = @import("target.zig");
|
||||
|
||||
const Compilation = @This();
|
||||
|
||||
pub const Error = error{
|
||||
/// A fatal error has ocurred and compilation has stopped.
|
||||
FatalError,
|
||||
} || Allocator.Error;
|
||||
|
||||
pub const bit_int_max_bits = 128;
|
||||
pub const bit_int_max_bits = std.math.maxInt(u16);
|
||||
const path_buf_stack_limit = 1024;
|
||||
|
||||
/// Environment variables used during compilation / linking.
|
||||
@ -58,12 +57,12 @@ pub const Environment = struct {
|
||||
|
||||
/// Load all of the environment variables using the std.process API. Do not use if using Aro as a shared library on Linux without libc
|
||||
/// See https://github.com/ziglang/zig/issues/4524
|
||||
/// Assumes that `self` has been default-initialized
|
||||
pub fn loadAll(self: *Environment, allocator: std.mem.Allocator) !void {
|
||||
errdefer self.deinit(allocator);
|
||||
pub fn loadAll(allocator: std.mem.Allocator) !Environment {
|
||||
var env: Environment = .{};
|
||||
errdefer env.deinit(allocator);
|
||||
|
||||
inline for (@typeInfo(@TypeOf(self.*)).Struct.fields) |field| {
|
||||
std.debug.assert(@field(self, field.name) == null);
|
||||
inline for (@typeInfo(@TypeOf(env)).Struct.fields) |field| {
|
||||
std.debug.assert(@field(env, field.name) == null);
|
||||
|
||||
var env_var_buf: [field.name.len]u8 = undefined;
|
||||
const env_var_name = std.ascii.upperString(&env_var_buf, field.name);
|
||||
@ -72,8 +71,9 @@ pub const Environment = struct {
|
||||
error.EnvironmentVariableNotFound => null,
|
||||
error.InvalidUtf8 => null,
|
||||
};
|
||||
@field(self, field.name) = val;
|
||||
@field(env, field.name) = val;
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
/// Use this only if environment slices were allocated with `allocator` (such as via `loadAll`)
|
||||
@ -87,16 +87,19 @@ pub const Environment = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const Compilation = @This();
|
||||
|
||||
gpa: Allocator,
|
||||
diagnostics: Diagnostics,
|
||||
|
||||
environment: Environment = .{},
|
||||
sources: std.StringArrayHashMap(Source),
|
||||
diag: Diagnostics,
|
||||
include_dirs: std.ArrayList([]const u8),
|
||||
system_include_dirs: std.ArrayList([]const u8),
|
||||
sources: std.StringArrayHashMapUnmanaged(Source) = .{},
|
||||
include_dirs: std.ArrayListUnmanaged([]const u8) = .{},
|
||||
system_include_dirs: std.ArrayListUnmanaged([]const u8) = .{},
|
||||
target: std.Target = @import("builtin").target,
|
||||
pragma_handlers: std.StringArrayHashMap(*Pragma),
|
||||
pragma_handlers: std.StringArrayHashMapUnmanaged(*Pragma) = .{},
|
||||
langopts: LangOpts = .{},
|
||||
generated_buf: std.ArrayList(u8),
|
||||
generated_buf: std.ArrayListUnmanaged(u8) = .{},
|
||||
builtins: Builtins = .{},
|
||||
types: struct {
|
||||
wchar: Type = undefined,
|
||||
@ -122,21 +125,31 @@ types: struct {
|
||||
int16: Type = .{ .specifier = .invalid },
|
||||
int64: Type = .{ .specifier = .invalid },
|
||||
} = .{},
|
||||
string_interner: StringInterner = .{},
|
||||
string_interner: StrInt = .{},
|
||||
interner: Interner = .{},
|
||||
ms_cwd_source_id: ?Source.Id = null,
|
||||
|
||||
pub fn init(gpa: Allocator) Compilation {
|
||||
return .{
|
||||
.gpa = gpa,
|
||||
.sources = std.StringArrayHashMap(Source).init(gpa),
|
||||
.diag = Diagnostics.init(gpa),
|
||||
.include_dirs = std.ArrayList([]const u8).init(gpa),
|
||||
.system_include_dirs = std.ArrayList([]const u8).init(gpa),
|
||||
.pragma_handlers = std.StringArrayHashMap(*Pragma).init(gpa),
|
||||
.generated_buf = std.ArrayList(u8).init(gpa),
|
||||
.diagnostics = Diagnostics.init(gpa),
|
||||
};
|
||||
}
|
||||
|
||||
/// Initialize Compilation with default environment,
|
||||
/// pragma handlers and emulation mode set to target.
|
||||
pub fn initDefault(gpa: Allocator) !Compilation {
|
||||
var comp: Compilation = .{
|
||||
.gpa = gpa,
|
||||
.environment = try Environment.loadAll(gpa),
|
||||
.diagnostics = Diagnostics.init(gpa),
|
||||
};
|
||||
errdefer comp.deinit();
|
||||
try comp.addDefaultPragmaHandlers();
|
||||
comp.langopts.setEmulatedCompiler(target_util.systemCompiler(comp.target));
|
||||
return comp;
|
||||
}
|
||||
|
||||
pub fn deinit(comp: *Compilation) void {
|
||||
for (comp.pragma_handlers.values()) |pragma| {
|
||||
pragma.deinit(pragma, comp);
|
||||
@ -146,19 +159,17 @@ pub fn deinit(comp: *Compilation) void {
|
||||
comp.gpa.free(source.buf);
|
||||
comp.gpa.free(source.splice_locs);
|
||||
}
|
||||
comp.sources.deinit();
|
||||
comp.diag.deinit();
|
||||
comp.include_dirs.deinit();
|
||||
comp.sources.deinit(comp.gpa);
|
||||
comp.diagnostics.deinit();
|
||||
comp.include_dirs.deinit(comp.gpa);
|
||||
for (comp.system_include_dirs.items) |path| comp.gpa.free(path);
|
||||
comp.system_include_dirs.deinit();
|
||||
comp.pragma_handlers.deinit();
|
||||
comp.generated_buf.deinit();
|
||||
comp.system_include_dirs.deinit(comp.gpa);
|
||||
comp.pragma_handlers.deinit(comp.gpa);
|
||||
comp.generated_buf.deinit(comp.gpa);
|
||||
comp.builtins.deinit(comp.gpa);
|
||||
comp.string_interner.deinit(comp.gpa);
|
||||
}
|
||||
|
||||
pub fn intern(comp: *Compilation, str: []const u8) !StringInterner.StringId {
|
||||
return comp.string_interner.intern(comp.gpa, str);
|
||||
comp.interner.deinit(comp.gpa);
|
||||
comp.environment.deinit(comp.gpa);
|
||||
}
|
||||
|
||||
pub fn getSourceEpoch(self: *const Compilation, max: i64) !?i64 {
|
||||
@ -173,7 +184,7 @@ const max_timestamp = 253402300799;
|
||||
|
||||
fn getTimestamp(comp: *Compilation) !u47 {
|
||||
const provided: ?i64 = comp.getSourceEpoch(max_timestamp) catch blk: {
|
||||
try comp.diag.add(.{
|
||||
try comp.addDiagnostic(.{
|
||||
.tag = .invalid_source_epoch,
|
||||
.loc = .{ .id = .unused, .byte_offset = 0, .line = 0 },
|
||||
}, &.{});
|
||||
@ -219,32 +230,15 @@ fn generateDateAndTime(w: anytype, timestamp: u47) !void {
|
||||
});
|
||||
}
|
||||
|
||||
/// Generate builtin macros that will be available to each source file.
|
||||
pub fn generateBuiltinMacros(comp: *Compilation) !Source {
|
||||
try comp.generateBuiltinTypes();
|
||||
/// Which set of system defines to generate via generateBuiltinMacros
|
||||
pub const SystemDefinesMode = enum {
|
||||
/// Only define macros required by the C standard (date/time macros and those beginning with `__STDC`)
|
||||
no_system_defines,
|
||||
/// Define the standard set of system macros
|
||||
include_system_defines,
|
||||
};
|
||||
|
||||
var buf = std.ArrayList(u8).init(comp.gpa);
|
||||
defer buf.deinit();
|
||||
const w = buf.writer();
|
||||
|
||||
// standard macros
|
||||
try w.writeAll(
|
||||
\\#define __VERSION__ "Aro
|
||||
++ @import("lib.zig").version_str ++ "\"\n" ++
|
||||
\\#define __Aro__
|
||||
\\#define __STDC__ 1
|
||||
\\#define __STDC_HOSTED__ 1
|
||||
\\#define __STDC_NO_ATOMICS__ 1
|
||||
\\#define __STDC_NO_COMPLEX__ 1
|
||||
\\#define __STDC_NO_THREADS__ 1
|
||||
\\#define __STDC_NO_VLA__ 1
|
||||
\\#define __STDC_UTF_16__ 1
|
||||
\\#define __STDC_UTF_32__ 1
|
||||
\\
|
||||
);
|
||||
if (comp.langopts.standard.StdCVersionMacro()) |stdc_version| {
|
||||
try w.print("#define __STDC_VERSION__ {s}\n", .{stdc_version});
|
||||
}
|
||||
fn generateSystemDefines(comp: *Compilation, w: anytype) !void {
|
||||
const ptr_width = comp.target.ptrBitWidth();
|
||||
|
||||
// os macros
|
||||
@ -414,10 +408,6 @@ pub fn generateBuiltinMacros(comp: *Compilation) !Source {
|
||||
\\
|
||||
);
|
||||
|
||||
// timestamps
|
||||
const timestamp = try comp.getTimestamp();
|
||||
try generateDateAndTime(w, timestamp);
|
||||
|
||||
// types
|
||||
if (comp.getCharSignedness() == .unsigned) try w.writeAll("#define __CHAR_UNSIGNED__ 1\n");
|
||||
try w.writeAll("#define __CHAR_BIT__ 8\n");
|
||||
@ -489,6 +479,49 @@ pub fn generateBuiltinMacros(comp: *Compilation) !Source {
|
||||
\\#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
/// Generate builtin macros that will be available to each source file.
|
||||
pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefinesMode) !Source {
|
||||
try comp.generateBuiltinTypes();
|
||||
|
||||
var buf = std.ArrayList(u8).init(comp.gpa);
|
||||
defer buf.deinit();
|
||||
|
||||
if (system_defines_mode == .include_system_defines) {
|
||||
try buf.appendSlice(
|
||||
\\#define __VERSION__ "Aro
|
||||
++ @import("backend").version_str ++ "\"\n" ++
|
||||
\\#define __Aro__
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
// standard macros
|
||||
try buf.appendSlice(
|
||||
\\#define __STDC__ 1
|
||||
\\#define __STDC_HOSTED__ 1
|
||||
\\#define __STDC_NO_ATOMICS__ 1
|
||||
\\#define __STDC_NO_COMPLEX__ 1
|
||||
\\#define __STDC_NO_THREADS__ 1
|
||||
\\#define __STDC_NO_VLA__ 1
|
||||
\\#define __STDC_UTF_16__ 1
|
||||
\\#define __STDC_UTF_32__ 1
|
||||
\\
|
||||
);
|
||||
if (comp.langopts.standard.StdCVersionMacro()) |stdc_version| {
|
||||
try buf.appendSlice("#define __STDC_VERSION__ ");
|
||||
try buf.appendSlice(stdc_version);
|
||||
try buf.append('\n');
|
||||
}
|
||||
|
||||
// timestamps
|
||||
const timestamp = try comp.getTimestamp();
|
||||
try generateDateAndTime(buf.writer(), timestamp);
|
||||
|
||||
if (system_defines_mode == .include_system_defines) {
|
||||
try comp.generateSystemDefines(buf.writer());
|
||||
}
|
||||
|
||||
return comp.addSourceFromBuffer("<builtin>", buf.items);
|
||||
}
|
||||
@ -573,7 +606,7 @@ fn generateFloatMacros(w: anytype, prefix: []const u8, semantics: target_util.FP
|
||||
try w.print("#define {s}MIN__ {s}{s}\n", .{ prefix_slice, min, ext });
|
||||
}
|
||||
|
||||
fn generateTypeMacro(w: anytype, mapper: StringInterner.TypeMapper, name: []const u8, ty: Type, langopts: LangOpts) !void {
|
||||
fn generateTypeMacro(w: anytype, mapper: StrInt.TypeMapper, name: []const u8, ty: Type, langopts: LangOpts) !void {
|
||||
try w.print("#define {s} ", .{name});
|
||||
try ty.print(mapper, langopts, w);
|
||||
try w.writeByte('\n');
|
||||
@ -661,7 +694,7 @@ fn intSize(comp: *const Compilation, specifier: Type.Specifier) u64 {
|
||||
return ty.sizeof(comp).?;
|
||||
}
|
||||
|
||||
fn generateExactWidthTypes(comp: *const Compilation, w: anytype, mapper: StringInterner.TypeMapper) !void {
|
||||
fn generateExactWidthTypes(comp: *const Compilation, w: anytype, mapper: StrInt.TypeMapper) !void {
|
||||
try comp.generateExactWidthType(w, mapper, .schar);
|
||||
|
||||
if (comp.intSize(.short) > comp.intSize(.char)) {
|
||||
@ -726,7 +759,7 @@ fn generateSuffixMacro(comp: *const Compilation, prefix: []const u8, w: anytype,
|
||||
/// Name macro (e.g. #define __UINT32_TYPE__ unsigned int)
|
||||
/// Format strings (e.g. #define __UINT32_FMTu__ "u")
|
||||
/// Suffix macro (e.g. #define __UINT32_C_SUFFIX__ U)
|
||||
fn generateExactWidthType(comp: *const Compilation, w: anytype, mapper: StringInterner.TypeMapper, specifier: Type.Specifier) !void {
|
||||
fn generateExactWidthType(comp: *const Compilation, w: anytype, mapper: StrInt.TypeMapper, specifier: Type.Specifier) !void {
|
||||
var ty = Type{ .specifier = specifier };
|
||||
const width = 8 * ty.sizeof(comp).?;
|
||||
const unsigned = ty.isUnsignedInt(comp);
|
||||
@ -751,13 +784,17 @@ fn generateExactWidthType(comp: *const Compilation, w: anytype, mapper: StringIn
|
||||
try comp.generateSuffixMacro(prefix.constSlice(), w, ty);
|
||||
}
|
||||
|
||||
pub fn hasFloat128(comp: *const Compilation) bool {
|
||||
return target_util.hasFloat128(comp.target);
|
||||
}
|
||||
|
||||
pub fn hasHalfPrecisionFloatABI(comp: *const Compilation) bool {
|
||||
return comp.langopts.allow_half_args_and_returns or target_util.hasHalfPrecisionFloatABI(comp.target);
|
||||
}
|
||||
|
||||
fn generateNsConstantStringType(comp: *Compilation) !void {
|
||||
comp.types.ns_constant_string.record = .{
|
||||
.name = try comp.intern("__NSConstantString_tag"),
|
||||
.name = try StrInt.intern(comp, "__NSConstantString_tag"),
|
||||
.fields = &comp.types.ns_constant_string.fields,
|
||||
.field_attributes = null,
|
||||
.type_layout = undefined,
|
||||
@ -765,10 +802,10 @@ fn generateNsConstantStringType(comp: *Compilation) !void {
|
||||
const const_int_ptr = Type{ .specifier = .pointer, .data = .{ .sub_type = &comp.types.ns_constant_string.int_ty } };
|
||||
const const_char_ptr = Type{ .specifier = .pointer, .data = .{ .sub_type = &comp.types.ns_constant_string.char_ty } };
|
||||
|
||||
comp.types.ns_constant_string.fields[0] = .{ .name = try comp.intern("isa"), .ty = const_int_ptr };
|
||||
comp.types.ns_constant_string.fields[1] = .{ .name = try comp.intern("flags"), .ty = .{ .specifier = .int } };
|
||||
comp.types.ns_constant_string.fields[2] = .{ .name = try comp.intern("str"), .ty = const_char_ptr };
|
||||
comp.types.ns_constant_string.fields[3] = .{ .name = try comp.intern("length"), .ty = .{ .specifier = .long } };
|
||||
comp.types.ns_constant_string.fields[0] = .{ .name = try StrInt.intern(comp, "isa"), .ty = const_int_ptr };
|
||||
comp.types.ns_constant_string.fields[1] = .{ .name = try StrInt.intern(comp, "flags"), .ty = .{ .specifier = .int } };
|
||||
comp.types.ns_constant_string.fields[2] = .{ .name = try StrInt.intern(comp, "str"), .ty = const_char_ptr };
|
||||
comp.types.ns_constant_string.fields[3] = .{ .name = try StrInt.intern(comp, "length"), .ty = .{ .specifier = .long } };
|
||||
comp.types.ns_constant_string.ty = .{ .specifier = .@"struct", .data = .{ .record = &comp.types.ns_constant_string.record } };
|
||||
record_layout.compute(&comp.types.ns_constant_string.record, comp.types.ns_constant_string.ty, comp, null);
|
||||
}
|
||||
@ -795,7 +832,7 @@ fn generateVaListType(comp: *Compilation) !Type {
|
||||
};
|
||||
|
||||
// TODO this might be bad?
|
||||
const arena = comp.diag.arena.allocator();
|
||||
const arena = comp.diagnostics.arena.allocator();
|
||||
|
||||
var ty: Type = undefined;
|
||||
switch (kind) {
|
||||
@ -804,7 +841,7 @@ fn generateVaListType(comp: *Compilation) !Type {
|
||||
.aarch64_va_list => {
|
||||
const record_ty = try arena.create(Type.Record);
|
||||
record_ty.* = .{
|
||||
.name = try comp.intern("__va_list_tag"),
|
||||
.name = try StrInt.intern(comp, "__va_list_tag"),
|
||||
.fields = try arena.alloc(Type.Record.Field, 5),
|
||||
.field_attributes = null,
|
||||
.type_layout = undefined, // computed below
|
||||
@ -812,18 +849,18 @@ fn generateVaListType(comp: *Compilation) !Type {
|
||||
const void_ty = try arena.create(Type);
|
||||
void_ty.* = .{ .specifier = .void };
|
||||
const void_ptr = Type{ .specifier = .pointer, .data = .{ .sub_type = void_ty } };
|
||||
record_ty.fields[0] = .{ .name = try comp.intern("__stack"), .ty = void_ptr };
|
||||
record_ty.fields[1] = .{ .name = try comp.intern("__gr_top"), .ty = void_ptr };
|
||||
record_ty.fields[2] = .{ .name = try comp.intern("__vr_top"), .ty = void_ptr };
|
||||
record_ty.fields[3] = .{ .name = try comp.intern("__gr_offs"), .ty = .{ .specifier = .int } };
|
||||
record_ty.fields[4] = .{ .name = try comp.intern("__vr_offs"), .ty = .{ .specifier = .int } };
|
||||
record_ty.fields[0] = .{ .name = try StrInt.intern(comp, "__stack"), .ty = void_ptr };
|
||||
record_ty.fields[1] = .{ .name = try StrInt.intern(comp, "__gr_top"), .ty = void_ptr };
|
||||
record_ty.fields[2] = .{ .name = try StrInt.intern(comp, "__vr_top"), .ty = void_ptr };
|
||||
record_ty.fields[3] = .{ .name = try StrInt.intern(comp, "__gr_offs"), .ty = .{ .specifier = .int } };
|
||||
record_ty.fields[4] = .{ .name = try StrInt.intern(comp, "__vr_offs"), .ty = .{ .specifier = .int } };
|
||||
ty = .{ .specifier = .@"struct", .data = .{ .record = record_ty } };
|
||||
record_layout.compute(record_ty, ty, comp, null);
|
||||
},
|
||||
.x86_64_va_list => {
|
||||
const record_ty = try arena.create(Type.Record);
|
||||
record_ty.* = .{
|
||||
.name = try comp.intern("__va_list_tag"),
|
||||
.name = try StrInt.intern(comp, "__va_list_tag"),
|
||||
.fields = try arena.alloc(Type.Record.Field, 4),
|
||||
.field_attributes = null,
|
||||
.type_layout = undefined, // computed below
|
||||
@ -831,10 +868,10 @@ fn generateVaListType(comp: *Compilation) !Type {
|
||||
const void_ty = try arena.create(Type);
|
||||
void_ty.* = .{ .specifier = .void };
|
||||
const void_ptr = Type{ .specifier = .pointer, .data = .{ .sub_type = void_ty } };
|
||||
record_ty.fields[0] = .{ .name = try comp.intern("gp_offset"), .ty = .{ .specifier = .uint } };
|
||||
record_ty.fields[1] = .{ .name = try comp.intern("fp_offset"), .ty = .{ .specifier = .uint } };
|
||||
record_ty.fields[2] = .{ .name = try comp.intern("overflow_arg_area"), .ty = void_ptr };
|
||||
record_ty.fields[3] = .{ .name = try comp.intern("reg_save_area"), .ty = void_ptr };
|
||||
record_ty.fields[0] = .{ .name = try StrInt.intern(comp, "gp_offset"), .ty = .{ .specifier = .uint } };
|
||||
record_ty.fields[1] = .{ .name = try StrInt.intern(comp, "fp_offset"), .ty = .{ .specifier = .uint } };
|
||||
record_ty.fields[2] = .{ .name = try StrInt.intern(comp, "overflow_arg_area"), .ty = void_ptr };
|
||||
record_ty.fields[3] = .{ .name = try StrInt.intern(comp, "reg_save_area"), .ty = void_ptr };
|
||||
ty = .{ .specifier = .@"struct", .data = .{ .record = record_ty } };
|
||||
record_layout.compute(record_ty, ty, comp, null);
|
||||
},
|
||||
@ -932,7 +969,7 @@ pub fn defineSystemIncludes(comp: *Compilation, aro_dir: []const u8) !void {
|
||||
base_dir.access("include/stddef.h", .{}) catch continue;
|
||||
const path = try std.fs.path.join(comp.gpa, &.{ dirname, "include" });
|
||||
errdefer comp.gpa.free(path);
|
||||
try comp.system_include_dirs.append(path);
|
||||
try comp.system_include_dirs.append(comp.gpa, path);
|
||||
break;
|
||||
} else return error.AroIncludeNotFound;
|
||||
|
||||
@ -946,12 +983,12 @@ pub fn defineSystemIncludes(comp: *Compilation, aro_dir: []const u8) !void {
|
||||
if (!std.meta.isError(std.fs.accessAbsolute(multiarch_path, .{}))) {
|
||||
const duped = try comp.gpa.dupe(u8, multiarch_path);
|
||||
errdefer comp.gpa.free(duped);
|
||||
try comp.system_include_dirs.append(duped);
|
||||
try comp.system_include_dirs.append(comp.gpa, duped);
|
||||
}
|
||||
}
|
||||
const usr_include = try comp.gpa.dupe(u8, "/usr/include");
|
||||
errdefer comp.gpa.free(usr_include);
|
||||
try comp.system_include_dirs.append(usr_include);
|
||||
try comp.system_include_dirs.append(comp.gpa, usr_include);
|
||||
}
|
||||
|
||||
pub fn getSource(comp: *const Compilation, id: Source.Id) Source {
|
||||
@ -980,7 +1017,7 @@ pub fn addSourceFromReader(comp: *Compilation, reader: anytype, path: []const u8
|
||||
/// To add the contents of an arbitrary reader as a Source, see addSourceFromReader
|
||||
/// To add a file's contents given its path, see addSourceFromPath
|
||||
pub fn addSourceFromOwnedBuffer(comp: *Compilation, buf: []u8, path: []const u8, kind: Source.Kind) !Source {
|
||||
try comp.sources.ensureUnusedCapacity(1);
|
||||
try comp.sources.ensureUnusedCapacity(comp.gpa, 1);
|
||||
|
||||
var contents = buf;
|
||||
const duped_path = try comp.gpa.dupe(u8, path);
|
||||
@ -1022,7 +1059,7 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, buf: []u8, path: []const u8,
|
||||
i = backslash_loc;
|
||||
try splice_list.append(i);
|
||||
if (state == .trailing_ws) {
|
||||
try comp.diag.add(.{
|
||||
try comp.addDiagnostic(.{
|
||||
.tag = .backslash_newline_escape,
|
||||
.loc = .{ .id = source_id, .byte_offset = i, .line = line },
|
||||
}, &.{});
|
||||
@ -1046,7 +1083,7 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, buf: []u8, path: []const u8,
|
||||
try splice_list.append(i);
|
||||
}
|
||||
if (state == .trailing_ws) {
|
||||
try comp.diag.add(.{
|
||||
try comp.addDiagnostic(.{
|
||||
.tag = .backslash_newline_escape,
|
||||
.loc = .{ .id = source_id, .byte_offset = i, .line = line },
|
||||
}, &.{});
|
||||
@ -1105,7 +1142,7 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, buf: []u8, path: []const u8,
|
||||
if (i != contents.len) contents = try comp.gpa.realloc(contents, i);
|
||||
errdefer @compileError("errdefers in callers would possibly free the realloced slice using the original len");
|
||||
|
||||
var source = Source{
|
||||
const source = Source{
|
||||
.id = source_id,
|
||||
.path = duped_path,
|
||||
.buf = contents,
|
||||
@ -1259,7 +1296,7 @@ pub const IncludeType = enum {
|
||||
angle_brackets,
|
||||
};
|
||||
|
||||
fn getFileContents(comp: *Compilation, path: []const u8) ![]const u8 {
|
||||
fn getFileContents(comp: *Compilation, path: []const u8, limit: ?u32) ![]const u8 {
|
||||
if (mem.indexOfScalar(u8, path, 0) != null) {
|
||||
return error.FileNotFound;
|
||||
}
|
||||
@ -1267,7 +1304,16 @@ fn getFileContents(comp: *Compilation, path: []const u8) ![]const u8 {
|
||||
const file = try std.fs.cwd().openFile(path, .{});
|
||||
defer file.close();
|
||||
|
||||
return file.readToEndAlloc(comp.gpa, std.math.maxInt(u32));
|
||||
var buf = std.ArrayList(u8).init(comp.gpa);
|
||||
defer buf.deinit();
|
||||
|
||||
const max = limit orelse std.math.maxInt(u32);
|
||||
file.reader().readAllArrayList(&buf, max) catch |e| switch (e) {
|
||||
error.StreamTooLong => if (limit == null) return e,
|
||||
else => return e,
|
||||
};
|
||||
|
||||
return buf.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn findEmbed(
|
||||
@ -1276,9 +1322,10 @@ pub fn findEmbed(
|
||||
includer_token_source: Source.Id,
|
||||
/// angle bracket vs quotes
|
||||
include_type: IncludeType,
|
||||
limit: ?u32,
|
||||
) !?[]const u8 {
|
||||
if (std.fs.path.isAbsolute(filename)) {
|
||||
return if (comp.getFileContents(filename)) |some|
|
||||
return if (comp.getFileContents(filename, limit)) |some|
|
||||
some
|
||||
else |err| switch (err) {
|
||||
error.OutOfMemory => |e| return e,
|
||||
@ -1295,7 +1342,7 @@ pub fn findEmbed(
|
||||
|
||||
while (try it.nextWithFile(filename, stack_fallback.get())) |found| {
|
||||
defer stack_fallback.get().free(found.path);
|
||||
if (comp.getFileContents(found.path)) |some|
|
||||
if (comp.getFileContents(found.path, limit)) |some|
|
||||
return some
|
||||
else |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
@ -1342,7 +1389,7 @@ pub fn findInclude(
|
||||
defer stack_fallback.get().free(found.path);
|
||||
if (comp.addSourceFromPathExtra(found.path, found.kind)) |some| {
|
||||
if (it.tried_ms_cwd) {
|
||||
try comp.diag.add(.{
|
||||
try comp.addDiagnostic(.{
|
||||
.tag = .ms_search_rule,
|
||||
.extra = .{ .str = some.path },
|
||||
.loc = .{
|
||||
@ -1362,7 +1409,7 @@ pub fn findInclude(
|
||||
}
|
||||
|
||||
pub fn addPragmaHandler(comp: *Compilation, name: []const u8, handler: *Pragma) Allocator.Error!void {
|
||||
try comp.pragma_handlers.putNoClobber(name, handler);
|
||||
try comp.pragma_handlers.putNoClobber(comp.gpa, name, handler);
|
||||
}
|
||||
|
||||
pub fn addDefaultPragmaHandlers(comp: *Compilation) Allocator.Error!void {
|
||||
@ -1444,7 +1491,7 @@ pub const CharUnitSize = enum(u32) {
|
||||
}
|
||||
};
|
||||
|
||||
pub const renderErrors = Diagnostics.render;
|
||||
pub const addDiagnostic = Diagnostics.add;
|
||||
|
||||
test "addSourceFromReader" {
|
||||
const Test = struct {
|
||||
@ -1456,7 +1503,7 @@ test "addSourceFromReader" {
|
||||
const source = try comp.addSourceFromReader(buf_reader.reader(), "path", .user);
|
||||
|
||||
try std.testing.expectEqualStrings(expected, source.buf);
|
||||
try std.testing.expectEqual(warning_count, @as(u32, @intCast(comp.diag.list.items.len)));
|
||||
try std.testing.expectEqual(warning_count, @as(u32, @intCast(comp.diagnostics.list.items.len)));
|
||||
try std.testing.expectEqualSlices(u32, splices, source.splice_locs);
|
||||
}
|
||||
|
||||
588
deps/aro/aro/Diagnostics.zig
vendored
Normal file
588
deps/aro/aro/Diagnostics.zig
vendored
Normal file
@ -0,0 +1,588 @@
|
||||
const std = @import("std");
|
||||
const Allocator = mem.Allocator;
|
||||
const mem = std.mem;
|
||||
const Source = @import("Source.zig");
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Attribute = @import("Attribute.zig");
|
||||
const Builtins = @import("Builtins.zig");
|
||||
const Builtin = Builtins.Builtin;
|
||||
const Header = @import("Builtins/Properties.zig").Header;
|
||||
const Tree = @import("Tree.zig");
|
||||
const is_windows = @import("builtin").os.tag == .windows;
|
||||
const LangOpts = @import("LangOpts.zig");
|
||||
|
||||
pub const Message = struct {
|
||||
tag: Tag,
|
||||
kind: Kind = undefined,
|
||||
loc: Source.Location = .{},
|
||||
extra: Extra = .{ .none = {} },
|
||||
|
||||
pub const Extra = union {
|
||||
str: []const u8,
|
||||
tok_id: struct {
|
||||
expected: Tree.Token.Id,
|
||||
actual: Tree.Token.Id,
|
||||
},
|
||||
tok_id_expected: Tree.Token.Id,
|
||||
arguments: struct {
|
||||
expected: u32,
|
||||
actual: u32,
|
||||
},
|
||||
codepoints: struct {
|
||||
actual: u21,
|
||||
resembles: u21,
|
||||
},
|
||||
attr_arg_count: struct {
|
||||
attribute: Attribute.Tag,
|
||||
expected: u32,
|
||||
},
|
||||
attr_arg_type: struct {
|
||||
expected: Attribute.ArgumentType,
|
||||
actual: Attribute.ArgumentType,
|
||||
},
|
||||
attr_enum: struct {
|
||||
tag: Attribute.Tag,
|
||||
},
|
||||
ignored_record_attr: struct {
|
||||
tag: Attribute.Tag,
|
||||
specifier: enum { @"struct", @"union", @"enum" },
|
||||
},
|
||||
builtin_with_header: struct {
|
||||
builtin: Builtin.Tag,
|
||||
header: Header,
|
||||
},
|
||||
invalid_escape: struct {
|
||||
offset: u32,
|
||||
char: u8,
|
||||
},
|
||||
actual_codepoint: u21,
|
||||
ascii: u7,
|
||||
unsigned: u64,
|
||||
offset: u64,
|
||||
pow_2_as_string: u8,
|
||||
signed: i64,
|
||||
normalized: []const u8,
|
||||
none: void,
|
||||
};
|
||||
};
|
||||
|
||||
const Properties = struct {
|
||||
msg: []const u8,
|
||||
kind: Kind,
|
||||
extra: std.meta.FieldEnum(Message.Extra) = .none,
|
||||
opt: ?u8 = null,
|
||||
all: bool = false,
|
||||
w_extra: bool = false,
|
||||
pedantic: bool = false,
|
||||
suppress_version: ?LangOpts.Standard = null,
|
||||
suppress_unless_version: ?LangOpts.Standard = null,
|
||||
suppress_gnu: bool = false,
|
||||
suppress_gcc: bool = false,
|
||||
suppress_clang: bool = false,
|
||||
suppress_msvc: bool = false,
|
||||
|
||||
pub fn makeOpt(comptime str: []const u8) u16 {
|
||||
return @offsetOf(Options, str);
|
||||
}
|
||||
pub fn getKind(prop: Properties, options: *Options) Kind {
|
||||
const opt = @as([*]Kind, @ptrCast(options))[prop.opt orelse return prop.kind];
|
||||
if (opt == .default) return prop.kind;
|
||||
return opt;
|
||||
}
|
||||
pub const max_bits = Compilation.bit_int_max_bits;
|
||||
};
|
||||
|
||||
pub const Tag = @import("Diagnostics/messages.def").with(Properties).Tag;
|
||||
|
||||
pub const Kind = enum { @"fatal error", @"error", note, warning, off, default };
|
||||
|
||||
pub const Options = struct {
|
||||
// do not directly use these, instead add `const NAME = true;`
|
||||
all: Kind = .default,
|
||||
extra: Kind = .default,
|
||||
pedantic: Kind = .default,
|
||||
|
||||
@"unsupported-pragma": Kind = .default,
|
||||
@"c99-extensions": Kind = .default,
|
||||
@"implicit-int": Kind = .default,
|
||||
@"duplicate-decl-specifier": Kind = .default,
|
||||
@"missing-declaration": Kind = .default,
|
||||
@"extern-initializer": Kind = .default,
|
||||
@"implicit-function-declaration": Kind = .default,
|
||||
@"unused-value": Kind = .default,
|
||||
@"unreachable-code": Kind = .default,
|
||||
@"unknown-warning-option": Kind = .default,
|
||||
@"gnu-empty-struct": Kind = .default,
|
||||
@"gnu-alignof-expression": Kind = .default,
|
||||
@"macro-redefined": Kind = .default,
|
||||
@"generic-qual-type": Kind = .default,
|
||||
multichar: Kind = .default,
|
||||
@"pointer-integer-compare": Kind = .default,
|
||||
@"compare-distinct-pointer-types": Kind = .default,
|
||||
@"literal-conversion": Kind = .default,
|
||||
@"cast-qualifiers": Kind = .default,
|
||||
@"array-bounds": Kind = .default,
|
||||
@"int-conversion": Kind = .default,
|
||||
@"pointer-type-mismatch": Kind = .default,
|
||||
@"c23-extensions": Kind = .default,
|
||||
@"incompatible-pointer-types": Kind = .default,
|
||||
@"excess-initializers": Kind = .default,
|
||||
@"division-by-zero": Kind = .default,
|
||||
@"initializer-overrides": Kind = .default,
|
||||
@"incompatible-pointer-types-discards-qualifiers": Kind = .default,
|
||||
@"unknown-attributes": Kind = .default,
|
||||
@"ignored-attributes": Kind = .default,
|
||||
@"builtin-macro-redefined": Kind = .default,
|
||||
@"gnu-label-as-value": Kind = .default,
|
||||
@"malformed-warning-check": Kind = .default,
|
||||
@"#pragma-messages": Kind = .default,
|
||||
@"newline-eof": Kind = .default,
|
||||
@"empty-translation-unit": Kind = .default,
|
||||
@"implicitly-unsigned-literal": Kind = .default,
|
||||
@"c99-compat": Kind = .default,
|
||||
@"unicode-zero-width": Kind = .default,
|
||||
@"unicode-homoglyph": Kind = .default,
|
||||
unicode: Kind = .default,
|
||||
@"return-type": Kind = .default,
|
||||
@"dollar-in-identifier-extension": Kind = .default,
|
||||
@"unknown-pragmas": Kind = .default,
|
||||
@"predefined-identifier-outside-function": Kind = .default,
|
||||
@"many-braces-around-scalar-init": Kind = .default,
|
||||
uninitialized: Kind = .default,
|
||||
@"gnu-statement-expression": Kind = .default,
|
||||
@"gnu-imaginary-constant": Kind = .default,
|
||||
@"gnu-complex-integer": Kind = .default,
|
||||
@"ignored-qualifiers": Kind = .default,
|
||||
@"integer-overflow": Kind = .default,
|
||||
@"extra-semi": Kind = .default,
|
||||
@"gnu-binary-literal": Kind = .default,
|
||||
@"variadic-macros": Kind = .default,
|
||||
varargs: Kind = .default,
|
||||
@"#warnings": Kind = .default,
|
||||
@"deprecated-declarations": Kind = .default,
|
||||
@"backslash-newline-escape": Kind = .default,
|
||||
@"pointer-to-int-cast": Kind = .default,
|
||||
@"gnu-case-range": Kind = .default,
|
||||
@"c++-compat": Kind = .default,
|
||||
vla: Kind = .default,
|
||||
@"float-overflow-conversion": Kind = .default,
|
||||
@"float-zero-conversion": Kind = .default,
|
||||
@"float-conversion": Kind = .default,
|
||||
@"gnu-folding-constant": Kind = .default,
|
||||
undef: Kind = .default,
|
||||
@"ignored-pragmas": Kind = .default,
|
||||
@"gnu-include-next": Kind = .default,
|
||||
@"include-next-outside-header": Kind = .default,
|
||||
@"include-next-absolute-path": Kind = .default,
|
||||
@"enum-too-large": Kind = .default,
|
||||
@"fixed-enum-extension": Kind = .default,
|
||||
@"designated-init": Kind = .default,
|
||||
@"attribute-warning": Kind = .default,
|
||||
@"invalid-noreturn": Kind = .default,
|
||||
@"zero-length-array": Kind = .default,
|
||||
@"old-style-flexible-struct": Kind = .default,
|
||||
@"gnu-zero-variadic-macro-arguments": Kind = .default,
|
||||
@"main-return-type": Kind = .default,
|
||||
@"expansion-to-defined": Kind = .default,
|
||||
@"bit-int-extension": Kind = .default,
|
||||
@"keyword-macro": Kind = .default,
|
||||
@"pointer-arith": Kind = .default,
|
||||
@"sizeof-array-argument": Kind = .default,
|
||||
@"pre-c23-compat": Kind = .default,
|
||||
@"pointer-bool-conversion": Kind = .default,
|
||||
@"string-conversion": Kind = .default,
|
||||
@"gnu-auto-type": Kind = .default,
|
||||
@"gnu-union-cast": Kind = .default,
|
||||
@"pointer-sign": Kind = .default,
|
||||
@"fuse-ld-path": Kind = .default,
|
||||
@"language-extension-token": Kind = .default,
|
||||
@"complex-component-init": Kind = .default,
|
||||
@"microsoft-include": Kind = .default,
|
||||
@"microsoft-end-of-file": Kind = .default,
|
||||
@"invalid-source-encoding": Kind = .default,
|
||||
@"four-char-constants": Kind = .default,
|
||||
@"unknown-escape-sequence": Kind = .default,
|
||||
@"invalid-pp-token": Kind = .default,
|
||||
@"deprecated-non-prototype": Kind = .default,
|
||||
@"duplicate-embed-param": Kind = .default,
|
||||
@"unsupported-embed-param": Kind = .default,
|
||||
@"unused-result": Kind = .default,
|
||||
normalized: Kind = .default,
|
||||
};
|
||||
|
||||
const Diagnostics = @This();
|
||||
|
||||
list: std.ArrayListUnmanaged(Message) = .{},
|
||||
arena: std.heap.ArenaAllocator,
|
||||
fatal_errors: bool = false,
|
||||
options: Options = .{},
|
||||
errors: u32 = 0,
|
||||
macro_backtrace_limit: u32 = 6,
|
||||
|
||||
pub fn warningExists(name: []const u8) bool {
|
||||
inline for (std.meta.fields(Options)) |f| {
|
||||
if (mem.eql(u8, f.name, name)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn set(d: *Diagnostics, name: []const u8, to: Kind) !void {
|
||||
inline for (std.meta.fields(Options)) |f| {
|
||||
if (mem.eql(u8, f.name, name)) {
|
||||
@field(d.options, f.name) = to;
|
||||
return;
|
||||
}
|
||||
}
|
||||
try d.addExtra(.{}, .{
|
||||
.tag = .unknown_warning,
|
||||
.extra = .{ .str = name },
|
||||
}, &.{});
|
||||
}
|
||||
|
||||
pub fn init(gpa: Allocator) Diagnostics {
|
||||
return .{
|
||||
.arena = std.heap.ArenaAllocator.init(gpa),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(d: *Diagnostics) void {
|
||||
d.list.deinit(d.arena.child_allocator);
|
||||
d.arena.deinit();
|
||||
}
|
||||
|
||||
pub fn add(comp: *Compilation, msg: Message, expansion_locs: []const Source.Location) Compilation.Error!void {
|
||||
return comp.diagnostics.addExtra(comp.langopts, msg, expansion_locs);
|
||||
}
|
||||
|
||||
pub fn addExtra(
|
||||
d: *Diagnostics,
|
||||
langopts: LangOpts,
|
||||
msg: Message,
|
||||
expansion_locs: []const Source.Location,
|
||||
) Compilation.Error!void {
|
||||
const kind = d.tagKind(msg.tag, langopts);
|
||||
if (kind == .off) return;
|
||||
var copy = msg;
|
||||
copy.kind = kind;
|
||||
|
||||
if (expansion_locs.len != 0) copy.loc = expansion_locs[expansion_locs.len - 1];
|
||||
try d.list.append(d.arena.child_allocator, copy);
|
||||
if (expansion_locs.len != 0) {
|
||||
// Add macro backtrace notes in reverse order omitting from the middle if needed.
|
||||
var i = expansion_locs.len - 1;
|
||||
const half = d.macro_backtrace_limit / 2;
|
||||
const limit = if (i < d.macro_backtrace_limit) 0 else i - half;
|
||||
try d.list.ensureUnusedCapacity(
|
||||
d.arena.child_allocator,
|
||||
if (limit == 0) expansion_locs.len else d.macro_backtrace_limit + 1,
|
||||
);
|
||||
while (i > limit) {
|
||||
i -= 1;
|
||||
d.list.appendAssumeCapacity(.{
|
||||
.tag = .expanded_from_here,
|
||||
.kind = .note,
|
||||
.loc = expansion_locs[i],
|
||||
});
|
||||
}
|
||||
if (limit != 0) {
|
||||
d.list.appendAssumeCapacity(.{
|
||||
.tag = .skipping_macro_backtrace,
|
||||
.kind = .note,
|
||||
.extra = .{ .unsigned = expansion_locs.len - d.macro_backtrace_limit },
|
||||
});
|
||||
i = half - 1;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
d.list.appendAssumeCapacity(.{
|
||||
.tag = .expanded_from_here,
|
||||
.kind = .note,
|
||||
.loc = expansion_locs[i],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
d.list.appendAssumeCapacity(.{
|
||||
.tag = .expanded_from_here,
|
||||
.kind = .note,
|
||||
.loc = msg.loc,
|
||||
});
|
||||
}
|
||||
if (kind == .@"fatal error" or (kind == .@"error" and d.fatal_errors))
|
||||
return error.FatalError;
|
||||
}
|
||||
|
||||
pub fn render(comp: *Compilation, config: std.io.tty.Config) void {
|
||||
if (comp.diagnostics.list.items.len == 0) return;
|
||||
var m = defaultMsgWriter(config);
|
||||
defer m.deinit();
|
||||
renderMessages(comp, &m);
|
||||
}
|
||||
pub fn defaultMsgWriter(config: std.io.tty.Config) MsgWriter {
|
||||
return MsgWriter.init(config);
|
||||
}
|
||||
|
||||
pub fn renderMessages(comp: *Compilation, m: anytype) void {
|
||||
var errors: u32 = 0;
|
||||
var warnings: u32 = 0;
|
||||
for (comp.diagnostics.list.items) |msg| {
|
||||
switch (msg.kind) {
|
||||
.@"fatal error", .@"error" => errors += 1,
|
||||
.warning => warnings += 1,
|
||||
.note => {},
|
||||
.off => continue, // happens if an error is added before it is disabled
|
||||
.default => unreachable,
|
||||
}
|
||||
renderMessage(comp, m, msg);
|
||||
}
|
||||
const w_s: []const u8 = if (warnings == 1) "" else "s";
|
||||
const e_s: []const u8 = if (errors == 1) "" else "s";
|
||||
if (errors != 0 and warnings != 0) {
|
||||
m.print("{d} warning{s} and {d} error{s} generated.\n", .{ warnings, w_s, errors, e_s });
|
||||
} else if (warnings != 0) {
|
||||
m.print("{d} warning{s} generated.\n", .{ warnings, w_s });
|
||||
} else if (errors != 0) {
|
||||
m.print("{d} error{s} generated.\n", .{ errors, e_s });
|
||||
}
|
||||
|
||||
comp.diagnostics.list.items.len = 0;
|
||||
comp.diagnostics.errors += errors;
|
||||
}
|
||||
|
||||
pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
|
||||
var line: ?[]const u8 = null;
|
||||
var end_with_splice = false;
|
||||
const width = if (msg.loc.id != .unused) blk: {
|
||||
var loc = msg.loc;
|
||||
switch (msg.tag) {
|
||||
.escape_sequence_overflow,
|
||||
.invalid_universal_character,
|
||||
=> loc.byte_offset += @truncate(msg.extra.offset),
|
||||
.non_standard_escape_char,
|
||||
.unknown_escape_sequence,
|
||||
=> loc.byte_offset += msg.extra.invalid_escape.offset,
|
||||
else => {},
|
||||
}
|
||||
const source = comp.getSource(loc.id);
|
||||
var line_col = source.lineCol(loc);
|
||||
line = line_col.line;
|
||||
end_with_splice = line_col.end_with_splice;
|
||||
if (msg.tag == .backslash_newline_escape) {
|
||||
line = line_col.line[0 .. line_col.col - 1];
|
||||
line_col.col += 1;
|
||||
line_col.width += 1;
|
||||
}
|
||||
m.location(source.path, line_col.line_no, line_col.col);
|
||||
break :blk line_col.width;
|
||||
} else 0;
|
||||
|
||||
m.start(msg.kind);
|
||||
const prop = msg.tag.property();
|
||||
switch (prop.extra) {
|
||||
.str => printRt(m, prop.msg, .{"{s}"}, .{msg.extra.str}),
|
||||
.tok_id => printRt(m, prop.msg, .{ "{s}", "{s}" }, .{
|
||||
msg.extra.tok_id.expected.symbol(),
|
||||
msg.extra.tok_id.actual.symbol(),
|
||||
}),
|
||||
.tok_id_expected => printRt(m, prop.msg, .{"{s}"}, .{msg.extra.tok_id_expected.symbol()}),
|
||||
.arguments => printRt(m, prop.msg, .{ "{d}", "{d}" }, .{
|
||||
msg.extra.arguments.expected,
|
||||
msg.extra.arguments.actual,
|
||||
}),
|
||||
.codepoints => printRt(m, prop.msg, .{ "{X:0>4}", "{u}" }, .{
|
||||
msg.extra.codepoints.actual,
|
||||
msg.extra.codepoints.resembles,
|
||||
}),
|
||||
.attr_arg_count => printRt(m, prop.msg, .{ "{s}", "{d}" }, .{
|
||||
@tagName(msg.extra.attr_arg_count.attribute),
|
||||
msg.extra.attr_arg_count.expected,
|
||||
}),
|
||||
.attr_arg_type => printRt(m, prop.msg, .{ "{s}", "{s}" }, .{
|
||||
msg.extra.attr_arg_type.expected.toString(),
|
||||
msg.extra.attr_arg_type.actual.toString(),
|
||||
}),
|
||||
.actual_codepoint => printRt(m, prop.msg, .{"{X:0>4}"}, .{msg.extra.actual_codepoint}),
|
||||
.ascii => printRt(m, prop.msg, .{"{c}"}, .{msg.extra.ascii}),
|
||||
.unsigned => printRt(m, prop.msg, .{"{d}"}, .{msg.extra.unsigned}),
|
||||
.pow_2_as_string => printRt(m, prop.msg, .{"{s}"}, .{switch (msg.extra.pow_2_as_string) {
|
||||
63 => "9223372036854775808",
|
||||
64 => "18446744073709551616",
|
||||
127 => "170141183460469231731687303715884105728",
|
||||
128 => "340282366920938463463374607431768211456",
|
||||
else => unreachable,
|
||||
}}),
|
||||
.signed => printRt(m, prop.msg, .{"{d}"}, .{msg.extra.signed}),
|
||||
.attr_enum => printRt(m, prop.msg, .{ "{s}", "{s}" }, .{
|
||||
@tagName(msg.extra.attr_enum.tag),
|
||||
Attribute.Formatting.choices(msg.extra.attr_enum.tag),
|
||||
}),
|
||||
.ignored_record_attr => printRt(m, prop.msg, .{ "{s}", "{s}" }, .{
|
||||
@tagName(msg.extra.ignored_record_attr.tag),
|
||||
@tagName(msg.extra.ignored_record_attr.specifier),
|
||||
}),
|
||||
.builtin_with_header => printRt(m, prop.msg, .{ "{s}", "{s}" }, .{
|
||||
@tagName(msg.extra.builtin_with_header.header),
|
||||
Builtin.nameFromTag(msg.extra.builtin_with_header.builtin).span(),
|
||||
}),
|
||||
.invalid_escape => {
|
||||
if (std.ascii.isPrint(msg.extra.invalid_escape.char)) {
|
||||
const str: [1]u8 = .{msg.extra.invalid_escape.char};
|
||||
printRt(m, prop.msg, .{"{s}"}, .{&str});
|
||||
} else {
|
||||
var buf: [3]u8 = undefined;
|
||||
const str = std.fmt.bufPrint(&buf, "x{x}", .{std.fmt.fmtSliceHexLower(&.{msg.extra.invalid_escape.char})}) catch unreachable;
|
||||
printRt(m, prop.msg, .{"{s}"}, .{str});
|
||||
}
|
||||
},
|
||||
.normalized => {
|
||||
const f = struct {
|
||||
pub fn f(
|
||||
bytes: []const u8,
|
||||
comptime _: []const u8,
|
||||
_: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
) !void {
|
||||
var it: std.unicode.Utf8Iterator = .{
|
||||
.bytes = bytes,
|
||||
.i = 0,
|
||||
};
|
||||
while (it.nextCodepoint()) |codepoint| {
|
||||
if (codepoint < 0x7F) {
|
||||
try writer.writeByte(@intCast(codepoint));
|
||||
} else if (codepoint < 0xFFFF) {
|
||||
try writer.writeAll("\\u");
|
||||
try std.fmt.formatInt(codepoint, 16, .upper, .{
|
||||
.fill = '0',
|
||||
.width = 4,
|
||||
}, writer);
|
||||
} else {
|
||||
try writer.writeAll("\\U");
|
||||
try std.fmt.formatInt(codepoint, 16, .upper, .{
|
||||
.fill = '0',
|
||||
.width = 8,
|
||||
}, writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.f;
|
||||
printRt(m, prop.msg, .{"{s}"}, .{
|
||||
std.fmt.Formatter(f){ .data = msg.extra.normalized },
|
||||
});
|
||||
},
|
||||
.none, .offset => m.write(prop.msg),
|
||||
}
|
||||
|
||||
if (prop.opt) |some| {
|
||||
if (msg.kind == .@"error" and prop.kind != .@"error") {
|
||||
m.print(" [-Werror,-W{s}]", .{optName(some)});
|
||||
} else if (msg.kind != .note) {
|
||||
m.print(" [-W{s}]", .{optName(some)});
|
||||
}
|
||||
}
|
||||
|
||||
m.end(line, width, end_with_splice);
|
||||
}
|
||||
|
||||
fn printRt(m: anytype, str: []const u8, comptime fmts: anytype, args: anytype) void {
|
||||
var i: usize = 0;
|
||||
inline for (fmts, args) |fmt, arg| {
|
||||
const new = std.mem.indexOfPos(u8, str, i, fmt).?;
|
||||
m.write(str[i..new]);
|
||||
i = new + fmt.len;
|
||||
m.print(fmt, .{arg});
|
||||
}
|
||||
m.write(str[i..]);
|
||||
}
|
||||
|
||||
fn optName(offset: u16) []const u8 {
|
||||
return std.meta.fieldNames(Options)[offset / @sizeOf(Kind)];
|
||||
}
|
||||
|
||||
fn tagKind(d: *Diagnostics, tag: Tag, langopts: LangOpts) Kind {
|
||||
const prop = tag.property();
|
||||
var kind = prop.getKind(&d.options);
|
||||
|
||||
if (prop.all) {
|
||||
if (d.options.all != .default) kind = d.options.all;
|
||||
}
|
||||
if (prop.w_extra) {
|
||||
if (d.options.extra != .default) kind = d.options.extra;
|
||||
}
|
||||
if (prop.pedantic) {
|
||||
if (d.options.pedantic != .default) kind = d.options.pedantic;
|
||||
}
|
||||
if (prop.suppress_version) |some| if (langopts.standard.atLeast(some)) return .off;
|
||||
if (prop.suppress_unless_version) |some| if (!langopts.standard.atLeast(some)) return .off;
|
||||
if (prop.suppress_gnu and langopts.standard.isExplicitGNU()) return .off;
|
||||
if (prop.suppress_gcc and langopts.emulate == .gcc) return .off;
|
||||
if (prop.suppress_clang and langopts.emulate == .clang) return .off;
|
||||
if (prop.suppress_msvc and langopts.emulate == .msvc) return .off;
|
||||
if (kind == .@"error" and d.fatal_errors) kind = .@"fatal error";
|
||||
return kind;
|
||||
}
|
||||
|
||||
const MsgWriter = struct {
|
||||
w: std.io.BufferedWriter(4096, std.fs.File.Writer),
|
||||
config: std.io.tty.Config,
|
||||
|
||||
fn init(config: std.io.tty.Config) MsgWriter {
|
||||
std.debug.getStderrMutex().lock();
|
||||
return .{
|
||||
.w = std.io.bufferedWriter(std.io.getStdErr().writer()),
|
||||
.config = config,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(m: *MsgWriter) void {
|
||||
m.w.flush() catch {};
|
||||
std.debug.getStderrMutex().unlock();
|
||||
}
|
||||
|
||||
pub fn print(m: *MsgWriter, comptime fmt: []const u8, args: anytype) void {
|
||||
m.w.writer().print(fmt, args) catch {};
|
||||
}
|
||||
|
||||
fn write(m: *MsgWriter, msg: []const u8) void {
|
||||
m.w.writer().writeAll(msg) catch {};
|
||||
}
|
||||
|
||||
fn setColor(m: *MsgWriter, color: std.io.tty.Color) void {
|
||||
m.config.setColor(m.w.writer(), color) catch {};
|
||||
}
|
||||
|
||||
fn location(m: *MsgWriter, path: []const u8, line: u32, col: u32) void {
|
||||
m.setColor(.bold);
|
||||
m.print("{s}:{d}:{d}: ", .{ path, line, col });
|
||||
}
|
||||
|
||||
fn start(m: *MsgWriter, kind: Kind) void {
|
||||
switch (kind) {
|
||||
.@"fatal error", .@"error" => m.setColor(.bright_red),
|
||||
.note => m.setColor(.bright_cyan),
|
||||
.warning => m.setColor(.bright_magenta),
|
||||
.off, .default => unreachable,
|
||||
}
|
||||
m.write(switch (kind) {
|
||||
.@"fatal error" => "fatal error: ",
|
||||
.@"error" => "error: ",
|
||||
.note => "note: ",
|
||||
.warning => "warning: ",
|
||||
.off, .default => unreachable,
|
||||
});
|
||||
m.setColor(.white);
|
||||
}
|
||||
|
||||
fn end(m: *MsgWriter, maybe_line: ?[]const u8, col: u32, end_with_splice: bool) void {
|
||||
const line = maybe_line orelse {
|
||||
m.write("\n");
|
||||
m.setColor(.reset);
|
||||
return;
|
||||
};
|
||||
const trailer = if (end_with_splice) "\\ " else "";
|
||||
m.setColor(.reset);
|
||||
m.print("\n{s}{s}\n{s: >[3]}", .{ line, trailer, "", col });
|
||||
m.setColor(.bold);
|
||||
m.setColor(.bright_green);
|
||||
m.write("^\n");
|
||||
m.setColor(.reset);
|
||||
}
|
||||
};
|
||||
2446
deps/aro/aro/Diagnostics/messages.def
vendored
Normal file
2446
deps/aro/aro/Diagnostics/messages.def
vendored
Normal file
File diff suppressed because it is too large
Load Diff
228
deps/aro/Driver.zig → deps/aro/aro/Driver.zig
vendored
228
deps/aro/Driver.zig → deps/aro/aro/Driver.zig
vendored
@ -2,18 +2,17 @@ const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const Allocator = mem.Allocator;
|
||||
const process = std.process;
|
||||
const Codegen = @import("Codegen_legacy.zig");
|
||||
const backend = @import("backend");
|
||||
const Ir = backend.Ir;
|
||||
const Object = backend.Object;
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Diagnostics = @import("Diagnostics.zig");
|
||||
const LangOpts = @import("LangOpts.zig");
|
||||
const Preprocessor = @import("Preprocessor.zig");
|
||||
const Parser = @import("Parser.zig");
|
||||
const Source = @import("Source.zig");
|
||||
const Toolchain = @import("Toolchain.zig");
|
||||
const util = @import("util.zig");
|
||||
const target_util = @import("target.zig");
|
||||
|
||||
const Driver = @This();
|
||||
|
||||
pub const Linker = enum {
|
||||
ld,
|
||||
bfd,
|
||||
@ -22,11 +21,14 @@ pub const Linker = enum {
|
||||
mold,
|
||||
};
|
||||
|
||||
const Driver = @This();
|
||||
|
||||
comp: *Compilation,
|
||||
inputs: std.ArrayListUnmanaged(Source) = .{},
|
||||
link_objects: std.ArrayListUnmanaged([]const u8) = .{},
|
||||
output_name: ?[]const u8 = null,
|
||||
sysroot: ?[]const u8 = null,
|
||||
system_defines: Compilation.SystemDefinesMode = .include_system_defines,
|
||||
temp_file_count: u32 = 0,
|
||||
/// If false, do not emit line directives in -E mode
|
||||
line_commands: bool = true,
|
||||
@ -40,6 +42,7 @@ verbose_ast: bool = false,
|
||||
verbose_pp: bool = false,
|
||||
verbose_ir: bool = false,
|
||||
verbose_linker_args: bool = false,
|
||||
color: ?bool = null,
|
||||
|
||||
/// Full path to the aro executable
|
||||
aro_name: []const u8 = "",
|
||||
@ -87,8 +90,8 @@ pub const usage =
|
||||
\\ -c, --compile Only run preprocess, compile, and assemble steps
|
||||
\\ -D <macro>=<value> Define <macro> to <value> (defaults to 1)
|
||||
\\ -E Only run the preprocessor
|
||||
\\ -fchar8_t Enable char8_t (enabled by default in C2X and later)
|
||||
\\ -fno-char8_t Disable char8_t (disabled by default for pre-C2X)
|
||||
\\ -fchar8_t Enable char8_t (enabled by default in C23 and later)
|
||||
\\ -fno-char8_t Disable char8_t (disabled by default for pre-C23)
|
||||
\\ -fcolor-diagnostics Enable colors in diagnostics
|
||||
\\ -fno-color-diagnostics Disable colors in diagnostics
|
||||
\\ -fdeclspec Enable support for __declspec attributes
|
||||
@ -131,6 +134,7 @@ pub const usage =
|
||||
\\ --sysroot=<dir> Use dir as the logical root directory for headers and libraries (not fully implemented)
|
||||
\\ --target=<value> Generate code for the given target
|
||||
\\ -U <macro> Undefine <macro>
|
||||
\\ -undef Do not predefine any system-specific macros. Standard predefined macros remain defined.
|
||||
\\ -Werror Treat all warnings as errors
|
||||
\\ -Werror=<warning> Treat warning as error
|
||||
\\ -W<warning> Enable the specified warning
|
||||
@ -172,23 +176,18 @@ pub fn parseArgs(
|
||||
args: []const []const u8,
|
||||
) !bool {
|
||||
var i: usize = 1;
|
||||
var color_setting: enum {
|
||||
on,
|
||||
off,
|
||||
unset,
|
||||
} = .unset;
|
||||
var comment_arg: []const u8 = "";
|
||||
while (i < args.len) : (i += 1) {
|
||||
const arg = args[i];
|
||||
if (mem.startsWith(u8, arg, "-") and arg.len > 1) {
|
||||
if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
|
||||
std_out.print(usage, .{args[0]}) catch |er| {
|
||||
return d.fatal("unable to print usage: {s}", .{util.errorDescription(er)});
|
||||
return d.fatal("unable to print usage: {s}", .{errorDescription(er)});
|
||||
};
|
||||
return true;
|
||||
} else if (mem.eql(u8, arg, "-v") or mem.eql(u8, arg, "--version")) {
|
||||
std_out.writeAll(@import("lib.zig").version_str ++ "\n") catch |er| {
|
||||
return d.fatal("unable to print version: {s}", .{util.errorDescription(er)});
|
||||
std_out.writeAll(@import("backend").version_str ++ "\n") catch |er| {
|
||||
return d.fatal("unable to print version: {s}", .{errorDescription(er)});
|
||||
};
|
||||
return true;
|
||||
} else if (mem.startsWith(u8, arg, "-D")) {
|
||||
@ -218,6 +217,8 @@ pub fn parseArgs(
|
||||
macro = args[i];
|
||||
}
|
||||
try macro_buf.print("#undef {s}\n", .{macro});
|
||||
} else if (mem.eql(u8, arg, "-undef")) {
|
||||
d.system_defines = .no_system_defines;
|
||||
} else if (mem.eql(u8, arg, "-c") or mem.eql(u8, arg, "--compile")) {
|
||||
d.only_compile = true;
|
||||
} else if (mem.eql(u8, arg, "-E")) {
|
||||
@ -233,9 +234,9 @@ pub fn parseArgs(
|
||||
} else if (mem.eql(u8, arg, "-fno-char8_t")) {
|
||||
d.comp.langopts.has_char8_t_override = false;
|
||||
} else if (mem.eql(u8, arg, "-fcolor-diagnostics")) {
|
||||
color_setting = .on;
|
||||
d.color = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-color-diagnostics")) {
|
||||
color_setting = .off;
|
||||
d.color = false;
|
||||
} else if (mem.eql(u8, arg, "-fdollars-in-identifiers")) {
|
||||
d.comp.langopts.dollars_in_identifiers = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-dollars-in-identifiers")) {
|
||||
@ -255,7 +256,7 @@ pub fn parseArgs(
|
||||
};
|
||||
|
||||
if (limit == 0) limit = std.math.maxInt(u32);
|
||||
d.comp.diag.macro_backtrace_limit = limit;
|
||||
d.comp.diagnostics.macro_backtrace_limit = limit;
|
||||
} else if (mem.eql(u8, arg, "-fnative-half-type")) {
|
||||
d.comp.langopts.use_native_half_type = true;
|
||||
} else if (mem.eql(u8, arg, "-fnative-half-arguments-and-returns")) {
|
||||
@ -290,7 +291,7 @@ pub fn parseArgs(
|
||||
}
|
||||
path = args[i];
|
||||
}
|
||||
try d.comp.include_dirs.append(path);
|
||||
try d.comp.include_dirs.append(d.comp.gpa, path);
|
||||
} else if (mem.startsWith(u8, arg, "-fsyntax-only")) {
|
||||
d.only_syntax = true;
|
||||
} else if (mem.startsWith(u8, arg, "-fno-syntax-only")) {
|
||||
@ -307,17 +308,17 @@ pub fn parseArgs(
|
||||
}
|
||||
const duped = try d.comp.gpa.dupe(u8, path);
|
||||
errdefer d.comp.gpa.free(duped);
|
||||
try d.comp.system_include_dirs.append(duped);
|
||||
try d.comp.system_include_dirs.append(d.comp.gpa, duped);
|
||||
} else if (option(arg, "--emulate=")) |compiler_str| {
|
||||
const compiler = std.meta.stringToEnum(LangOpts.Compiler, compiler_str) orelse {
|
||||
try d.comp.diag.add(.{ .tag = .cli_invalid_emulate, .extra = .{ .str = arg } }, &.{});
|
||||
try d.comp.addDiagnostic(.{ .tag = .cli_invalid_emulate, .extra = .{ .str = arg } }, &.{});
|
||||
continue;
|
||||
};
|
||||
d.comp.langopts.setEmulatedCompiler(compiler);
|
||||
} else if (option(arg, "-ffp-eval-method=")) |fp_method_str| {
|
||||
const fp_eval_method = std.meta.stringToEnum(LangOpts.FPEvalMethod, fp_method_str) orelse .indeterminate;
|
||||
if (fp_eval_method == .indeterminate) {
|
||||
try d.comp.diag.add(.{ .tag = .cli_invalid_fp_eval_method, .extra = .{ .str = fp_method_str } }, &.{});
|
||||
try d.comp.addDiagnostic(.{ .tag = .cli_invalid_fp_eval_method, .extra = .{ .str = fp_method_str } }, &.{});
|
||||
continue;
|
||||
}
|
||||
d.comp.langopts.setFpEvalMethod(fp_eval_method);
|
||||
@ -335,31 +336,31 @@ pub fn parseArgs(
|
||||
} else if (option(arg, "--sysroot=")) |sysroot| {
|
||||
d.sysroot = sysroot;
|
||||
} else if (mem.eql(u8, arg, "-pedantic")) {
|
||||
d.comp.diag.options.pedantic = .warning;
|
||||
d.comp.diagnostics.options.pedantic = .warning;
|
||||
} else if (option(arg, "--rtlib=")) |rtlib| {
|
||||
if (mem.eql(u8, rtlib, "compiler-rt") or mem.eql(u8, rtlib, "libgcc") or mem.eql(u8, rtlib, "platform")) {
|
||||
d.rtlib = rtlib;
|
||||
} else {
|
||||
try d.comp.diag.add(.{ .tag = .invalid_rtlib, .extra = .{ .str = rtlib } }, &.{});
|
||||
try d.comp.addDiagnostic(.{ .tag = .invalid_rtlib, .extra = .{ .str = rtlib } }, &.{});
|
||||
}
|
||||
} else if (option(arg, "-Werror=")) |err_name| {
|
||||
try d.comp.diag.set(err_name, .@"error");
|
||||
try d.comp.diagnostics.set(err_name, .@"error");
|
||||
} else if (mem.eql(u8, arg, "-Wno-fatal-errors")) {
|
||||
d.comp.diag.fatal_errors = false;
|
||||
d.comp.diagnostics.fatal_errors = false;
|
||||
} else if (option(arg, "-Wno-")) |err_name| {
|
||||
try d.comp.diag.set(err_name, .off);
|
||||
try d.comp.diagnostics.set(err_name, .off);
|
||||
} else if (mem.eql(u8, arg, "-Wfatal-errors")) {
|
||||
d.comp.diag.fatal_errors = true;
|
||||
d.comp.diagnostics.fatal_errors = true;
|
||||
} else if (option(arg, "-W")) |err_name| {
|
||||
try d.comp.diag.set(err_name, .warning);
|
||||
try d.comp.diagnostics.set(err_name, .warning);
|
||||
} else if (option(arg, "-std=")) |standard| {
|
||||
d.comp.langopts.setStandard(standard) catch
|
||||
try d.comp.diag.add(.{ .tag = .cli_invalid_standard, .extra = .{ .str = arg } }, &.{});
|
||||
try d.comp.addDiagnostic(.{ .tag = .cli_invalid_standard, .extra = .{ .str = arg } }, &.{});
|
||||
} else if (mem.eql(u8, arg, "-S") or mem.eql(u8, arg, "--assemble")) {
|
||||
d.only_preprocess_and_compile = true;
|
||||
} else if (option(arg, "--target=")) |triple| {
|
||||
const cross = std.zig.CrossTarget.parse(.{ .arch_os_abi = triple }) catch {
|
||||
try d.comp.diag.add(.{ .tag = .cli_invalid_target, .extra = .{ .str = arg } }, &.{});
|
||||
try d.comp.addDiagnostic(.{ .tag = .cli_invalid_target, .extra = .{ .str = arg } }, &.{});
|
||||
continue;
|
||||
};
|
||||
d.comp.target = cross.toTarget(); // TODO deprecated
|
||||
@ -422,25 +423,20 @@ pub fn parseArgs(
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
try d.comp.diag.add(.{ .tag = .invalid_unwindlib, .extra = .{ .str = unwindlib } }, &.{});
|
||||
try d.comp.addDiagnostic(.{ .tag = .invalid_unwindlib, .extra = .{ .str = unwindlib } }, &.{});
|
||||
}
|
||||
} else {
|
||||
try d.comp.diag.add(.{ .tag = .cli_unknown_arg, .extra = .{ .str = arg } }, &.{});
|
||||
try d.comp.addDiagnostic(.{ .tag = .cli_unknown_arg, .extra = .{ .str = arg } }, &.{});
|
||||
}
|
||||
} else if (std.mem.endsWith(u8, arg, ".o") or std.mem.endsWith(u8, arg, ".obj")) {
|
||||
try d.link_objects.append(d.comp.gpa, arg);
|
||||
} else {
|
||||
const source = d.addSource(arg) catch |er| {
|
||||
return d.fatal("unable to add source file '{s}': {s}", .{ arg, util.errorDescription(er) });
|
||||
return d.fatal("unable to add source file '{s}': {s}", .{ arg, errorDescription(er) });
|
||||
};
|
||||
try d.inputs.append(d.comp.gpa, source);
|
||||
}
|
||||
}
|
||||
d.comp.diag.color = switch (color_setting) {
|
||||
.on => true,
|
||||
.off => false,
|
||||
.unset => util.fileSupportsColor(std.io.getStdErr()) and !std.process.hasEnvVarConstant("NO_COLOR"),
|
||||
};
|
||||
if (d.comp.langopts.preserve_comments and !d.only_preprocess) {
|
||||
return d.fatal("invalid argument '{s}' only allowed with '-E'", .{comment_arg});
|
||||
}
|
||||
@ -465,15 +461,65 @@ fn addSource(d: *Driver, path: []const u8) !Source {
|
||||
}
|
||||
|
||||
pub fn err(d: *Driver, msg: []const u8) !void {
|
||||
try d.comp.diag.add(.{ .tag = .cli_error, .extra = .{ .str = msg } }, &.{});
|
||||
try d.comp.addDiagnostic(.{ .tag = .cli_error, .extra = .{ .str = msg } }, &.{});
|
||||
}
|
||||
|
||||
pub fn fatal(d: *Driver, comptime fmt: []const u8, args: anytype) error{FatalError} {
|
||||
d.comp.renderErrors();
|
||||
return d.comp.diag.fatalNoSrc(fmt, args);
|
||||
pub fn fatal(d: *Driver, comptime fmt: []const u8, args: anytype) error{ FatalError, OutOfMemory } {
|
||||
try d.comp.diagnostics.list.append(d.comp.gpa, .{
|
||||
.tag = .cli_error,
|
||||
.kind = .@"fatal error",
|
||||
.extra = .{ .str = try std.fmt.allocPrint(d.comp.diagnostics.arena.allocator(), fmt, args) },
|
||||
});
|
||||
return error.FatalError;
|
||||
}
|
||||
|
||||
pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8) !void {
|
||||
pub fn renderErrors(d: *Driver) void {
|
||||
Diagnostics.render(d.comp, d.detectConfig(std.io.getStdErr()));
|
||||
}
|
||||
|
||||
pub fn detectConfig(d: *Driver, file: std.fs.File) std.io.tty.Config {
|
||||
if (d.color == true) return .escape_codes;
|
||||
if (d.color == false) return .no_color;
|
||||
|
||||
if (file.supportsAnsiEscapeCodes()) return .escape_codes;
|
||||
if (@import("builtin").os.tag == .windows and file.isTty()) {
|
||||
var info: std.os.windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
|
||||
if (std.os.windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != std.os.windows.TRUE) {
|
||||
return .no_color;
|
||||
}
|
||||
return .{ .windows_api = .{
|
||||
.handle = file.handle,
|
||||
.reset_attributes = info.wAttributes,
|
||||
} };
|
||||
}
|
||||
|
||||
return .no_color;
|
||||
}
|
||||
|
||||
pub fn errorDescription(e: anyerror) []const u8 {
|
||||
return switch (e) {
|
||||
error.OutOfMemory => "ran out of memory",
|
||||
error.FileNotFound => "file not found",
|
||||
error.IsDir => "is a directory",
|
||||
error.NotDir => "is not a directory",
|
||||
error.NotOpenForReading => "file is not open for reading",
|
||||
error.NotOpenForWriting => "file is not open for writing",
|
||||
error.InvalidUtf8 => "input is not valid UTF-8",
|
||||
error.FileBusy => "file is busy",
|
||||
error.NameTooLong => "file name is too long",
|
||||
error.AccessDenied => "access denied",
|
||||
error.FileTooBig => "file is too big",
|
||||
error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded => "ran out of file descriptors",
|
||||
error.SystemResources => "ran out of system resources",
|
||||
error.FatalError => "a fatal error occurred",
|
||||
error.Unexpected => "an unexpected error occurred",
|
||||
else => @errorName(e),
|
||||
};
|
||||
}
|
||||
|
||||
/// The entry point of the Aro compiler.
|
||||
/// **MAY call `exit` if `fast_exit` is set.**
|
||||
pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_exit: bool) !void {
|
||||
var macro_buf = std.ArrayList(u8).init(d.comp.gpa);
|
||||
defer macro_buf.deinit();
|
||||
|
||||
@ -489,7 +535,7 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8) !void {
|
||||
}
|
||||
|
||||
if (!linking) for (d.link_objects.items) |obj| {
|
||||
try d.comp.diag.add(.{ .tag = .cli_unused_link_object, .extra = .{ .str = obj } }, &.{});
|
||||
try d.comp.addDiagnostic(.{ .tag = .cli_unused_link_object, .extra = .{ .str = obj } }, &.{});
|
||||
};
|
||||
|
||||
d.comp.defineSystemIncludes(d.aro_name) catch |er| switch (er) {
|
||||
@ -497,15 +543,13 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8) !void {
|
||||
error.AroIncludeNotFound => return d.fatal("unable to find Aro builtin headers", .{}),
|
||||
};
|
||||
|
||||
const builtin = try d.comp.generateBuiltinMacros();
|
||||
const builtin = try d.comp.generateBuiltinMacros(d.system_defines);
|
||||
const user_macros = try d.comp.addSourceFromBuffer("<command line>", macro_buf.items);
|
||||
|
||||
const fast_exit = @import("builtin").mode != .Debug;
|
||||
|
||||
if (fast_exit and d.inputs.items.len == 1) {
|
||||
d.processSource(tc, d.inputs.items[0], builtin, user_macros, fast_exit) catch |e| switch (e) {
|
||||
error.FatalError => {
|
||||
d.comp.renderErrors();
|
||||
d.renderErrors();
|
||||
d.exitWithCleanup(1);
|
||||
},
|
||||
else => |er| return er,
|
||||
@ -516,12 +560,12 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8) !void {
|
||||
for (d.inputs.items) |source| {
|
||||
d.processSource(tc, source, builtin, user_macros, fast_exit) catch |e| switch (e) {
|
||||
error.FatalError => {
|
||||
d.comp.renderErrors();
|
||||
d.renderErrors();
|
||||
},
|
||||
else => |er| return er,
|
||||
};
|
||||
}
|
||||
if (d.comp.diag.errors != 0) {
|
||||
if (d.comp.diagnostics.errors != 0) {
|
||||
if (fast_exit) d.exitWithCleanup(1);
|
||||
return;
|
||||
}
|
||||
@ -540,7 +584,7 @@ fn processSource(
|
||||
comptime fast_exit: bool,
|
||||
) !void {
|
||||
d.comp.generated_buf.items.len = 0;
|
||||
var pp = Preprocessor.init(d.comp);
|
||||
var pp = try Preprocessor.initDefault(d.comp);
|
||||
defer pp.deinit();
|
||||
|
||||
if (d.comp.langopts.ms_extensions) {
|
||||
@ -554,52 +598,48 @@ fn processSource(
|
||||
pp.linemarkers = if (d.use_line_directives) .line_directives else .numeric_directives;
|
||||
}
|
||||
}
|
||||
try pp.addBuiltinMacros();
|
||||
|
||||
try pp.addIncludeStart(source);
|
||||
try pp.addIncludeStart(builtin);
|
||||
_ = try pp.preprocess(builtin);
|
||||
try pp.addIncludeStart(user_macros);
|
||||
_ = try pp.preprocess(user_macros);
|
||||
try pp.addIncludeResume(source.id, 0, 0);
|
||||
const eof = try pp.preprocess(source);
|
||||
try pp.tokens.append(pp.comp.gpa, eof);
|
||||
try pp.preprocessSources(&.{ source, builtin, user_macros });
|
||||
|
||||
if (d.only_preprocess) {
|
||||
d.comp.renderErrors();
|
||||
d.renderErrors();
|
||||
|
||||
if (d.comp.diagnostics.errors != 0) {
|
||||
if (fast_exit) std.process.exit(1); // Not linking, no need for cleanup.
|
||||
return;
|
||||
}
|
||||
|
||||
const file = if (d.output_name) |some|
|
||||
std.fs.cwd().createFile(some, .{}) catch |er|
|
||||
return d.fatal("unable to create output file '{s}': {s}", .{ some, util.errorDescription(er) })
|
||||
return d.fatal("unable to create output file '{s}': {s}", .{ some, errorDescription(er) })
|
||||
else
|
||||
std.io.getStdOut();
|
||||
defer if (d.output_name != null) file.close();
|
||||
|
||||
var buf_w = std.io.bufferedWriter(file.writer());
|
||||
pp.prettyPrintTokens(buf_w.writer()) catch |er|
|
||||
return d.fatal("unable to write result: {s}", .{util.errorDescription(er)});
|
||||
return d.fatal("unable to write result: {s}", .{errorDescription(er)});
|
||||
|
||||
buf_w.flush() catch |er|
|
||||
return d.fatal("unable to write result: {s}", .{util.errorDescription(er)});
|
||||
return d.fatal("unable to write result: {s}", .{errorDescription(er)});
|
||||
if (fast_exit) std.process.exit(0); // Not linking, no need for cleanup.
|
||||
return;
|
||||
}
|
||||
|
||||
var tree = try Parser.parse(&pp);
|
||||
var tree = try pp.parse();
|
||||
defer tree.deinit();
|
||||
|
||||
if (d.verbose_ast) {
|
||||
const stdout = std.io.getStdOut();
|
||||
var buf_writer = std.io.bufferedWriter(stdout.writer());
|
||||
const color = d.comp.diag.color and util.fileSupportsColor(stdout);
|
||||
tree.dump(color, buf_writer.writer()) catch {};
|
||||
tree.dump(d.detectConfig(stdout), buf_writer.writer()) catch {};
|
||||
buf_writer.flush() catch {};
|
||||
}
|
||||
|
||||
const prev_errors = d.comp.diag.errors;
|
||||
d.comp.renderErrors();
|
||||
const prev_errors = d.comp.diagnostics.errors;
|
||||
d.renderErrors();
|
||||
|
||||
if (d.comp.diag.errors != prev_errors) {
|
||||
if (d.comp.diagnostics.errors != prev_errors) {
|
||||
if (fast_exit) d.exitWithCleanup(1);
|
||||
return; // do not compile if there were errors
|
||||
}
|
||||
@ -616,11 +656,31 @@ fn processSource(
|
||||
);
|
||||
}
|
||||
|
||||
var ir = try tree.genIr();
|
||||
defer ir.deinit(d.comp.gpa);
|
||||
|
||||
if (d.verbose_ir) {
|
||||
try @import("CodeGen.zig").generateTree(d.comp, tree);
|
||||
const stdout = std.io.getStdOut();
|
||||
var buf_writer = std.io.bufferedWriter(stdout.writer());
|
||||
ir.dump(d.comp.gpa, d.detectConfig(stdout), buf_writer.writer()) catch {};
|
||||
buf_writer.flush() catch {};
|
||||
}
|
||||
|
||||
const obj = try Codegen.generateTree(d.comp, tree);
|
||||
var render_errors: Ir.Renderer.ErrorList = .{};
|
||||
defer {
|
||||
for (render_errors.values()) |msg| d.comp.gpa.free(msg);
|
||||
render_errors.deinit(d.comp.gpa);
|
||||
}
|
||||
|
||||
var obj = ir.render(d.comp.gpa, d.comp.target, &render_errors) catch |e| switch (e) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.LowerFail => {
|
||||
return d.fatal(
|
||||
"unable to render Ir to machine code: {s}",
|
||||
.{render_errors.values()[0]},
|
||||
);
|
||||
},
|
||||
};
|
||||
defer obj.deinit();
|
||||
|
||||
// If it's used, name_buf will either hold a filename or `/tmp/<12 random bytes with base-64 encoding>.<extension>`
|
||||
@ -653,11 +713,11 @@ fn processSource(
|
||||
};
|
||||
|
||||
const out_file = std.fs.cwd().createFile(out_file_name, .{}) catch |er|
|
||||
return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, util.errorDescription(er) });
|
||||
return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, errorDescription(er) });
|
||||
defer out_file.close();
|
||||
|
||||
obj.finish(out_file) catch |er|
|
||||
return d.fatal("could not output to object file '{s}': {s}", .{ out_file_name, util.errorDescription(er) });
|
||||
return d.fatal("could not output to object file '{s}': {s}", .{ out_file_name, errorDescription(er) });
|
||||
|
||||
if (d.only_compile) {
|
||||
if (fast_exit) std.process.exit(0); // Not linking, no need for cleanup.
|
||||
@ -680,6 +740,8 @@ fn dumpLinkerArgs(items: []const []const u8) !void {
|
||||
try stdout.writeByte('\n');
|
||||
}
|
||||
|
||||
/// The entry point of the Aro compiler.
|
||||
/// **MAY call `exit` if `fast_exit` is set.**
|
||||
pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) !void {
|
||||
try tc.discover();
|
||||
|
||||
@ -694,7 +756,7 @@ pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) !void
|
||||
|
||||
if (d.verbose_linker_args) {
|
||||
dumpLinkerArgs(argv.items) catch |er| {
|
||||
return d.fatal("unable to dump linker args: {s}", .{util.errorDescription(er)});
|
||||
return d.fatal("unable to dump linker args: {s}", .{errorDescription(er)});
|
||||
};
|
||||
}
|
||||
var child = std.ChildProcess.init(argv.items, d.comp.gpa);
|
||||
@ -704,11 +766,19 @@ pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) !void
|
||||
child.stderr_behavior = .Inherit;
|
||||
|
||||
const term = child.spawnAndWait() catch |er| {
|
||||
return d.fatal("unable to spawn linker: {s}", .{util.errorDescription(er)});
|
||||
return d.fatal("unable to spawn linker: {s}", .{errorDescription(er)});
|
||||
};
|
||||
switch (term) {
|
||||
.Exited => |code| if (code != 0) d.exitWithCleanup(code),
|
||||
else => std.process.abort(),
|
||||
.Exited => |code| if (code != 0) {
|
||||
const e = d.fatal("linker exited with an error code", .{});
|
||||
if (fast_exit) d.exitWithCleanup(code);
|
||||
return e;
|
||||
},
|
||||
else => {
|
||||
const e = d.fatal("linker crashed", .{});
|
||||
if (fast_exit) d.exitWithCleanup(1);
|
||||
return e;
|
||||
},
|
||||
}
|
||||
if (fast_exit) d.exitWithCleanup(0);
|
||||
}
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const util = @import("../util.zig");
|
||||
const Filesystem = @import("Filesystem.zig").Filesystem;
|
||||
|
||||
const MAX_BYTES = 1024; // TODO: Can we assume 1024 bytes enough for the info we need?
|
||||
@ -1,7 +1,6 @@
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const builtin = @import("builtin");
|
||||
const system_defaults = @import("system_defaults");
|
||||
const is_windows = builtin.os.tag == .windows;
|
||||
|
||||
fn readFileFake(entries: []const Filesystem.Entry, path: []const u8, buf: []u8) ?[]const u8 {
|
||||
@ -25,7 +24,7 @@ fn findProgramByNameFake(entries: []const Filesystem.Entry, name: []const u8, pa
|
||||
const path_env = path orelse return null;
|
||||
var fib = std.heap.FixedBufferAllocator.init(buf);
|
||||
|
||||
var it = mem.tokenizeScalar(u8, path_env, system_defaults.path_sep);
|
||||
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;
|
||||
@ -86,7 +85,7 @@ fn findProgramByNamePosix(name: []const u8, path: ?[]const u8, buf: []u8) ?[]con
|
||||
const path_env = path orelse return null;
|
||||
var fib = std.heap.FixedBufferAllocator.init(buf);
|
||||
|
||||
var it = mem.tokenizeScalar(u8, path_env, system_defaults.path_sep);
|
||||
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;
|
||||
@ -122,8 +121,6 @@ pub const Filesystem = union(enum) {
|
||||
base: []const u8,
|
||||
i: usize = 0,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
fn next(self: *@This()) !?std.fs.IterableDir.Entry {
|
||||
while (self.i < self.entries.len) {
|
||||
const entry = self.entries[self.i];
|
||||
@ -2,9 +2,9 @@ const std = @import("std");
|
||||
const Toolchain = @import("../Toolchain.zig");
|
||||
const target_util = @import("../target.zig");
|
||||
const system_defaults = @import("system_defaults");
|
||||
const util = @import("../util.zig");
|
||||
const GCCVersion = @import("GCCVersion.zig");
|
||||
const Multilib = @import("Multilib.zig");
|
||||
|
||||
const GCCDetector = @This();
|
||||
|
||||
is_valid: bool = false,
|
||||
@ -403,13 +403,22 @@ pub fn discover(self: *GCCDetector, tc: *Toolchain) !void {
|
||||
var fib = std.heap.FixedBufferAllocator.init(&path_buf);
|
||||
|
||||
const target = tc.getTarget();
|
||||
const biarch_variant_target = if (target.ptrBitWidth() == 32) target_util.get64BitArchVariant(target) else target_util.get32BitArchVariant(target);
|
||||
const biarch_variant_target = if (target.ptrBitWidth() == 32)
|
||||
target_util.get64BitArchVariant(target)
|
||||
else
|
||||
target_util.get32BitArchVariant(target);
|
||||
|
||||
var candidate_lib_dirs: PathPrefixes = .{};
|
||||
var candidate_biarch_lib_dirs: PathPrefixes = .{};
|
||||
var candidate_triple_aliases: PathPrefixes = .{};
|
||||
var candidate_biarch_lib_dirs: PathPrefixes = .{};
|
||||
var candidate_biarch_triple_aliases: PathPrefixes = .{};
|
||||
try collectLibDirsAndTriples(tc, &candidate_lib_dirs, &candidate_biarch_lib_dirs, &candidate_triple_aliases, &candidate_biarch_triple_aliases);
|
||||
try collectLibDirsAndTriples(
|
||||
tc,
|
||||
&candidate_lib_dirs,
|
||||
&candidate_triple_aliases,
|
||||
&candidate_biarch_lib_dirs,
|
||||
&candidate_biarch_triple_aliases,
|
||||
);
|
||||
|
||||
var target_buf: [64]u8 = undefined;
|
||||
const triple_str = target_util.toLLVMTriple(target, &target_buf);
|
||||
@ -476,7 +485,13 @@ pub fn discover(self: *GCCDetector, tc: *Toolchain) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn findBiarchMultilibs(tc: *const Toolchain, result: *Multilib.Detected, target: std.Target, path: [2][]const u8, needs_biarch_suffix: bool) !bool {
|
||||
fn findBiarchMultilibs(
|
||||
tc: *const Toolchain,
|
||||
result: *Multilib.Detected,
|
||||
target: std.Target,
|
||||
path: [2][]const u8,
|
||||
needs_biarch_suffix: bool,
|
||||
) !bool {
|
||||
const suff64 = if (target.os.tag == .solaris) switch (target.cpu.arch) {
|
||||
.x86, .x86_64 => "/amd64",
|
||||
.sparc => "/sparcv9",
|
||||
@ -531,7 +546,13 @@ fn findBiarchMultilibs(tc: *const Toolchain, result: *Multilib.Detected, target:
|
||||
return result.select(flags);
|
||||
}
|
||||
|
||||
fn scanGCCForMultilibs(self: *GCCDetector, tc: *const Toolchain, target: std.Target, path: [2][]const u8, needs_biarch_suffix: bool) !bool {
|
||||
fn scanGCCForMultilibs(
|
||||
self: *GCCDetector,
|
||||
tc: *const Toolchain,
|
||||
target: std.Target,
|
||||
path: [2][]const u8,
|
||||
needs_biarch_suffix: bool,
|
||||
) !bool {
|
||||
var detected: Multilib.Detected = .{};
|
||||
if (target.cpu.arch == .csky) {
|
||||
// TODO
|
||||
@ -1,5 +1,4 @@
|
||||
const std = @import("std");
|
||||
const util = @import("../util.zig");
|
||||
const Filesystem = @import("Filesystem.zig").Filesystem;
|
||||
|
||||
pub const Flags = std.BoundedArray([]const u8, 6);
|
||||
@ -12,8 +12,6 @@ const Diagnostics = @import("Diagnostics.zig");
|
||||
const NodeList = std.ArrayList(NodeIndex);
|
||||
const Parser = @import("Parser.zig");
|
||||
|
||||
const InitList = @This();
|
||||
|
||||
const Item = struct {
|
||||
list: InitList = .{},
|
||||
index: u64,
|
||||
@ -23,6 +21,8 @@ const Item = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const InitList = @This();
|
||||
|
||||
list: std.ArrayListUnmanaged(Item) = .{},
|
||||
node: NodeIndex = .none,
|
||||
tok: TokenIndex = 0,
|
||||
@ -1,8 +1,6 @@
|
||||
const std = @import("std");
|
||||
const DiagnosticTag = @import("Diagnostics.zig").Tag;
|
||||
const CharInfo = @import("CharInfo.zig");
|
||||
|
||||
const LangOpts = @This();
|
||||
const char_info = @import("char_info.zig");
|
||||
|
||||
pub const Compiler = enum {
|
||||
clang,
|
||||
@ -44,19 +42,21 @@ pub const Standard = enum {
|
||||
default,
|
||||
/// ISO C 2017 with GNU extensions
|
||||
gnu17,
|
||||
/// Working Draft for ISO C2x
|
||||
c2x,
|
||||
/// Working Draft for ISO C2x with GNU extensions
|
||||
gnu2x,
|
||||
/// Working Draft for ISO C23
|
||||
c23,
|
||||
/// Working Draft for ISO C23 with GNU extensions
|
||||
gnu23,
|
||||
|
||||
const NameMap = std.ComptimeStringMap(Standard, .{
|
||||
.{ "c89", .c89 }, .{ "c90", .c89 }, .{ "iso9899:1990", .c89 },
|
||||
.{ "iso9899:199409", .iso9899 }, .{ "gnu89", .gnu89 }, .{ "gnu90", .gnu89 },
|
||||
.{ "c99", .c99 }, .{ "iso9899:1999", .c99 }, .{ "gnu99", .gnu99 },
|
||||
.{ "c11", .c11 }, .{ "iso9899:2011", .c11 }, .{ "gnu11", .gnu11 },
|
||||
.{ "c17", .c17 }, .{ "iso9899:2017", .c17 }, .{ "c18", .c17 },
|
||||
.{ "iso9899:2018", .c17 }, .{ "gnu17", .gnu17 }, .{ "gnu18", .gnu17 },
|
||||
.{ "c2x", .c2x }, .{ "gnu2x", .gnu2x },
|
||||
.{ "c99", .c99 }, .{ "iso9899:1999", .c99 }, .{ "c9x", .c99 },
|
||||
.{ "iso9899:199x", .c99 }, .{ "gnu99", .gnu99 }, .{ "gnu9x", .gnu99 },
|
||||
.{ "c11", .c11 }, .{ "iso9899:2011", .c11 }, .{ "c1x", .c11 },
|
||||
.{ "iso9899:201x", .c11 }, .{ "gnu11", .gnu11 }, .{ "c17", .c17 },
|
||||
.{ "iso9899:2017", .c17 }, .{ "c18", .c17 }, .{ "iso9899:2018", .c17 },
|
||||
.{ "gnu17", .gnu17 }, .{ "gnu18", .gnu17 }, .{ "c23", .c23 },
|
||||
.{ "gnu23", .gnu23 }, .{ "c2x", .c23 }, .{ "gnu2x", .gnu23 },
|
||||
});
|
||||
|
||||
pub fn atLeast(self: Standard, other: Standard) bool {
|
||||
@ -65,7 +65,7 @@ pub const Standard = enum {
|
||||
|
||||
pub fn isGNU(standard: Standard) bool {
|
||||
return switch (standard) {
|
||||
.gnu89, .gnu99, .gnu11, .default, .gnu17, .gnu2x => true,
|
||||
.gnu89, .gnu99, .gnu11, .default, .gnu17, .gnu23 => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
@ -82,26 +82,31 @@ pub const Standard = enum {
|
||||
.c99, .gnu99 => "199901L",
|
||||
.c11, .gnu11 => "201112L",
|
||||
.default, .c17, .gnu17 => "201710L",
|
||||
// todo: subject to change, verify once c23 finalized
|
||||
.c2x, .gnu2x => "202311L",
|
||||
.c23, .gnu23 => "202311L",
|
||||
};
|
||||
}
|
||||
|
||||
pub fn codepointAllowedInIdentifier(standard: Standard, codepoint: u21, is_start: bool) bool {
|
||||
if (is_start) {
|
||||
return if (standard.atLeast(.c11))
|
||||
CharInfo.isC11IdChar(codepoint) and !CharInfo.isC11DisallowedInitialIdChar(codepoint)
|
||||
return if (standard.atLeast(.c23))
|
||||
char_info.isXidStart(codepoint)
|
||||
else if (standard.atLeast(.c11))
|
||||
char_info.isC11IdChar(codepoint) and !char_info.isC11DisallowedInitialIdChar(codepoint)
|
||||
else
|
||||
CharInfo.isC99IdChar(codepoint) and !CharInfo.isC99DisallowedInitialIDChar(codepoint);
|
||||
char_info.isC99IdChar(codepoint) and !char_info.isC99DisallowedInitialIDChar(codepoint);
|
||||
} else {
|
||||
return if (standard.atLeast(.c11))
|
||||
CharInfo.isC11IdChar(codepoint)
|
||||
return if (standard.atLeast(.c23))
|
||||
char_info.isXidContinue(codepoint)
|
||||
else if (standard.atLeast(.c11))
|
||||
char_info.isC11IdChar(codepoint)
|
||||
else
|
||||
CharInfo.isC99IdChar(codepoint);
|
||||
char_info.isC99IdChar(codepoint);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const LangOpts = @This();
|
||||
|
||||
emulate: Compiler = .clang,
|
||||
standard: Standard = .default,
|
||||
/// -fshort-enums option, makes enums only take up as much space as they need to hold all the values.
|
||||
@ -119,7 +124,7 @@ allow_half_args_and_returns: bool = false,
|
||||
fp_eval_method: ?FPEvalMethod = null,
|
||||
/// If set, use specified signedness for `char` instead of the target's default char signedness
|
||||
char_signedness_override: ?std.builtin.Signedness = null,
|
||||
/// If set, override the default availability of char8_t (by default, enabled in C2X and later; disabled otherwise)
|
||||
/// If set, override the default availability of char8_t (by default, enabled in C23 and later; disabled otherwise)
|
||||
has_char8_t_override: ?bool = null,
|
||||
|
||||
/// Whether to allow GNU-style inline assembly
|
||||
@ -145,7 +150,7 @@ pub fn disableMSExtensions(self: *LangOpts) void {
|
||||
}
|
||||
|
||||
pub fn hasChar8_T(self: *const LangOpts) bool {
|
||||
return self.has_char8_t_override orelse self.standard.atLeast(.c2x);
|
||||
return self.has_char8_t_override orelse self.standard.atLeast(.c23);
|
||||
}
|
||||
|
||||
pub fn hasDigraphs(self: *const LangOpts) bool {
|
||||
1416
deps/aro/Parser.zig → deps/aro/aro/Parser.zig
vendored
1416
deps/aro/Parser.zig → deps/aro/aro/Parser.zig
vendored
File diff suppressed because it is too large
Load Diff
@ -4,10 +4,10 @@ const Preprocessor = @import("Preprocessor.zig");
|
||||
const Parser = @import("Parser.zig");
|
||||
const TokenIndex = @import("Tree.zig").TokenIndex;
|
||||
|
||||
const Pragma = @This();
|
||||
|
||||
pub const Error = Compilation.Error || error{ UnknownPragma, StopPreprocessing };
|
||||
|
||||
const Pragma = @This();
|
||||
|
||||
/// Called during Preprocessor.init
|
||||
beforePreprocess: ?*const fn (*Pragma, *Compilation) void = null,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,4 @@
|
||||
const std = @import("std");
|
||||
const Source = @This();
|
||||
|
||||
pub const Id = enum(u32) {
|
||||
unused = 0,
|
||||
@ -27,6 +26,8 @@ pub const Location = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const Source = @This();
|
||||
|
||||
path: []const u8,
|
||||
buf: []const u8,
|
||||
id: Id,
|
||||
@ -1,7 +1,6 @@
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
|
||||
const StringInterner = @This();
|
||||
const Compilation = @import("Compilation.zig");
|
||||
|
||||
const StringToIdMap = std.StringHashMapUnmanaged(StringId);
|
||||
|
||||
@ -43,6 +42,8 @@ pub const TypeMapper = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const StringInterner = @This();
|
||||
|
||||
string_table: StringToIdMap = .{},
|
||||
next_id: StringId = @enumFromInt(@intFromEnum(StringId.empty) + 1),
|
||||
|
||||
@ -50,7 +51,11 @@ pub fn deinit(self: *StringInterner, allocator: mem.Allocator) void {
|
||||
self.string_table.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn intern(self: *StringInterner, allocator: mem.Allocator, str: []const u8) !StringId {
|
||||
pub fn intern(comp: *Compilation, str: []const u8) !StringId {
|
||||
return comp.string_interner.internExtra(comp.gpa, str);
|
||||
}
|
||||
|
||||
pub fn internExtra(self: *StringInterner, allocator: mem.Allocator, str: []const u8) !StringId {
|
||||
if (str.len == 0) return .empty;
|
||||
|
||||
const gop = try self.string_table.getOrPut(allocator, str);
|
||||
@ -11,8 +11,6 @@ const Parser = @import("Parser.zig");
|
||||
const Value = @import("Value.zig");
|
||||
const StringId = @import("StringInterner.zig").StringId;
|
||||
|
||||
const SymbolStack = @This();
|
||||
|
||||
pub const Symbol = struct {
|
||||
name: StringId,
|
||||
ty: Type,
|
||||
@ -33,6 +31,8 @@ pub const Kind = enum {
|
||||
constexpr,
|
||||
};
|
||||
|
||||
const SymbolStack = @This();
|
||||
|
||||
syms: std.MultiArrayList(Symbol) = .{},
|
||||
scopes: std.ArrayListUnmanaged(u32) = .{},
|
||||
|
||||
@ -4,8 +4,6 @@ const Compilation = @import("Compilation.zig");
|
||||
const Source = @import("Source.zig");
|
||||
const LangOpts = @import("LangOpts.zig");
|
||||
|
||||
const Tokenizer = @This();
|
||||
|
||||
pub const Token = struct {
|
||||
id: Id,
|
||||
source: Source.Id,
|
||||
@ -121,6 +119,8 @@ pub const Token = struct {
|
||||
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
|
||||
@ -135,6 +135,8 @@ pub const Token = struct {
|
||||
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__
|
||||
@ -216,6 +218,7 @@ pub const Token = struct {
|
||||
keyword_true,
|
||||
keyword_false,
|
||||
keyword_nullptr,
|
||||
keyword_typeof_unqual,
|
||||
|
||||
// Preprocessor directives
|
||||
keyword_include,
|
||||
@ -235,6 +238,7 @@ pub const Token = struct {
|
||||
keyword_pragma,
|
||||
keyword_line,
|
||||
keyword_va_args,
|
||||
keyword_va_opt,
|
||||
|
||||
// gcc keywords
|
||||
keyword_const1,
|
||||
@ -255,7 +259,10 @@ pub const Token = struct {
|
||||
keyword_asm1,
|
||||
keyword_asm2,
|
||||
keyword_float80,
|
||||
keyword_float128,
|
||||
/// _Float128
|
||||
keyword_float128_1,
|
||||
/// __float128
|
||||
keyword_float128_2,
|
||||
keyword_int128,
|
||||
keyword_imag1,
|
||||
keyword_imag2,
|
||||
@ -335,6 +342,7 @@ pub const Token = struct {
|
||||
.keyword_pragma,
|
||||
.keyword_line,
|
||||
.keyword_va_args,
|
||||
.keyword_va_opt,
|
||||
.macro_func,
|
||||
.macro_function,
|
||||
.macro_pretty_func,
|
||||
@ -410,7 +418,8 @@ pub const Token = struct {
|
||||
.keyword_asm1,
|
||||
.keyword_asm2,
|
||||
.keyword_float80,
|
||||
.keyword_float128,
|
||||
.keyword_float128_1,
|
||||
.keyword_float128_2,
|
||||
.keyword_int128,
|
||||
.keyword_imag1,
|
||||
.keyword_imag2,
|
||||
@ -443,6 +452,7 @@ pub const Token = struct {
|
||||
.keyword_true,
|
||||
.keyword_false,
|
||||
.keyword_nullptr,
|
||||
.keyword_typeof_unqual,
|
||||
=> return true,
|
||||
else => return false,
|
||||
}
|
||||
@ -469,6 +479,7 @@ pub const Token = struct {
|
||||
.keyword_pragma,
|
||||
.keyword_line,
|
||||
.keyword_va_args,
|
||||
.keyword_va_opt,
|
||||
=> id.* = .identifier,
|
||||
.keyword_defined => if (defined_to_identifier) {
|
||||
id.* = .identifier;
|
||||
@ -485,9 +496,9 @@ pub const Token = struct {
|
||||
return switch (id) {
|
||||
.include_start,
|
||||
.include_resume,
|
||||
.unterminated_comment, // Fatal error; parsing should not be attempted
|
||||
=> unreachable,
|
||||
|
||||
.unterminated_comment,
|
||||
.invalid,
|
||||
.identifier,
|
||||
.extended_identifier,
|
||||
@ -521,6 +532,7 @@ pub const Token = struct {
|
||||
.stringify_param,
|
||||
.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,
|
||||
@ -528,6 +540,7 @@ pub const Token = struct {
|
||||
.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,
|
||||
@ -647,6 +660,7 @@ pub const Token = struct {
|
||||
.keyword_true => "true",
|
||||
.keyword_false => "false",
|
||||
.keyword_nullptr => "nullptr",
|
||||
.keyword_typeof_unqual => "typeof_unqual",
|
||||
.keyword_include => "include",
|
||||
.keyword_include_next => "include_next",
|
||||
.keyword_embed => "embed",
|
||||
@ -664,6 +678,7 @@ pub const Token = struct {
|
||||
.keyword_pragma => "pragma",
|
||||
.keyword_line => "line",
|
||||
.keyword_va_args => "__VA_ARGS__",
|
||||
.keyword_va_opt => "__VA_OPT__",
|
||||
.keyword_const1 => "__const",
|
||||
.keyword_const2 => "__const__",
|
||||
.keyword_inline1 => "__inline",
|
||||
@ -688,7 +703,8 @@ pub const Token = struct {
|
||||
.keyword_asm1 => "__asm",
|
||||
.keyword_asm2 => "__asm__",
|
||||
.keyword_float80 => "__float80",
|
||||
.keyword_float128 => "__float18",
|
||||
.keyword_float128_1 => "_Float128",
|
||||
.keyword_float128_2 => "__float128",
|
||||
.keyword_int128 => "__int128",
|
||||
.keyword_imag1 => "__imag",
|
||||
.keyword_imag2 => "__imag__",
|
||||
@ -819,7 +835,7 @@ pub const Token = struct {
|
||||
return switch (kw) {
|
||||
.keyword_inline => if (standard.isGNU() or standard.atLeast(.c99)) kw else .identifier,
|
||||
.keyword_restrict => if (standard.atLeast(.c99)) kw else .identifier,
|
||||
.keyword_typeof => if (standard.isGNU() or standard.atLeast(.c2x)) kw else .identifier,
|
||||
.keyword_typeof => if (standard.isGNU() or standard.atLeast(.c23)) kw else .identifier,
|
||||
.keyword_asm => if (standard.isGNU()) kw else .identifier,
|
||||
.keyword_declspec => if (comp.langopts.declspec_attrs) kw else .identifier,
|
||||
|
||||
@ -832,9 +848,10 @@ pub const Token = struct {
|
||||
.keyword_true,
|
||||
.keyword_false,
|
||||
.keyword_nullptr,
|
||||
.keyword_typeof_unqual,
|
||||
.keyword_elifdef,
|
||||
.keyword_elifndef,
|
||||
=> if (standard.atLeast(.c2x)) kw else .identifier,
|
||||
=> if (standard.atLeast(.c23)) kw else .identifier,
|
||||
|
||||
.keyword_int64,
|
||||
.keyword_int64_2,
|
||||
@ -918,6 +935,7 @@ pub const Token = struct {
|
||||
.{ "true", .keyword_true },
|
||||
.{ "false", .keyword_false },
|
||||
.{ "nullptr", .keyword_nullptr },
|
||||
.{ "typeof_unqual", .keyword_typeof_unqual },
|
||||
|
||||
// Preprocessor directives
|
||||
.{ "include", .keyword_include },
|
||||
@ -937,6 +955,7 @@ pub const Token = struct {
|
||||
.{ "pragma", .keyword_pragma },
|
||||
.{ "line", .keyword_line },
|
||||
.{ "__VA_ARGS__", .keyword_va_args },
|
||||
.{ "__VA_OPT__", .keyword_va_opt },
|
||||
.{ "__func__", .macro_func },
|
||||
.{ "__FUNCTION__", .macro_function },
|
||||
.{ "__PRETTY_FUNCTION__", .macro_pretty_func },
|
||||
@ -961,7 +980,8 @@ pub const Token = struct {
|
||||
.{ "__asm", .keyword_asm1 },
|
||||
.{ "__asm__", .keyword_asm2 },
|
||||
.{ "__float80", .keyword_float80 },
|
||||
.{ "__float128", .keyword_float128 },
|
||||
.{ "_Float128", .keyword_float128_1 },
|
||||
.{ "__float128", .keyword_float128_2 },
|
||||
.{ "__int128", .keyword_int128 },
|
||||
.{ "__imag", .keyword_imag1 },
|
||||
.{ "__imag__", .keyword_imag2 },
|
||||
@ -998,6 +1018,8 @@ pub const Token = struct {
|
||||
});
|
||||
};
|
||||
|
||||
const Tokenizer = @This();
|
||||
|
||||
buf: []const u8,
|
||||
index: u32 = 0,
|
||||
source: Source.Id,
|
||||
@ -1345,7 +1367,7 @@ pub fn next(self: *Tokenizer) Token {
|
||||
break;
|
||||
},
|
||||
':' => {
|
||||
if (self.comp.langopts.standard.atLeast(.c2x)) {
|
||||
if (self.comp.langopts.standard.atLeast(.c23)) {
|
||||
id = .colon_colon;
|
||||
self.index += 1;
|
||||
break;
|
||||
@ -1651,7 +1673,7 @@ pub fn next(self: *Tokenizer) Token {
|
||||
'.',
|
||||
=> {},
|
||||
'e', 'E', 'p', 'P' => state = .pp_num_exponent,
|
||||
'\'' => if (self.comp.langopts.standard.atLeast(.c2x)) {
|
||||
'\'' => if (self.comp.langopts.standard.atLeast(.c23)) {
|
||||
state = .pp_num_digit_separator;
|
||||
} else {
|
||||
id = .pp_num;
|
||||
@ -1679,14 +1701,17 @@ pub fn next(self: *Tokenizer) Token {
|
||||
},
|
||||
},
|
||||
.pp_num_exponent => switch (c) {
|
||||
'a'...'z',
|
||||
'A'...'Z',
|
||||
'a'...'o',
|
||||
'q'...'z',
|
||||
'A'...'O',
|
||||
'Q'...'Z',
|
||||
'0'...'9',
|
||||
'_',
|
||||
'.',
|
||||
'+',
|
||||
'-',
|
||||
=> state = .pp_num,
|
||||
'p', 'P' => {},
|
||||
else => {
|
||||
id = .pp_num;
|
||||
break;
|
||||
@ -1761,6 +1786,16 @@ pub fn nextNoWSComments(self: *Tokenizer) Token {
|
||||
return tok;
|
||||
}
|
||||
|
||||
/// Try to tokenize a '::' even if not supported by the current language standard.
|
||||
pub fn colonColon(self: *Tokenizer) Token {
|
||||
var tok = self.nextNoWS();
|
||||
if (tok.id == .colon and self.buf[self.index] == ':') {
|
||||
self.index += 1;
|
||||
tok.id = .colon_colon;
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
test "operators" {
|
||||
try expectTokens(
|
||||
\\ ! != | || |= = ==
|
||||
@ -2091,7 +2126,7 @@ test "digraphs" {
|
||||
}
|
||||
|
||||
test "C23 keywords" {
|
||||
try expectTokensExtra("true false alignas alignof bool static_assert thread_local nullptr", &.{
|
||||
try expectTokensExtra("true false alignas alignof bool static_assert thread_local nullptr typeof_unqual", &.{
|
||||
.keyword_true,
|
||||
.keyword_false,
|
||||
.keyword_c23_alignas,
|
||||
@ -2100,7 +2135,8 @@ test "C23 keywords" {
|
||||
.keyword_c23_static_assert,
|
||||
.keyword_c23_thread_local,
|
||||
.keyword_nullptr,
|
||||
}, .c2x);
|
||||
.keyword_typeof_unqual,
|
||||
}, .c23);
|
||||
}
|
||||
|
||||
fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, standard: ?LangOpts.Standard) !void {
|
||||
@ -1,7 +1,6 @@
|
||||
const std = @import("std");
|
||||
const Driver = @import("Driver.zig");
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const util = @import("util.zig");
|
||||
const mem = std.mem;
|
||||
const system_defaults = @import("system_defaults");
|
||||
const target_util = @import("target.zig");
|
||||
@ -9,8 +8,6 @@ const Linux = @import("toolchains/Linux.zig");
|
||||
const Multilib = @import("Driver/Multilib.zig");
|
||||
const Filesystem = @import("Driver/Filesystem.zig").Filesystem;
|
||||
|
||||
const Toolchain = @This();
|
||||
|
||||
pub const PathList = std.ArrayListUnmanaged([]const u8);
|
||||
|
||||
pub const RuntimeLibKind = enum {
|
||||
@ -49,6 +46,8 @@ const Inner = union(enum) {
|
||||
}
|
||||
};
|
||||
|
||||
const Toolchain = @This();
|
||||
|
||||
filesystem: Filesystem = .{ .real = {} },
|
||||
driver: *Driver,
|
||||
arena: mem.Allocator,
|
||||
@ -152,7 +151,7 @@ pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 {
|
||||
// to a relative path is surprising. This is more complex due to priorities
|
||||
// among -B, COMPILER_PATH and PATH. --ld-path= should be used instead.
|
||||
if (mem.indexOfScalar(u8, use_linker, '/') != null) {
|
||||
try tc.driver.comp.diag.add(.{ .tag = .fuse_ld_path }, &.{});
|
||||
try tc.driver.comp.addDiagnostic(.{ .tag = .fuse_ld_path }, &.{});
|
||||
}
|
||||
|
||||
if (std.fs.path.isAbsolute(use_linker)) {
|
||||
@ -402,7 +401,7 @@ fn getUnwindLibKind(tc: *const Toolchain) !UnwindLibKind {
|
||||
return .libgcc;
|
||||
} else if (mem.eql(u8, libname, "libunwind")) {
|
||||
if (tc.getRuntimeLibKind() == .libgcc) {
|
||||
try tc.driver.comp.diag.add(.{ .tag = .incompatible_unwindlib }, &.{});
|
||||
try tc.driver.comp.addDiagnostic(.{ .tag = .incompatible_unwindlib }, &.{});
|
||||
}
|
||||
return .compiler_rt;
|
||||
} else {
|
||||
@ -479,7 +478,7 @@ pub fn addRuntimeLibs(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !v
|
||||
if (target_util.isKnownWindowsMSVCEnvironment(target)) {
|
||||
const rtlib_str = tc.driver.rtlib orelse system_defaults.rtlib;
|
||||
if (!mem.eql(u8, rtlib_str, "platform")) {
|
||||
try tc.driver.comp.diag.add(.{ .tag = .unsupported_rtlib_gcc, .extra = .{ .str = "MSVC" } }, &.{});
|
||||
try tc.driver.comp.addDiagnostic(.{ .tag = .unsupported_rtlib_gcc, .extra = .{ .str = "MSVC" } }, &.{});
|
||||
}
|
||||
} else {
|
||||
try tc.addLibGCC(argv);
|
||||
368
deps/aro/Tree.zig → deps/aro/aro/Tree.zig
vendored
368
deps/aro/Tree.zig → deps/aro/aro/Tree.zig
vendored
@ -1,14 +1,14 @@
|
||||
const std = @import("std");
|
||||
const Interner = @import("backend").Interner;
|
||||
const Type = @import("Type.zig");
|
||||
const Tokenizer = @import("Tokenizer.zig");
|
||||
const CodeGen = @import("CodeGen.zig");
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Source = @import("Source.zig");
|
||||
const Attribute = @import("Attribute.zig");
|
||||
const Value = @import("Value.zig");
|
||||
const StringInterner = @import("StringInterner.zig");
|
||||
|
||||
const Tree = @This();
|
||||
|
||||
pub const Token = struct {
|
||||
id: Id,
|
||||
flags: packed struct {
|
||||
@ -79,7 +79,7 @@ pub const Token = struct {
|
||||
pub fn checkMsEof(tok: Token, source: Source, comp: *Compilation) !void {
|
||||
std.debug.assert(tok.id == .eof);
|
||||
if (source.buf.len > tok.loc.byte_offset and source.buf[tok.loc.byte_offset] == 0x1A) {
|
||||
try comp.diag.add(.{
|
||||
try comp.addDiagnostic(.{
|
||||
.tag = .ctrl_z_eof,
|
||||
.loc = .{
|
||||
.id = source.id,
|
||||
@ -98,6 +98,8 @@ pub const TokenIndex = u32;
|
||||
pub const NodeIndex = enum(u32) { none, _ };
|
||||
pub const ValueMap = std.AutoHashMap(NodeIndex, Value);
|
||||
|
||||
const Tree = @This();
|
||||
|
||||
comp: *Compilation,
|
||||
arena: std.heap.ArenaAllocator,
|
||||
generated: []const u8,
|
||||
@ -105,13 +107,13 @@ tokens: Token.List.Slice,
|
||||
nodes: Node.List.Slice,
|
||||
data: []const NodeIndex,
|
||||
root_decls: []const NodeIndex,
|
||||
strings: []const u8,
|
||||
value_map: ValueMap,
|
||||
|
||||
pub const genIr = CodeGen.genIr;
|
||||
|
||||
pub fn deinit(tree: *Tree) void {
|
||||
tree.comp.gpa.free(tree.root_decls);
|
||||
tree.comp.gpa.free(tree.data);
|
||||
tree.comp.gpa.free(tree.strings);
|
||||
tree.nodes.deinit(tree.comp.gpa);
|
||||
tree.arena.deinit();
|
||||
tree.value_map.deinit();
|
||||
@ -161,7 +163,7 @@ pub const Node = struct {
|
||||
int: u64,
|
||||
return_zero: bool,
|
||||
|
||||
pub fn forDecl(data: Data, tree: Tree) struct {
|
||||
pub fn forDecl(data: Data, tree: *const Tree) struct {
|
||||
decls: []const NodeIndex,
|
||||
cond: NodeIndex,
|
||||
incr: NodeIndex,
|
||||
@ -178,7 +180,7 @@ pub const Node = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn forStmt(data: Data, tree: Tree) struct {
|
||||
pub fn forStmt(data: Data, tree: *const Tree) struct {
|
||||
init: NodeIndex,
|
||||
cond: NodeIndex,
|
||||
incr: NodeIndex,
|
||||
@ -495,12 +497,8 @@ pub const Tag = enum(u8) {
|
||||
int_literal,
|
||||
/// Same as int_literal, but originates from a char literal
|
||||
char_literal,
|
||||
/// _Float16 literal
|
||||
float16_literal,
|
||||
/// f32 literal
|
||||
/// a floating point literal
|
||||
float_literal,
|
||||
/// f64 literal
|
||||
double_literal,
|
||||
/// wraps a float or double literal: un
|
||||
imaginary_literal,
|
||||
/// tree.str[index..][0..len]
|
||||
@ -540,6 +538,12 @@ pub const Tag = enum(u8) {
|
||||
union_init_expr,
|
||||
/// (ty){ un }
|
||||
compound_literal_expr,
|
||||
/// (static ty){ un }
|
||||
static_compound_literal_expr,
|
||||
/// (thread_local ty){ un }
|
||||
thread_local_compound_literal_expr,
|
||||
/// (static thread_local ty){ un }
|
||||
static_thread_local_compound_literal_expr,
|
||||
|
||||
/// Inserted at the end of a function body if no return stmt is found.
|
||||
/// ty is the functions return type
|
||||
@ -566,18 +570,18 @@ pub const Tag = enum(u8) {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn isBitfield(nodes: Node.List.Slice, node: NodeIndex) bool {
|
||||
return bitfieldWidth(nodes, node, false) != null;
|
||||
pub fn isBitfield(tree: *const Tree, node: NodeIndex) bool {
|
||||
return tree.bitfieldWidth(node, false) != null;
|
||||
}
|
||||
|
||||
/// Returns null if node is not a bitfield. If inspect_lval is true, this function will
|
||||
/// recurse into implicit lval_to_rval casts (useful for arithmetic conversions)
|
||||
pub fn bitfieldWidth(nodes: Node.List.Slice, node: NodeIndex, inspect_lval: bool) ?u32 {
|
||||
pub fn bitfieldWidth(tree: *const Tree, node: NodeIndex, inspect_lval: bool) ?u32 {
|
||||
if (node == .none) return null;
|
||||
switch (nodes.items(.tag)[@intFromEnum(node)]) {
|
||||
switch (tree.nodes.items(.tag)[@intFromEnum(node)]) {
|
||||
.member_access_expr, .member_access_ptr_expr => {
|
||||
const member = nodes.items(.data)[@intFromEnum(node)].member;
|
||||
var ty = nodes.items(.ty)[@intFromEnum(member.lhs)];
|
||||
const member = tree.nodes.items(.data)[@intFromEnum(node)].member;
|
||||
var ty = tree.nodes.items(.ty)[@intFromEnum(member.lhs)];
|
||||
if (ty.isPtr()) ty = ty.elemType();
|
||||
const record_ty = ty.get(.@"struct") orelse ty.get(.@"union") orelse return null;
|
||||
const field = record_ty.data.record.fields[member.index];
|
||||
@ -586,9 +590,9 @@ pub fn bitfieldWidth(nodes: Node.List.Slice, node: NodeIndex, inspect_lval: bool
|
||||
.implicit_cast => {
|
||||
if (!inspect_lval) return null;
|
||||
|
||||
const data = nodes.items(.data)[@intFromEnum(node)];
|
||||
const data = tree.nodes.items(.data)[@intFromEnum(node)];
|
||||
return switch (data.cast.kind) {
|
||||
.lval_to_rval => bitfieldWidth(nodes, data.cast.operand, false),
|
||||
.lval_to_rval => tree.bitfieldWidth(data.cast.operand, false),
|
||||
else => null,
|
||||
};
|
||||
},
|
||||
@ -596,59 +600,63 @@ pub fn bitfieldWidth(nodes: Node.List.Slice, node: NodeIndex, inspect_lval: bool
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isLval(nodes: Node.List.Slice, extra: []const NodeIndex, value_map: ValueMap, node: NodeIndex) bool {
|
||||
pub fn isLval(tree: *const Tree, node: NodeIndex) bool {
|
||||
var is_const: bool = undefined;
|
||||
return isLvalExtra(nodes, extra, value_map, node, &is_const);
|
||||
return tree.isLvalExtra(node, &is_const);
|
||||
}
|
||||
|
||||
pub fn isLvalExtra(nodes: Node.List.Slice, extra: []const NodeIndex, value_map: ValueMap, node: NodeIndex, is_const: *bool) bool {
|
||||
pub fn isLvalExtra(tree: *const Tree, node: NodeIndex, is_const: *bool) bool {
|
||||
is_const.* = false;
|
||||
switch (nodes.items(.tag)[@intFromEnum(node)]) {
|
||||
.compound_literal_expr => {
|
||||
is_const.* = nodes.items(.ty)[@intFromEnum(node)].isConst();
|
||||
switch (tree.nodes.items(.tag)[@intFromEnum(node)]) {
|
||||
.compound_literal_expr,
|
||||
.static_compound_literal_expr,
|
||||
.thread_local_compound_literal_expr,
|
||||
.static_thread_local_compound_literal_expr,
|
||||
=> {
|
||||
is_const.* = tree.nodes.items(.ty)[@intFromEnum(node)].isConst();
|
||||
return true;
|
||||
},
|
||||
.string_literal_expr => return true,
|
||||
.member_access_ptr_expr => {
|
||||
const lhs_expr = nodes.items(.data)[@intFromEnum(node)].member.lhs;
|
||||
const ptr_ty = nodes.items(.ty)[@intFromEnum(lhs_expr)];
|
||||
const lhs_expr = tree.nodes.items(.data)[@intFromEnum(node)].member.lhs;
|
||||
const ptr_ty = tree.nodes.items(.ty)[@intFromEnum(lhs_expr)];
|
||||
if (ptr_ty.isPtr()) is_const.* = ptr_ty.elemType().isConst();
|
||||
return true;
|
||||
},
|
||||
.array_access_expr => {
|
||||
const lhs_expr = nodes.items(.data)[@intFromEnum(node)].bin.lhs;
|
||||
const lhs_expr = tree.nodes.items(.data)[@intFromEnum(node)].bin.lhs;
|
||||
if (lhs_expr != .none) {
|
||||
const array_ty = nodes.items(.ty)[@intFromEnum(lhs_expr)];
|
||||
const array_ty = tree.nodes.items(.ty)[@intFromEnum(lhs_expr)];
|
||||
if (array_ty.isPtr() or array_ty.isArray()) is_const.* = array_ty.elemType().isConst();
|
||||
}
|
||||
return true;
|
||||
},
|
||||
.decl_ref_expr => {
|
||||
const decl_ty = nodes.items(.ty)[@intFromEnum(node)];
|
||||
const decl_ty = tree.nodes.items(.ty)[@intFromEnum(node)];
|
||||
is_const.* = decl_ty.isConst();
|
||||
return true;
|
||||
},
|
||||
.deref_expr => {
|
||||
const data = nodes.items(.data)[@intFromEnum(node)];
|
||||
const operand_ty = nodes.items(.ty)[@intFromEnum(data.un)];
|
||||
const data = tree.nodes.items(.data)[@intFromEnum(node)];
|
||||
const operand_ty = tree.nodes.items(.ty)[@intFromEnum(data.un)];
|
||||
if (operand_ty.isFunc()) return false;
|
||||
if (operand_ty.isPtr() or operand_ty.isArray()) is_const.* = operand_ty.elemType().isConst();
|
||||
return true;
|
||||
},
|
||||
.member_access_expr => {
|
||||
const data = nodes.items(.data)[@intFromEnum(node)];
|
||||
return isLvalExtra(nodes, extra, value_map, data.member.lhs, is_const);
|
||||
const data = tree.nodes.items(.data)[@intFromEnum(node)];
|
||||
return tree.isLvalExtra(data.member.lhs, is_const);
|
||||
},
|
||||
.paren_expr => {
|
||||
const data = nodes.items(.data)[@intFromEnum(node)];
|
||||
return isLvalExtra(nodes, extra, value_map, data.un, is_const);
|
||||
const data = tree.nodes.items(.data)[@intFromEnum(node)];
|
||||
return tree.isLvalExtra(data.un, is_const);
|
||||
},
|
||||
.builtin_choose_expr => {
|
||||
const data = nodes.items(.data)[@intFromEnum(node)];
|
||||
const data = tree.nodes.items(.data)[@intFromEnum(node)];
|
||||
|
||||
if (value_map.get(data.if3.cond)) |val| {
|
||||
const offset = @intFromBool(val.isZero());
|
||||
return isLvalExtra(nodes, extra, value_map, extra[data.if3.body + offset], is_const);
|
||||
if (tree.value_map.get(data.if3.cond)) |val| {
|
||||
const offset = @intFromBool(val.isZero(tree.comp));
|
||||
return tree.isLvalExtra(tree.data[data.if3.body + offset], is_const);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
@ -656,7 +664,7 @@ pub fn isLvalExtra(nodes: Node.List.Slice, extra: []const NodeIndex, value_map:
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tokSlice(tree: Tree, tok_i: TokenIndex) []const u8 {
|
||||
pub fn tokSlice(tree: *const Tree, tok_i: TokenIndex) []const u8 {
|
||||
if (tree.tokens.items(.id)[tok_i].lexeme()) |some| return some;
|
||||
const loc = tree.tokens.items(.loc)[tok_i];
|
||||
var tmp_tokenizer = Tokenizer{
|
||||
@ -669,25 +677,25 @@ pub fn tokSlice(tree: Tree, tok_i: TokenIndex) []const u8 {
|
||||
return tmp_tokenizer.buf[tok.start..tok.end];
|
||||
}
|
||||
|
||||
pub fn dump(tree: Tree, color: bool, writer: anytype) @TypeOf(writer).Error!void {
|
||||
pub fn dump(tree: *const Tree, config: std.io.tty.Config, writer: anytype) !void {
|
||||
const mapper = tree.comp.string_interner.getFastTypeMapper(tree.comp.gpa) catch tree.comp.string_interner.getSlowTypeMapper();
|
||||
defer mapper.deinit(tree.comp.gpa);
|
||||
|
||||
for (tree.root_decls) |i| {
|
||||
try tree.dumpNode(i, 0, mapper, color, writer);
|
||||
try tree.dumpNode(i, 0, mapper, config, writer);
|
||||
try writer.writeByte('\n');
|
||||
}
|
||||
}
|
||||
|
||||
fn dumpFieldAttributes(attributes: []const Attribute, level: u32, strings: []const u8, writer: anytype) !void {
|
||||
fn dumpFieldAttributes(tree: *const Tree, attributes: []const Attribute, level: u32, writer: anytype) !void {
|
||||
for (attributes) |attr| {
|
||||
try writer.writeByteNTimes(' ', level);
|
||||
try writer.print("field attr: {s}", .{@tagName(attr.tag)});
|
||||
try dumpAttribute(attr, strings, writer);
|
||||
try tree.dumpAttribute(attr, writer);
|
||||
}
|
||||
}
|
||||
|
||||
fn dumpAttribute(attr: Attribute, strings: []const u8, writer: anytype) !void {
|
||||
fn dumpAttribute(tree: *const Tree, attr: Attribute, writer: anytype) !void {
|
||||
switch (attr.tag) {
|
||||
inline else => |tag| {
|
||||
const args = @field(attr.args, @tagName(tag));
|
||||
@ -705,8 +713,8 @@ fn dumpAttribute(attr: Attribute, strings: []const u8, writer: anytype) !void {
|
||||
try writer.writeAll(f.name);
|
||||
try writer.writeAll(": ");
|
||||
switch (f.type) {
|
||||
Value.ByteRange => try writer.print("\"{s}\"", .{@field(args, f.name).slice(strings, .@"1")}),
|
||||
?Value.ByteRange => try writer.print("\"{?s}\"", .{if (@field(args, f.name)) |range| range.slice(strings, .@"1") else null}),
|
||||
Interner.Ref => try writer.print("\"{s}\"", .{tree.interner.get(@field(args, f.name)).bytes}),
|
||||
?Interner.Ref => try writer.print("\"{?s}\"", .{if (@field(args, f.name)) |str| tree.interner.get(str).bytes else null}),
|
||||
else => switch (@typeInfo(f.type)) {
|
||||
.Enum => try writer.writeAll(@tagName(@field(args, f.name))),
|
||||
else => try writer.print("{any}", .{@field(args, f.name)}),
|
||||
@ -719,16 +727,22 @@ fn dumpAttribute(attr: Attribute, strings: []const u8, writer: anytype) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.TypeMapper, color: bool, w: anytype) @TypeOf(w).Error!void {
|
||||
fn dumpNode(
|
||||
tree: *const Tree,
|
||||
node: NodeIndex,
|
||||
level: u32,
|
||||
mapper: StringInterner.TypeMapper,
|
||||
config: std.io.tty.Config,
|
||||
w: anytype,
|
||||
) !void {
|
||||
const delta = 2;
|
||||
const half = delta / 2;
|
||||
const util = @import("util.zig");
|
||||
const TYPE = util.Color.purple;
|
||||
const TAG = util.Color.cyan;
|
||||
const IMPLICIT = util.Color.blue;
|
||||
const NAME = util.Color.red;
|
||||
const LITERAL = util.Color.green;
|
||||
const ATTRIBUTE = util.Color.yellow;
|
||||
const TYPE = std.io.tty.Color.bright_magenta;
|
||||
const TAG = std.io.tty.Color.bright_cyan;
|
||||
const IMPLICIT = std.io.tty.Color.bright_blue;
|
||||
const NAME = std.io.tty.Color.bright_red;
|
||||
const LITERAL = std.io.tty.Color.bright_green;
|
||||
const ATTRIBUTE = std.io.tty.Color.bright_yellow;
|
||||
std.debug.assert(node != .none);
|
||||
|
||||
const tag = tree.nodes.items(.tag)[@intFromEnum(node)];
|
||||
@ -736,68 +750,68 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
const ty = tree.nodes.items(.ty)[@intFromEnum(node)];
|
||||
try w.writeByteNTimes(' ', level);
|
||||
|
||||
if (color) util.setColor(if (tag.isImplicit()) IMPLICIT else TAG, w);
|
||||
try config.setColor(w, if (tag.isImplicit()) IMPLICIT else TAG);
|
||||
try w.print("{s}: ", .{@tagName(tag)});
|
||||
if (tag == .implicit_cast or tag == .explicit_cast) {
|
||||
if (color) util.setColor(.white, w);
|
||||
try config.setColor(w, .white);
|
||||
try w.print("({s}) ", .{@tagName(data.cast.kind)});
|
||||
}
|
||||
if (color) util.setColor(TYPE, w);
|
||||
try config.setColor(w, TYPE);
|
||||
try w.writeByte('\'');
|
||||
try ty.dump(mapper, tree.comp.langopts, w);
|
||||
try w.writeByte('\'');
|
||||
|
||||
if (isLval(tree.nodes, tree.data, tree.value_map, node)) {
|
||||
if (color) util.setColor(ATTRIBUTE, w);
|
||||
if (tree.isLval(node)) {
|
||||
try config.setColor(w, ATTRIBUTE);
|
||||
try w.writeAll(" lvalue");
|
||||
}
|
||||
if (isBitfield(tree.nodes, node)) {
|
||||
if (color) util.setColor(ATTRIBUTE, w);
|
||||
if (tree.isBitfield(node)) {
|
||||
try config.setColor(w, ATTRIBUTE);
|
||||
try w.writeAll(" bitfield");
|
||||
}
|
||||
if (tree.value_map.get(node)) |val| {
|
||||
if (color) util.setColor(LITERAL, w);
|
||||
try config.setColor(w, LITERAL);
|
||||
try w.writeAll(" (value: ");
|
||||
try val.dump(ty, tree.comp, tree.strings, w);
|
||||
try val.print(ty, tree.comp, w);
|
||||
try w.writeByte(')');
|
||||
}
|
||||
if (tag == .implicit_return and data.return_zero) {
|
||||
if (color) util.setColor(IMPLICIT, w);
|
||||
try config.setColor(w, IMPLICIT);
|
||||
try w.writeAll(" (value: 0)");
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
|
||||
try w.writeAll("\n");
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
|
||||
if (ty.specifier == .attributed) {
|
||||
if (color) util.setColor(ATTRIBUTE, w);
|
||||
try config.setColor(w, ATTRIBUTE);
|
||||
for (ty.data.attributed.attributes) |attr| {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.print("attr: {s}", .{@tagName(attr.tag)});
|
||||
try dumpAttribute(attr, tree.strings, w);
|
||||
try tree.dumpAttribute(attr, w);
|
||||
}
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
|
||||
switch (tag) {
|
||||
.invalid => unreachable,
|
||||
.file_scope_asm => {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, config, w);
|
||||
},
|
||||
.gnu_asm_simple => {
|
||||
try w.writeByteNTimes(' ', level);
|
||||
try tree.dumpNode(data.un, level, mapper, color, w);
|
||||
try tree.dumpNode(data.un, level, mapper, config, w);
|
||||
},
|
||||
.static_assert => {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("condition:\n");
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, config, w);
|
||||
if (data.bin.rhs != .none) {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("diagnostic:\n");
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.fn_proto,
|
||||
@ -807,9 +821,9 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
=> {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl.name)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
},
|
||||
.fn_def,
|
||||
.static_fn_def,
|
||||
@ -818,12 +832,12 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
=> {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl.name)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("body:\n");
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, config, w);
|
||||
},
|
||||
.typedef,
|
||||
.@"var",
|
||||
@ -836,39 +850,39 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
=> {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl.name)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
if (data.decl.node != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("init:\n");
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.enum_field_decl => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl.name)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
if (data.decl.node != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("value:\n");
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.record_field_decl => {
|
||||
if (data.decl.name != 0) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl.name)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
if (data.decl.node != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("bits:\n");
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.indirect_record_field_decl => {},
|
||||
@ -882,13 +896,13 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
const maybe_field_attributes = if (ty.getRecord()) |record| record.field_attributes else null;
|
||||
for (tree.data[data.range.start..data.range.end], 0..) |stmt, i| {
|
||||
if (i != 0) try w.writeByte('\n');
|
||||
try tree.dumpNode(stmt, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(stmt, level + delta, mapper, config, w);
|
||||
if (maybe_field_attributes) |field_attributes| {
|
||||
if (field_attributes[i].len == 0) continue;
|
||||
|
||||
if (color) util.setColor(ATTRIBUTE, w);
|
||||
try dumpFieldAttributes(field_attributes[i], level + delta + half, tree.strings, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, ATTRIBUTE);
|
||||
try tree.dumpFieldAttributes(field_attributes[i], level + delta + half, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -903,91 +917,95 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
const empty: [][]const Attribute = &attr_array;
|
||||
const field_attributes = if (ty.getRecord()) |record| (record.field_attributes orelse empty.ptr) else empty.ptr;
|
||||
if (data.bin.lhs != .none) {
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, config, w);
|
||||
if (field_attributes[0].len > 0) {
|
||||
if (color) util.setColor(ATTRIBUTE, w);
|
||||
try dumpFieldAttributes(field_attributes[0], level + delta + half, tree.strings, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, ATTRIBUTE);
|
||||
try tree.dumpFieldAttributes(field_attributes[0], level + delta + half, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
}
|
||||
if (data.bin.rhs != .none) {
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, config, w);
|
||||
if (field_attributes[1].len > 0) {
|
||||
if (color) util.setColor(ATTRIBUTE, w);
|
||||
try dumpFieldAttributes(field_attributes[1], level + delta + half, tree.strings, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, ATTRIBUTE);
|
||||
try tree.dumpFieldAttributes(field_attributes[1], level + delta + half, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
}
|
||||
},
|
||||
.union_init_expr => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("field index: ");
|
||||
if (color) util.setColor(LITERAL, w);
|
||||
try config.setColor(w, LITERAL);
|
||||
try w.print("{d}\n", .{data.union_init.field_index});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
if (data.union_init.node != .none) {
|
||||
try tree.dumpNode(data.union_init.node, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.union_init.node, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.compound_literal_expr => {
|
||||
try tree.dumpNode(data.un, level + half, mapper, color, w);
|
||||
.compound_literal_expr,
|
||||
.static_compound_literal_expr,
|
||||
.thread_local_compound_literal_expr,
|
||||
.static_thread_local_compound_literal_expr,
|
||||
=> {
|
||||
try tree.dumpNode(data.un, level + half, mapper, config, w);
|
||||
},
|
||||
.labeled_stmt => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("label: ");
|
||||
if (color) util.setColor(LITERAL, w);
|
||||
try config.setColor(w, LITERAL);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl.name)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
if (data.decl.node != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("stmt:\n");
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.case_stmt => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("value:\n");
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, config, w);
|
||||
if (data.bin.rhs != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("stmt:\n");
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.case_range_stmt => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("range start:\n");
|
||||
try tree.dumpNode(tree.data[data.if3.body], level + delta, mapper, color, w);
|
||||
try tree.dumpNode(tree.data[data.if3.body], level + delta, mapper, config, w);
|
||||
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("range end:\n");
|
||||
try tree.dumpNode(tree.data[data.if3.body + 1], level + delta, mapper, color, w);
|
||||
try tree.dumpNode(tree.data[data.if3.body + 1], level + delta, mapper, config, w);
|
||||
|
||||
if (data.if3.cond != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("stmt:\n");
|
||||
try tree.dumpNode(data.if3.cond, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.if3.cond, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.default_stmt => {
|
||||
if (data.un != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("stmt:\n");
|
||||
try tree.dumpNode(data.un, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.un, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.binary_cond_expr, .cond_expr, .if_then_else_stmt, .builtin_choose_expr => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("cond:\n");
|
||||
try tree.dumpNode(data.if3.cond, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.if3.cond, level + delta, mapper, config, w);
|
||||
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("then:\n");
|
||||
try tree.dumpNode(tree.data[data.if3.body], level + delta, mapper, color, w);
|
||||
try tree.dumpNode(tree.data[data.if3.body], level + delta, mapper, config, w);
|
||||
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("else:\n");
|
||||
try tree.dumpNode(tree.data[data.if3.body + 1], level + delta, mapper, color, w);
|
||||
try tree.dumpNode(tree.data[data.if3.body + 1], level + delta, mapper, config, w);
|
||||
},
|
||||
.builtin_types_compatible_p => {
|
||||
std.debug.assert(tree.nodes.items(.tag)[@intFromEnum(data.bin.lhs)] == .invalid);
|
||||
@ -997,40 +1015,40 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
try w.writeAll("lhs: ");
|
||||
|
||||
const lhs_ty = tree.nodes.items(.ty)[@intFromEnum(data.bin.lhs)];
|
||||
if (color) util.setColor(TYPE, w);
|
||||
try config.setColor(w, TYPE);
|
||||
try lhs_ty.dump(mapper, tree.comp.langopts, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeByte('\n');
|
||||
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("rhs: ");
|
||||
|
||||
const rhs_ty = tree.nodes.items(.ty)[@intFromEnum(data.bin.rhs)];
|
||||
if (color) util.setColor(TYPE, w);
|
||||
try config.setColor(w, TYPE);
|
||||
try rhs_ty.dump(mapper, tree.comp.langopts, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
.if_then_stmt => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("cond:\n");
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, config, w);
|
||||
|
||||
if (data.bin.rhs != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("then:\n");
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.switch_stmt, .while_stmt, .do_while_stmt => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("cond:\n");
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, config, w);
|
||||
|
||||
if (data.bin.rhs != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("body:\n");
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.for_decl_stmt => {
|
||||
@ -1039,30 +1057,30 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("decl:\n");
|
||||
for (for_decl.decls) |decl| {
|
||||
try tree.dumpNode(decl, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(decl, level + delta, mapper, config, w);
|
||||
try w.writeByte('\n');
|
||||
}
|
||||
if (for_decl.cond != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("cond:\n");
|
||||
try tree.dumpNode(for_decl.cond, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(for_decl.cond, level + delta, mapper, config, w);
|
||||
}
|
||||
if (for_decl.incr != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("incr:\n");
|
||||
try tree.dumpNode(for_decl.incr, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(for_decl.incr, level + delta, mapper, config, w);
|
||||
}
|
||||
if (for_decl.body != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("body:\n");
|
||||
try tree.dumpNode(for_decl.body, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(for_decl.body, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.forever_stmt => {
|
||||
if (data.un != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("body:\n");
|
||||
try tree.dumpNode(data.un, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.un, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.for_stmt => {
|
||||
@ -1071,91 +1089,91 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
if (for_stmt.init != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("init:\n");
|
||||
try tree.dumpNode(for_stmt.init, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(for_stmt.init, level + delta, mapper, config, w);
|
||||
}
|
||||
if (for_stmt.cond != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("cond:\n");
|
||||
try tree.dumpNode(for_stmt.cond, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(for_stmt.cond, level + delta, mapper, config, w);
|
||||
}
|
||||
if (for_stmt.incr != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("incr:\n");
|
||||
try tree.dumpNode(for_stmt.incr, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(for_stmt.incr, level + delta, mapper, config, w);
|
||||
}
|
||||
if (for_stmt.body != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("body:\n");
|
||||
try tree.dumpNode(for_stmt.body, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(for_stmt.body, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.goto_stmt, .addr_of_label => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("label: ");
|
||||
if (color) util.setColor(LITERAL, w);
|
||||
try config.setColor(w, LITERAL);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl_ref)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
},
|
||||
.continue_stmt, .break_stmt, .implicit_return, .null_stmt => {},
|
||||
.return_stmt => {
|
||||
if (data.un != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("expr:\n");
|
||||
try tree.dumpNode(data.un, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.un, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.call_expr => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("lhs:\n");
|
||||
try tree.dumpNode(tree.data[data.range.start], level + delta, mapper, color, w);
|
||||
try tree.dumpNode(tree.data[data.range.start], level + delta, mapper, config, w);
|
||||
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("args:\n");
|
||||
for (tree.data[data.range.start + 1 .. data.range.end]) |arg| try tree.dumpNode(arg, level + delta, mapper, color, w);
|
||||
for (tree.data[data.range.start + 1 .. data.range.end]) |arg| try tree.dumpNode(arg, level + delta, mapper, config, w);
|
||||
},
|
||||
.call_expr_one => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("lhs:\n");
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, config, w);
|
||||
if (data.bin.rhs != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("arg:\n");
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.builtin_call_expr => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(@intFromEnum(tree.data[data.range.start]))});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("args:\n");
|
||||
for (tree.data[data.range.start + 1 .. data.range.end]) |arg| try tree.dumpNode(arg, level + delta, mapper, color, w);
|
||||
for (tree.data[data.range.start + 1 .. data.range.end]) |arg| try tree.dumpNode(arg, level + delta, mapper, config, w);
|
||||
},
|
||||
.builtin_call_expr_one => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl.name)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
if (data.decl.node != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("arg:\n");
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.special_builtin_call_one => {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl.name)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
if (data.decl.node != .none) {
|
||||
try w.writeByteNTimes(' ', level + half);
|
||||
try w.writeAll("arg:\n");
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.decl.node, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.comma_expr,
|
||||
@ -1191,12 +1209,12 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
=> {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("lhs:\n");
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, config, w);
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("rhs:\n");
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, config, w);
|
||||
},
|
||||
.explicit_cast, .implicit_cast => try tree.dumpNode(data.cast.operand, level + delta, mapper, color, w),
|
||||
.explicit_cast, .implicit_cast => try tree.dumpNode(data.cast.operand, level + delta, mapper, config, w),
|
||||
.addr_of_expr,
|
||||
.computed_goto_stmt,
|
||||
.deref_expr,
|
||||
@ -1214,35 +1232,33 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
=> {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("operand:\n");
|
||||
try tree.dumpNode(data.un, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.un, level + delta, mapper, config, w);
|
||||
},
|
||||
.decl_ref_expr => {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl_ref)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
},
|
||||
.enumeration_ref => {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{tree.tokSlice(data.decl_ref)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
},
|
||||
.bool_literal,
|
||||
.nullptr_literal,
|
||||
.int_literal,
|
||||
.char_literal,
|
||||
.float16_literal,
|
||||
.float_literal,
|
||||
.double_literal,
|
||||
.string_literal_expr,
|
||||
=> {},
|
||||
.member_access_expr, .member_access_ptr_expr => {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("lhs:\n");
|
||||
try tree.dumpNode(data.member.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.member.lhs, level + delta, mapper, config, w);
|
||||
|
||||
var lhs_ty = tree.nodes.items(.ty)[@intFromEnum(data.member.lhs)];
|
||||
if (lhs_ty.isPtr()) lhs_ty = lhs_ty.elemType();
|
||||
@ -1250,60 +1266,60 @@ fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.Type
|
||||
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("name: ");
|
||||
if (color) util.setColor(NAME, w);
|
||||
try config.setColor(w, NAME);
|
||||
try w.print("{s}\n", .{mapper.lookup(lhs_ty.data.record.fields[data.member.index].name)});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
},
|
||||
.array_access_expr => {
|
||||
if (data.bin.lhs != .none) {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("lhs:\n");
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, config, w);
|
||||
}
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("index:\n");
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, config, w);
|
||||
},
|
||||
.sizeof_expr, .alignof_expr => {
|
||||
if (data.un != .none) {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("expr:\n");
|
||||
try tree.dumpNode(data.un, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.un, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.generic_expr_one => {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("controlling:\n");
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.lhs, level + delta, mapper, config, w);
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
if (data.bin.rhs != .none) {
|
||||
try w.writeAll("chosen:\n");
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.bin.rhs, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.generic_expr => {
|
||||
const nodes = tree.data[data.range.start..data.range.end];
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("controlling:\n");
|
||||
try tree.dumpNode(nodes[0], level + delta, mapper, color, w);
|
||||
try tree.dumpNode(nodes[0], level + delta, mapper, config, w);
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("chosen:\n");
|
||||
try tree.dumpNode(nodes[1], level + delta, mapper, color, w);
|
||||
try tree.dumpNode(nodes[1], level + delta, mapper, config, w);
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("rest:\n");
|
||||
for (nodes[2..]) |expr| {
|
||||
try tree.dumpNode(expr, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(expr, level + delta, mapper, config, w);
|
||||
}
|
||||
},
|
||||
.generic_association_expr, .generic_default_expr, .stmt_expr, .imaginary_literal => {
|
||||
try tree.dumpNode(data.un, level + delta, mapper, color, w);
|
||||
try tree.dumpNode(data.un, level + delta, mapper, config, w);
|
||||
},
|
||||
.array_filler_expr => {
|
||||
try w.writeByteNTimes(' ', level + 1);
|
||||
try w.writeAll("count: ");
|
||||
if (color) util.setColor(LITERAL, w);
|
||||
try config.setColor(w, LITERAL);
|
||||
try w.print("{d}\n", .{data.int});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
},
|
||||
.struct_forward_decl,
|
||||
.union_forward_decl,
|
||||
102
deps/aro/Type.zig → deps/aro/aro/Type.zig
vendored
102
deps/aro/Type.zig → deps/aro/aro/Type.zig
vendored
@ -10,8 +10,6 @@ const StringId = StringInterner.StringId;
|
||||
const target_util = @import("target.zig");
|
||||
const LangOpts = @import("LangOpts.zig");
|
||||
|
||||
const Type = @This();
|
||||
|
||||
pub const Qualifiers = packed struct {
|
||||
@"const": bool = false,
|
||||
atomic: bool = false,
|
||||
@ -104,22 +102,20 @@ pub const Func = struct {
|
||||
name_tok: TokenIndex,
|
||||
};
|
||||
|
||||
fn eql(a: *const Func, b: *const Func, a_var_args: bool, b_var_args: bool, comp: *const Compilation) bool {
|
||||
fn eql(a: *const Func, b: *const Func, a_spec: Specifier, b_spec: Specifier, comp: *const Compilation) bool {
|
||||
// return type cannot have qualifiers
|
||||
if (!a.return_type.eql(b.return_type, comp, false)) return false;
|
||||
|
||||
if (a.params.len != b.params.len) {
|
||||
const a_no_proto = a_var_args and a.params.len == 0 and !comp.langopts.standard.atLeast(.c2x);
|
||||
const b_no_proto = b_var_args and b.params.len == 0 and !comp.langopts.standard.atLeast(.c2x);
|
||||
if (a_no_proto or b_no_proto) {
|
||||
const maybe_has_params = if (a_no_proto) b else a;
|
||||
if (a_spec == .old_style_func or b_spec == .old_style_func) {
|
||||
const maybe_has_params = if (a_spec == .old_style_func) b else a;
|
||||
for (maybe_has_params.params) |param| {
|
||||
if (param.ty.undergoesDefaultArgPromotion(comp)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (a_var_args != b_var_args) return false;
|
||||
if ((a_spec == .func) != (b_spec == .func)) return false;
|
||||
// TODO validate this
|
||||
for (a.params, b.params) |param, b_qual| {
|
||||
var a_unqual = param.ty;
|
||||
@ -149,10 +145,10 @@ pub const Attributed = struct {
|
||||
base: Type,
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator, base: Type, existing_attributes: []const Attribute, attributes: []const Attribute) !*Attributed {
|
||||
var attributed_type = try allocator.create(Attributed);
|
||||
const attributed_type = try allocator.create(Attributed);
|
||||
errdefer allocator.destroy(attributed_type);
|
||||
|
||||
var all_attrs = try allocator.alloc(Attribute, existing_attributes.len + attributes.len);
|
||||
const all_attrs = try allocator.alloc(Attribute, existing_attributes.len + attributes.len);
|
||||
std.mem.copy(Attribute, all_attrs, existing_attributes);
|
||||
std.mem.copy(Attribute, all_attrs[existing_attributes.len..], attributes);
|
||||
|
||||
@ -312,6 +308,8 @@ pub const Specifier = enum {
|
||||
/// GNU auto type
|
||||
/// This is a placeholder specifier - it must be replaced by the actual type specifier (determined by the initializer)
|
||||
auto_type,
|
||||
/// C23 auto, behaves like auto_type
|
||||
c23_auto,
|
||||
|
||||
void,
|
||||
bool,
|
||||
@ -411,6 +409,8 @@ pub const Specifier = enum {
|
||||
nullptr_t,
|
||||
};
|
||||
|
||||
const Type = @This();
|
||||
|
||||
/// All fields of Type except data may be mutated
|
||||
data: union {
|
||||
sub_type: *Type,
|
||||
@ -422,7 +422,7 @@ data: union {
|
||||
attributed: *Attributed,
|
||||
none: void,
|
||||
int: struct {
|
||||
bits: u8,
|
||||
bits: u16,
|
||||
signedness: std.builtin.Signedness,
|
||||
},
|
||||
} = .{ .none = {} },
|
||||
@ -623,17 +623,21 @@ pub fn isConst(ty: Type) bool {
|
||||
}
|
||||
|
||||
pub fn isUnsignedInt(ty: Type, comp: *const Compilation) bool {
|
||||
return ty.signedness(comp) == .unsigned;
|
||||
}
|
||||
|
||||
pub fn signedness(ty: Type, comp: *const Compilation) std.builtin.Signedness {
|
||||
return switch (ty.specifier) {
|
||||
// zig fmt: off
|
||||
.char, .complex_char => return comp.getCharSignedness() == .unsigned,
|
||||
.char, .complex_char => return comp.getCharSignedness(),
|
||||
.uchar, .ushort, .uint, .ulong, .ulong_long, .bool, .complex_uchar, .complex_ushort,
|
||||
.complex_uint, .complex_ulong, .complex_ulong_long, .complex_uint128 => true,
|
||||
.complex_uint, .complex_ulong, .complex_ulong_long, .complex_uint128 => .unsigned,
|
||||
// zig fmt: on
|
||||
.bit_int, .complex_bit_int => return ty.data.int.signedness == .unsigned,
|
||||
.typeof_type => ty.data.sub_type.isUnsignedInt(comp),
|
||||
.typeof_expr => ty.data.expr.ty.isUnsignedInt(comp),
|
||||
.attributed => ty.data.attributed.base.isUnsignedInt(comp),
|
||||
else => false,
|
||||
.bit_int, .complex_bit_int => ty.data.int.signedness,
|
||||
.typeof_type => ty.data.sub_type.signedness(comp),
|
||||
.typeof_expr => ty.data.expr.ty.signedness(comp),
|
||||
.attributed => ty.data.attributed.base.signedness(comp),
|
||||
else => .signed,
|
||||
};
|
||||
}
|
||||
|
||||
@ -760,7 +764,7 @@ pub fn getRecord(ty: Type) ?*const Type.Record {
|
||||
};
|
||||
}
|
||||
|
||||
fn compareIntegerRanks(a: Type, b: Type, comp: *const Compilation) std.math.Order {
|
||||
pub fn compareIntegerRanks(a: Type, b: Type, comp: *const Compilation) std.math.Order {
|
||||
std.debug.assert(a.isInt() and b.isInt());
|
||||
if (a.eql(b, comp, false)) return .eq;
|
||||
|
||||
@ -898,7 +902,7 @@ pub fn bitfieldPromotion(ty: Type, comp: *Compilation, width: u32) ?Type {
|
||||
|
||||
pub fn hasIncompleteSize(ty: Type) bool {
|
||||
return switch (ty.specifier) {
|
||||
.void, .incomplete_array, .invalid => true,
|
||||
.void, .incomplete_array => true,
|
||||
.@"enum" => ty.data.@"enum".isIncomplete() and !ty.data.@"enum".fixed,
|
||||
.@"struct", .@"union" => ty.data.record.isIncomplete(),
|
||||
.array, .static_array => ty.data.array.elem.hasIncompleteSize(),
|
||||
@ -958,6 +962,7 @@ pub fn hasField(ty: Type, name: StringId) bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO handle bitints
|
||||
pub fn minInt(ty: Type, comp: *const Compilation) i64 {
|
||||
std.debug.assert(ty.isInt());
|
||||
if (ty.isUnsignedInt(comp)) return 0;
|
||||
@ -970,6 +975,7 @@ pub fn minInt(ty: Type, comp: *const Compilation) i64 {
|
||||
};
|
||||
}
|
||||
|
||||
// TODO handle bitints
|
||||
pub fn maxInt(ty: Type, comp: *const Compilation) u64 {
|
||||
std.debug.assert(ty.isInt());
|
||||
return switch (ty.sizeof(comp).?) {
|
||||
@ -1001,7 +1007,7 @@ pub fn sizeCompare(a: Type, b: Type, comp: *Compilation) TypeSizeOrder {
|
||||
/// Size of type as reported by sizeof
|
||||
pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 {
|
||||
return switch (ty.specifier) {
|
||||
.auto_type => unreachable,
|
||||
.auto_type, .c23_auto => unreachable,
|
||||
.variable_len_array, .unspecified_variable_len_array => return null,
|
||||
.incomplete_array => return if (comp.langopts.emulate == .msvc) @as(?u64, 0) else null,
|
||||
.func, .var_args_func, .old_style_func, .void, .bool => 1,
|
||||
@ -1104,7 +1110,7 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 {
|
||||
|
||||
return switch (ty.specifier) {
|
||||
.invalid => unreachable,
|
||||
.auto_type => unreachable,
|
||||
.auto_type, .c23_auto => unreachable,
|
||||
|
||||
.variable_len_array,
|
||||
.incomplete_array,
|
||||
@ -1271,7 +1277,7 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi
|
||||
.func,
|
||||
.var_args_func,
|
||||
.old_style_func,
|
||||
=> if (!a.data.func.eql(b.data.func, a.specifier == .var_args_func, b.specifier == .var_args_func, comp)) return false,
|
||||
=> if (!a.data.func.eql(b.data.func, a.specifier, b.specifier, comp)) return false,
|
||||
|
||||
.array,
|
||||
.static_array,
|
||||
@ -1418,7 +1424,7 @@ pub fn combine(inner: *Type, outer: Type) Parser.Error!void {
|
||||
.decayed_typeof_type,
|
||||
.decayed_typeof_expr,
|
||||
=> unreachable, // type should not be able to decay before being combined
|
||||
.void => inner.* = outer,
|
||||
.void, .invalid => inner.* = outer,
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@ -1496,6 +1502,8 @@ pub const Builder = struct {
|
||||
void,
|
||||
/// GNU __auto_type extension
|
||||
auto_type,
|
||||
/// C23 auto
|
||||
c23_auto,
|
||||
nullptr_t,
|
||||
bool,
|
||||
char,
|
||||
@ -1557,12 +1565,12 @@ pub const Builder = struct {
|
||||
complex_int128,
|
||||
complex_sint128,
|
||||
complex_uint128,
|
||||
bit_int: i16,
|
||||
sbit_int: i16,
|
||||
ubit_int: i16,
|
||||
complex_bit_int: i16,
|
||||
complex_sbit_int: i16,
|
||||
complex_ubit_int: i16,
|
||||
bit_int: u64,
|
||||
sbit_int: u64,
|
||||
ubit_int: u64,
|
||||
complex_bit_int: u64,
|
||||
complex_sbit_int: u64,
|
||||
complex_ubit_int: u64,
|
||||
|
||||
fp16,
|
||||
float16,
|
||||
@ -1608,8 +1616,9 @@ pub const Builder = struct {
|
||||
.none => unreachable,
|
||||
.void => "void",
|
||||
.auto_type => "__auto_type",
|
||||
.c23_auto => "auto",
|
||||
.nullptr_t => "nullptr_t",
|
||||
.bool => if (langopts.standard.atLeast(.c2x)) "bool" else "_Bool",
|
||||
.bool => if (langopts.standard.atLeast(.c23)) "bool" else "_Bool",
|
||||
.char => "char",
|
||||
.schar => "signed char",
|
||||
.uchar => "unsigned char",
|
||||
@ -1706,7 +1715,7 @@ pub const Builder = struct {
|
||||
// TODO this really should be easier
|
||||
switch (ty.specifier) {
|
||||
.array, .static_array, .incomplete_array => {
|
||||
var old = ty.data.array;
|
||||
const old = ty.data.array;
|
||||
ty.data.array = try p.arena.create(Array);
|
||||
ty.data.array.* = .{
|
||||
.len = old.len,
|
||||
@ -1714,7 +1723,7 @@ pub const Builder = struct {
|
||||
};
|
||||
},
|
||||
.variable_len_array, .unspecified_variable_len_array => {
|
||||
var old = ty.data.expr;
|
||||
const old = ty.data.expr;
|
||||
ty.data.expr = try p.arena.create(Expr);
|
||||
ty.data.expr.* = .{
|
||||
.node = old.node,
|
||||
@ -1738,8 +1747,8 @@ pub const Builder = struct {
|
||||
ty = typeof;
|
||||
} else {
|
||||
ty.specifier = .int;
|
||||
if (p.comp.langopts.standard.atLeast(.c2x)) {
|
||||
try p.err(.missing_type_specifier_c2x);
|
||||
if (p.comp.langopts.standard.atLeast(.c23)) {
|
||||
try p.err(.missing_type_specifier_c23);
|
||||
} else {
|
||||
try p.err(.missing_type_specifier);
|
||||
}
|
||||
@ -1747,6 +1756,7 @@ pub const Builder = struct {
|
||||
},
|
||||
.void => ty.specifier = .void,
|
||||
.auto_type => ty.specifier = .auto_type,
|
||||
.c23_auto => ty.specifier = .c23_auto,
|
||||
.nullptr_t => unreachable, // nullptr_t can only be accessed via typeof(nullptr)
|
||||
.bool => ty.specifier = .bool,
|
||||
.char => ty.specifier = .char,
|
||||
@ -1785,17 +1795,17 @@ pub const Builder = struct {
|
||||
if (unsigned) {
|
||||
if (bits < 1) {
|
||||
try p.errStr(.unsigned_bit_int_too_small, b.bit_int_tok.?, b.specifier.str(p.comp.langopts).?);
|
||||
return error.ParsingFailed;
|
||||
return Type.invalid;
|
||||
}
|
||||
} else {
|
||||
if (bits < 2) {
|
||||
try p.errStr(.signed_bit_int_too_small, b.bit_int_tok.?, b.specifier.str(p.comp.langopts).?);
|
||||
return error.ParsingFailed;
|
||||
return Type.invalid;
|
||||
}
|
||||
}
|
||||
if (bits > Compilation.bit_int_max_bits) {
|
||||
try p.errStr(.bit_int_too_big, b.bit_int_tok.?, b.specifier.str(p.comp.langopts).?);
|
||||
return error.ParsingFailed;
|
||||
return Type.invalid;
|
||||
}
|
||||
ty.specifier = if (b.complex_tok != null) .complex_bit_int else .bit_int;
|
||||
ty.data = .{ .int = .{
|
||||
@ -2175,6 +2185,10 @@ pub const Builder = struct {
|
||||
.none => .auto_type,
|
||||
else => return b.cannotCombine(p, source_tok),
|
||||
},
|
||||
.c23_auto => b.specifier = switch (b.specifier) {
|
||||
.none => .c23_auto,
|
||||
else => return b.cannotCombine(p, source_tok),
|
||||
},
|
||||
.fp16 => b.specifier = switch (b.specifier) {
|
||||
.none => .fp16,
|
||||
else => return b.cannotCombine(p, source_tok),
|
||||
@ -2292,6 +2306,7 @@ pub const Builder = struct {
|
||||
return switch (ty.specifier) {
|
||||
.void => .void,
|
||||
.auto_type => .auto_type,
|
||||
.c23_auto => .c23_auto,
|
||||
.nullptr_t => .nullptr_t,
|
||||
.bool => .bool,
|
||||
.char => .char,
|
||||
@ -2606,6 +2621,9 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w:
|
||||
try ty.data.sub_type.dump(mapper, langopts, w);
|
||||
},
|
||||
.func, .var_args_func, .old_style_func => {
|
||||
if (ty.specifier == .old_style_func)
|
||||
try w.writeAll("kr (")
|
||||
else
|
||||
try w.writeAll("fn (");
|
||||
for (ty.data.func.params, 0..) |param, i| {
|
||||
if (i != 0) try w.writeAll(", ");
|
||||
@ -2620,7 +2638,7 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w:
|
||||
try ty.data.func.return_type.dump(mapper, langopts, w);
|
||||
},
|
||||
.array, .static_array, .decayed_array, .decayed_static_array => {
|
||||
if (ty.specifier == .decayed_array or ty.specifier == .decayed_static_array) try w.writeByte('d');
|
||||
if (ty.specifier == .decayed_array or ty.specifier == .decayed_static_array) try w.writeAll("*d");
|
||||
try w.writeByte('[');
|
||||
if (ty.specifier == .static_array or ty.specifier == .decayed_static_array) try w.writeAll("static ");
|
||||
try w.print("{d}]", .{ty.data.array.len});
|
||||
@ -2632,7 +2650,7 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w:
|
||||
try w.writeAll(")");
|
||||
},
|
||||
.incomplete_array, .decayed_incomplete_array => {
|
||||
if (ty.specifier == .decayed_incomplete_array) try w.writeByte('d');
|
||||
if (ty.specifier == .decayed_incomplete_array) try w.writeAll("*d");
|
||||
try w.writeAll("[]");
|
||||
try ty.data.array.elem.dump(mapper, langopts, w);
|
||||
},
|
||||
@ -2655,12 +2673,12 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w:
|
||||
if (dump_detailed_containers) try dumpRecord(ty.data.record, mapper, langopts, w);
|
||||
},
|
||||
.unspecified_variable_len_array, .decayed_unspecified_variable_len_array => {
|
||||
if (ty.specifier == .decayed_unspecified_variable_len_array) try w.writeByte('d');
|
||||
if (ty.specifier == .decayed_unspecified_variable_len_array) try w.writeAll("*d");
|
||||
try w.writeAll("[*]");
|
||||
try ty.data.sub_type.dump(mapper, langopts, w);
|
||||
},
|
||||
.variable_len_array, .decayed_variable_len_array => {
|
||||
if (ty.specifier == .decayed_variable_len_array) try w.writeByte('d');
|
||||
if (ty.specifier == .decayed_variable_len_array) try w.writeAll("*d");
|
||||
try w.writeAll("[<expr>]");
|
||||
try ty.data.expr.ty.dump(mapper, langopts, w);
|
||||
},
|
||||
726
deps/aro/aro/Value.zig
vendored
Normal file
726
deps/aro/aro/Value.zig
vendored
Normal file
@ -0,0 +1,726 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const BigIntConst = std.math.big.int.Const;
|
||||
const BigIntMutable = std.math.big.int.Mutable;
|
||||
const backend = @import("backend");
|
||||
const Interner = backend.Interner;
|
||||
const BigIntSpace = Interner.Tag.Int.BigIntSpace;
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Type = @import("Type.zig");
|
||||
const target_util = @import("target.zig");
|
||||
|
||||
const Value = @This();
|
||||
|
||||
opt_ref: Interner.OptRef = .none,
|
||||
|
||||
pub const zero = Value{ .opt_ref = .zero };
|
||||
pub const one = Value{ .opt_ref = .one };
|
||||
pub const @"null" = Value{ .opt_ref = .null };
|
||||
|
||||
pub fn intern(comp: *Compilation, k: Interner.Key) !Value {
|
||||
const r = try comp.interner.put(comp.gpa, k);
|
||||
return .{ .opt_ref = @enumFromInt(@intFromEnum(r)) };
|
||||
}
|
||||
|
||||
pub fn int(i: anytype, comp: *Compilation) !Value {
|
||||
const info = @typeInfo(@TypeOf(i));
|
||||
if (info == .ComptimeInt or info.Int.signedness == .unsigned) {
|
||||
return intern(comp, .{ .int = .{ .u64 = i } });
|
||||
} else {
|
||||
return intern(comp, .{ .int = .{ .i64 = i } });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ref(v: Value) Interner.Ref {
|
||||
std.debug.assert(v.opt_ref != .none);
|
||||
return @enumFromInt(@intFromEnum(v.opt_ref));
|
||||
}
|
||||
|
||||
pub fn is(v: Value, tag: std.meta.Tag(Interner.Key), comp: *const Compilation) bool {
|
||||
if (v.opt_ref == .none) return false;
|
||||
return comp.interner.get(v.ref()) == tag;
|
||||
}
|
||||
|
||||
/// Number of bits needed to hold `v`.
|
||||
/// Asserts that `v` is not negative
|
||||
pub fn minUnsignedBits(v: Value, comp: *const Compilation) usize {
|
||||
var space: BigIntSpace = undefined;
|
||||
const big = v.toBigInt(&space, comp);
|
||||
assert(big.positive);
|
||||
return big.bitCountAbs();
|
||||
}
|
||||
|
||||
test "minUnsignedBits" {
|
||||
const Test = struct {
|
||||
fn checkIntBits(comp: *Compilation, v: u64, expected: usize) !void {
|
||||
const val = try intern(comp, .{ .int = .{ .u64 = v } });
|
||||
try std.testing.expectEqual(expected, val.minUnsignedBits(comp));
|
||||
}
|
||||
};
|
||||
|
||||
var comp = Compilation.init(std.testing.allocator);
|
||||
defer comp.deinit();
|
||||
comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget();
|
||||
|
||||
try Test.checkIntBits(&comp, 0, 0);
|
||||
try Test.checkIntBits(&comp, 1, 1);
|
||||
try Test.checkIntBits(&comp, 2, 2);
|
||||
try Test.checkIntBits(&comp, std.math.maxInt(i8), 7);
|
||||
try Test.checkIntBits(&comp, std.math.maxInt(u8), 8);
|
||||
try Test.checkIntBits(&comp, std.math.maxInt(i16), 15);
|
||||
try Test.checkIntBits(&comp, std.math.maxInt(u16), 16);
|
||||
try Test.checkIntBits(&comp, std.math.maxInt(i32), 31);
|
||||
try Test.checkIntBits(&comp, std.math.maxInt(u32), 32);
|
||||
try Test.checkIntBits(&comp, std.math.maxInt(i64), 63);
|
||||
try Test.checkIntBits(&comp, std.math.maxInt(u64), 64);
|
||||
}
|
||||
|
||||
/// Minimum number of bits needed to represent `v` in 2's complement notation
|
||||
/// Asserts that `v` is negative.
|
||||
pub fn minSignedBits(v: Value, comp: *const Compilation) usize {
|
||||
var space: BigIntSpace = undefined;
|
||||
const big = v.toBigInt(&space, comp);
|
||||
assert(!big.positive);
|
||||
return big.bitCountTwosComp();
|
||||
}
|
||||
|
||||
test "minSignedBits" {
|
||||
const Test = struct {
|
||||
fn checkIntBits(comp: *Compilation, v: i64, expected: usize) !void {
|
||||
const val = try intern(comp, .{ .int = .{ .i64 = v } });
|
||||
try std.testing.expectEqual(expected, val.minSignedBits(comp));
|
||||
}
|
||||
};
|
||||
|
||||
var comp = Compilation.init(std.testing.allocator);
|
||||
defer comp.deinit();
|
||||
comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget();
|
||||
|
||||
try Test.checkIntBits(&comp, -1, 1);
|
||||
try Test.checkIntBits(&comp, -2, 2);
|
||||
try Test.checkIntBits(&comp, -10, 5);
|
||||
try Test.checkIntBits(&comp, -101, 8);
|
||||
try Test.checkIntBits(&comp, std.math.minInt(i8), 8);
|
||||
try Test.checkIntBits(&comp, std.math.minInt(i16), 16);
|
||||
try Test.checkIntBits(&comp, std.math.minInt(i32), 32);
|
||||
try Test.checkIntBits(&comp, std.math.minInt(i64), 64);
|
||||
}
|
||||
|
||||
pub const FloatToIntChangeKind = enum {
|
||||
/// value did not change
|
||||
none,
|
||||
/// floating point number too small or large for destination integer type
|
||||
out_of_range,
|
||||
/// tried to convert a NaN or Infinity
|
||||
overflow,
|
||||
/// fractional value was converted to zero
|
||||
nonzero_to_zero,
|
||||
/// fractional part truncated
|
||||
value_changed,
|
||||
};
|
||||
|
||||
/// Converts the stored value from a float to an integer.
|
||||
/// `.none` value remains unchanged.
|
||||
pub fn floatToInt(v: *Value, dest_ty: Type, comp: *Compilation) !FloatToIntChangeKind {
|
||||
if (v.opt_ref == .none) return .none;
|
||||
|
||||
const float_val = v.toFloat(f128, comp);
|
||||
const was_zero = float_val == 0;
|
||||
|
||||
if (dest_ty.is(.bool)) {
|
||||
const was_one = float_val == 1.0;
|
||||
v.* = fromBool(!was_zero);
|
||||
if (was_zero or was_one) return .none;
|
||||
return .value_changed;
|
||||
} else if (dest_ty.isUnsignedInt(comp) and v.compare(.lt, zero, comp)) {
|
||||
v.* = zero;
|
||||
return .out_of_range;
|
||||
}
|
||||
|
||||
const had_fraction = @rem(float_val, 1) != 0;
|
||||
const is_negative = std.math.signbit(float_val);
|
||||
const floored = @floor(@abs(float_val));
|
||||
|
||||
var rational = try std.math.big.Rational.init(comp.gpa);
|
||||
defer rational.deinit();
|
||||
rational.setFloat(f128, floored) catch |err| switch (err) {
|
||||
error.NonFiniteFloat => {
|
||||
v.* = .{};
|
||||
return .overflow;
|
||||
},
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
};
|
||||
|
||||
// The float is reduced in rational.setFloat, so we assert that denominator is equal to one
|
||||
const big_one = std.math.big.int.Const{ .limbs = &.{1}, .positive = true };
|
||||
assert(rational.q.toConst().eqlAbs(big_one));
|
||||
|
||||
if (is_negative) {
|
||||
rational.negate();
|
||||
}
|
||||
|
||||
const signedness = dest_ty.signedness(comp);
|
||||
const bits: usize = @intCast(dest_ty.bitSizeof(comp).?);
|
||||
|
||||
// rational.p.truncate(rational.p.toConst(), signedness: Signedness, bit_count: usize)
|
||||
const fits = rational.p.fitsInTwosComp(signedness, bits);
|
||||
v.* = try intern(comp, .{ .int = .{ .big_int = rational.p.toConst() } });
|
||||
try rational.p.truncate(&rational.p, signedness, bits);
|
||||
|
||||
if (!was_zero and v.isZero(comp)) return .nonzero_to_zero;
|
||||
if (!fits) return .out_of_range;
|
||||
if (had_fraction) return .value_changed;
|
||||
return .none;
|
||||
}
|
||||
|
||||
/// Converts the stored value from an integer to a float.
|
||||
/// `.none` value remains unchanged.
|
||||
pub fn intToFloat(v: *Value, dest_ty: Type, comp: *Compilation) !void {
|
||||
if (v.opt_ref == .none) return;
|
||||
const bits = dest_ty.bitSizeof(comp).?;
|
||||
return switch (comp.interner.get(v.ref()).int) {
|
||||
inline .u64, .i64 => |data| {
|
||||
const f: Interner.Key.Float = switch (bits) {
|
||||
16 => .{ .f16 = @floatFromInt(data) },
|
||||
32 => .{ .f32 = @floatFromInt(data) },
|
||||
64 => .{ .f64 = @floatFromInt(data) },
|
||||
80 => .{ .f80 = @floatFromInt(data) },
|
||||
128 => .{ .f128 = @floatFromInt(data) },
|
||||
else => unreachable,
|
||||
};
|
||||
v.* = try intern(comp, .{ .float = f });
|
||||
},
|
||||
.big_int => |data| {
|
||||
const big_f = bigIntToFloat(data.limbs, data.positive);
|
||||
const f: Interner.Key.Float = switch (bits) {
|
||||
16 => .{ .f16 = @floatCast(big_f) },
|
||||
32 => .{ .f32 = @floatCast(big_f) },
|
||||
64 => .{ .f64 = @floatCast(big_f) },
|
||||
80 => .{ .f80 = @floatCast(big_f) },
|
||||
128 => .{ .f128 = @floatCast(big_f) },
|
||||
else => unreachable,
|
||||
};
|
||||
v.* = try intern(comp, .{ .float = f });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// Truncates or extends bits based on type.
|
||||
/// `.none` value remains unchanged.
|
||||
pub fn intCast(v: *Value, dest_ty: Type, comp: *Compilation) !void {
|
||||
if (v.opt_ref == .none) return;
|
||||
const bits: usize = @intCast(dest_ty.bitSizeof(comp).?);
|
||||
var space: BigIntSpace = undefined;
|
||||
const big = v.toBigInt(&space, comp);
|
||||
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcTwosCompLimbCount(bits),
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
result_bigint.truncate(big, dest_ty.signedness(comp), bits);
|
||||
|
||||
v.* = try intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
}
|
||||
|
||||
/// Converts the stored value from an integer to a float.
|
||||
/// `.none` value remains unchanged.
|
||||
pub fn floatCast(v: *Value, dest_ty: Type, comp: *Compilation) !void {
|
||||
if (v.opt_ref == .none) return;
|
||||
// TODO complex values
|
||||
const bits = dest_ty.makeReal().bitSizeof(comp).?;
|
||||
const f: Interner.Key.Float = switch (bits) {
|
||||
16 => .{ .f16 = v.toFloat(f16, comp) },
|
||||
32 => .{ .f32 = v.toFloat(f32, comp) },
|
||||
64 => .{ .f64 = v.toFloat(f64, comp) },
|
||||
80 => .{ .f80 = v.toFloat(f80, comp) },
|
||||
128 => .{ .f128 = v.toFloat(f128, comp) },
|
||||
else => unreachable,
|
||||
};
|
||||
v.* = try intern(comp, .{ .float = f });
|
||||
}
|
||||
|
||||
pub fn toFloat(v: Value, comptime T: type, comp: *const Compilation) T {
|
||||
return switch (comp.interner.get(v.ref())) {
|
||||
.int => |repr| switch (repr) {
|
||||
inline .u64, .i64 => |data| @floatFromInt(data),
|
||||
.big_int => |data| @floatCast(bigIntToFloat(data.limbs, data.positive)),
|
||||
},
|
||||
.float => |repr| switch (repr) {
|
||||
inline else => |data| @floatCast(data),
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
fn bigIntToFloat(limbs: []const std.math.big.Limb, positive: bool) f128 {
|
||||
if (limbs.len == 0) return 0;
|
||||
|
||||
const base = std.math.maxInt(std.math.big.Limb) + 1;
|
||||
var result: f128 = 0;
|
||||
var i: usize = limbs.len;
|
||||
while (i != 0) {
|
||||
i -= 1;
|
||||
const limb: f128 = @as(f128, @floatFromInt(limbs[i]));
|
||||
result = @mulAdd(f128, base, result, limb);
|
||||
}
|
||||
if (positive) {
|
||||
return result;
|
||||
} else {
|
||||
return -result;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toBigInt(val: Value, space: *BigIntSpace, comp: *const Compilation) BigIntConst {
|
||||
return switch (comp.interner.get(val.ref()).int) {
|
||||
inline .u64, .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),
|
||||
.big_int => |b| b,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isZero(v: Value, comp: *const Compilation) bool {
|
||||
if (v.opt_ref == .none) return false;
|
||||
switch (v.ref()) {
|
||||
.zero => return true,
|
||||
.one => return false,
|
||||
.null => return target_util.nullRepr(comp.target) == 0,
|
||||
else => {},
|
||||
}
|
||||
const key = comp.interner.get(v.ref());
|
||||
switch (key) {
|
||||
.float => |repr| switch (repr) {
|
||||
inline else => |data| return data == 0,
|
||||
},
|
||||
.int => |repr| switch (repr) {
|
||||
inline .i64, .u64 => |data| return data == 0,
|
||||
.big_int => |data| return data.eqlZero(),
|
||||
},
|
||||
.bytes => return false,
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts value to zero or one;
|
||||
/// `.none` value remains unchanged.
|
||||
pub fn boolCast(v: *Value, comp: *const Compilation) void {
|
||||
if (v.opt_ref == .none) return;
|
||||
v.* = fromBool(v.toBool(comp));
|
||||
}
|
||||
|
||||
pub fn fromBool(b: bool) Value {
|
||||
return if (b) one else zero;
|
||||
}
|
||||
|
||||
pub fn toBool(v: Value, comp: *const Compilation) bool {
|
||||
return !v.isZero(comp);
|
||||
}
|
||||
|
||||
pub fn toInt(v: Value, comptime T: type, comp: *const Compilation) ?T {
|
||||
if (v.opt_ref == .none) return null;
|
||||
if (comp.interner.get(v.ref()) != .int) return null;
|
||||
var space: BigIntSpace = undefined;
|
||||
const big_int = v.toBigInt(&space, comp);
|
||||
return big_int.to(T) catch null;
|
||||
}
|
||||
|
||||
pub fn add(res: *Value, lhs: Value, rhs: Value, ty: Type, comp: *Compilation) !bool {
|
||||
const bits: usize = @intCast(ty.bitSizeof(comp).?);
|
||||
if (ty.isFloat()) {
|
||||
const f: Interner.Key.Float = switch (bits) {
|
||||
16 => .{ .f16 = lhs.toFloat(f16, comp) + rhs.toFloat(f16, comp) },
|
||||
32 => .{ .f32 = lhs.toFloat(f32, comp) + rhs.toFloat(f32, comp) },
|
||||
64 => .{ .f64 = lhs.toFloat(f64, comp) + rhs.toFloat(f64, comp) },
|
||||
80 => .{ .f80 = lhs.toFloat(f80, comp) + rhs.toFloat(f80, comp) },
|
||||
128 => .{ .f128 = lhs.toFloat(f128, comp) + rhs.toFloat(f128, comp) },
|
||||
else => unreachable,
|
||||
};
|
||||
res.* = try intern(comp, .{ .float = f });
|
||||
return false;
|
||||
} else {
|
||||
var lhs_space: BigIntSpace = undefined;
|
||||
var rhs_space: BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const rhs_bigint = rhs.toBigInt(&rhs_space, comp);
|
||||
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcTwosCompLimbCount(bits),
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
|
||||
const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, ty.signedness(comp), bits);
|
||||
res.* = try intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
return overflowed;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sub(res: *Value, lhs: Value, rhs: Value, ty: Type, comp: *Compilation) !bool {
|
||||
const bits: usize = @intCast(ty.bitSizeof(comp).?);
|
||||
if (ty.isFloat()) {
|
||||
const f: Interner.Key.Float = switch (bits) {
|
||||
16 => .{ .f16 = lhs.toFloat(f16, comp) - rhs.toFloat(f16, comp) },
|
||||
32 => .{ .f32 = lhs.toFloat(f32, comp) - rhs.toFloat(f32, comp) },
|
||||
64 => .{ .f64 = lhs.toFloat(f64, comp) - rhs.toFloat(f64, comp) },
|
||||
80 => .{ .f80 = lhs.toFloat(f80, comp) - rhs.toFloat(f80, comp) },
|
||||
128 => .{ .f128 = lhs.toFloat(f128, comp) - rhs.toFloat(f128, comp) },
|
||||
else => unreachable,
|
||||
};
|
||||
res.* = try intern(comp, .{ .float = f });
|
||||
return false;
|
||||
} else {
|
||||
var lhs_space: BigIntSpace = undefined;
|
||||
var rhs_space: BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const rhs_bigint = rhs.toBigInt(&rhs_space, comp);
|
||||
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcTwosCompLimbCount(bits),
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
|
||||
const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, ty.signedness(comp), bits);
|
||||
res.* = try intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
return overflowed;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mul(res: *Value, lhs: Value, rhs: Value, ty: Type, comp: *Compilation) !bool {
|
||||
const bits: usize = @intCast(ty.bitSizeof(comp).?);
|
||||
if (ty.isFloat()) {
|
||||
const f: Interner.Key.Float = switch (bits) {
|
||||
16 => .{ .f16 = lhs.toFloat(f16, comp) * rhs.toFloat(f16, comp) },
|
||||
32 => .{ .f32 = lhs.toFloat(f32, comp) * rhs.toFloat(f32, comp) },
|
||||
64 => .{ .f64 = lhs.toFloat(f64, comp) * rhs.toFloat(f64, comp) },
|
||||
80 => .{ .f80 = lhs.toFloat(f80, comp) * rhs.toFloat(f80, comp) },
|
||||
128 => .{ .f128 = lhs.toFloat(f128, comp) * rhs.toFloat(f128, comp) },
|
||||
else => unreachable,
|
||||
};
|
||||
res.* = try intern(comp, .{ .float = f });
|
||||
return false;
|
||||
} else {
|
||||
var lhs_space: BigIntSpace = undefined;
|
||||
var rhs_space: BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const rhs_bigint = rhs.toBigInt(&rhs_space, comp);
|
||||
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
lhs_bigint.limbs.len + rhs_bigint.limbs.len,
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
|
||||
const limbs_buffer = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcMulLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len, 1),
|
||||
);
|
||||
defer comp.gpa.free(limbs_buffer);
|
||||
|
||||
result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, comp.gpa);
|
||||
|
||||
const signedness = ty.signedness(comp);
|
||||
const overflowed = !result_bigint.toConst().fitsInTwosComp(signedness, bits);
|
||||
if (overflowed) {
|
||||
result_bigint.truncate(result_bigint.toConst(), signedness, bits);
|
||||
}
|
||||
res.* = try intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
return overflowed;
|
||||
}
|
||||
}
|
||||
|
||||
/// caller guarantees rhs != 0
|
||||
pub fn div(res: *Value, lhs: Value, rhs: Value, ty: Type, comp: *Compilation) !bool {
|
||||
const bits: usize = @intCast(ty.bitSizeof(comp).?);
|
||||
if (ty.isFloat()) {
|
||||
const f: Interner.Key.Float = switch (bits) {
|
||||
16 => .{ .f16 = lhs.toFloat(f16, comp) / rhs.toFloat(f16, comp) },
|
||||
32 => .{ .f32 = lhs.toFloat(f32, comp) / rhs.toFloat(f32, comp) },
|
||||
64 => .{ .f64 = lhs.toFloat(f64, comp) / rhs.toFloat(f64, comp) },
|
||||
80 => .{ .f80 = lhs.toFloat(f80, comp) / rhs.toFloat(f80, comp) },
|
||||
128 => .{ .f128 = lhs.toFloat(f128, comp) / rhs.toFloat(f128, comp) },
|
||||
else => unreachable,
|
||||
};
|
||||
res.* = try intern(comp, .{ .float = f });
|
||||
return false;
|
||||
} else {
|
||||
var lhs_space: BigIntSpace = undefined;
|
||||
var rhs_space: BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const rhs_bigint = rhs.toBigInt(&rhs_space, comp);
|
||||
|
||||
const limbs_q = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
lhs_bigint.limbs.len,
|
||||
);
|
||||
defer comp.gpa.free(limbs_q);
|
||||
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
||||
|
||||
const limbs_r = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
rhs_bigint.limbs.len,
|
||||
);
|
||||
defer comp.gpa.free(limbs_r);
|
||||
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
||||
|
||||
const limbs_buffer = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcDivLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
|
||||
);
|
||||
defer comp.gpa.free(limbs_buffer);
|
||||
|
||||
result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
||||
|
||||
res.* = try intern(comp, .{ .int = .{ .big_int = result_q.toConst() } });
|
||||
return !result_q.toConst().fitsInTwosComp(ty.signedness(comp), bits);
|
||||
}
|
||||
}
|
||||
|
||||
/// caller guarantees rhs != 0
|
||||
/// caller guarantees lhs != std.math.minInt(T) OR rhs != -1
|
||||
pub fn rem(lhs: Value, rhs: Value, ty: Type, comp: *Compilation) !Value {
|
||||
var lhs_space: BigIntSpace = undefined;
|
||||
var rhs_space: BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const rhs_bigint = rhs.toBigInt(&rhs_space, comp);
|
||||
|
||||
const signedness = ty.signedness(comp);
|
||||
if (signedness == .signed) {
|
||||
var spaces: [3]BigIntSpace = undefined;
|
||||
const min_val = BigIntMutable.init(&spaces[0].limbs, ty.minInt(comp)).toConst();
|
||||
const negative = BigIntMutable.init(&spaces[1].limbs, -1).toConst();
|
||||
const big_one = BigIntMutable.init(&spaces[2].limbs, 1).toConst();
|
||||
if (lhs_bigint.eql(min_val) and rhs_bigint.eql(negative)) {
|
||||
return .{};
|
||||
} else if (rhs_bigint.order(big_one).compare(.lt)) {
|
||||
// lhs - @divTrunc(lhs, rhs) * rhs
|
||||
var tmp: Value = undefined;
|
||||
_ = try tmp.div(lhs, rhs, ty, comp);
|
||||
_ = try tmp.mul(tmp, rhs, ty, comp);
|
||||
_ = try tmp.sub(lhs, tmp, ty, comp);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
const limbs_q = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
lhs_bigint.limbs.len,
|
||||
);
|
||||
defer comp.gpa.free(limbs_q);
|
||||
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
||||
|
||||
const limbs_r = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
rhs_bigint.limbs.len,
|
||||
);
|
||||
defer comp.gpa.free(limbs_r);
|
||||
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
||||
|
||||
const limbs_buffer = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcDivLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
|
||||
);
|
||||
defer comp.gpa.free(limbs_buffer);
|
||||
|
||||
result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
||||
return intern(comp, .{ .int = .{ .big_int = result_r.toConst() } });
|
||||
}
|
||||
|
||||
pub fn bitOr(lhs: Value, rhs: Value, comp: *Compilation) !Value {
|
||||
var lhs_space: BigIntSpace = undefined;
|
||||
var rhs_space: BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const rhs_bigint = rhs.toBigInt(&rhs_space, comp);
|
||||
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
@max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
|
||||
result_bigint.bitOr(lhs_bigint, rhs_bigint);
|
||||
return intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
}
|
||||
|
||||
pub fn bitXor(lhs: Value, rhs: Value, comp: *Compilation) !Value {
|
||||
var lhs_space: BigIntSpace = undefined;
|
||||
var rhs_space: BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const rhs_bigint = rhs.toBigInt(&rhs_space, comp);
|
||||
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
@max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
|
||||
result_bigint.bitXor(lhs_bigint, rhs_bigint);
|
||||
return intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
}
|
||||
|
||||
pub fn bitAnd(lhs: Value, rhs: Value, comp: *Compilation) !Value {
|
||||
var lhs_space: BigIntSpace = undefined;
|
||||
var rhs_space: BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const rhs_bigint = rhs.toBigInt(&rhs_space, comp);
|
||||
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
@max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
|
||||
result_bigint.bitAnd(lhs_bigint, rhs_bigint);
|
||||
return intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
}
|
||||
|
||||
pub fn bitNot(val: Value, ty: Type, comp: *Compilation) !Value {
|
||||
const bits: usize = @intCast(ty.bitSizeof(comp).?);
|
||||
var val_space: Value.BigIntSpace = undefined;
|
||||
const val_bigint = val.toBigInt(&val_space, comp);
|
||||
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcTwosCompLimbCount(bits),
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
|
||||
result_bigint.bitNotWrap(val_bigint, ty.signedness(comp), bits);
|
||||
return intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
}
|
||||
|
||||
pub fn shl(res: *Value, lhs: Value, rhs: Value, ty: Type, comp: *Compilation) !bool {
|
||||
var lhs_space: Value.BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const shift = rhs.toInt(usize, comp) orelse std.math.maxInt(usize);
|
||||
|
||||
const bits: usize = @intCast(ty.bitSizeof(comp).?);
|
||||
if (shift > bits) {
|
||||
if (lhs_bigint.positive) {
|
||||
res.* = try intern(comp, .{ .int = .{ .u64 = ty.maxInt(comp) } });
|
||||
} else {
|
||||
res.* = try intern(comp, .{ .int = .{ .i64 = ty.minInt(comp) } });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1,
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
|
||||
result_bigint.shiftLeft(lhs_bigint, shift);
|
||||
const signedness = ty.signedness(comp);
|
||||
const overflowed = !result_bigint.toConst().fitsInTwosComp(signedness, bits);
|
||||
if (overflowed) {
|
||||
result_bigint.truncate(result_bigint.toConst(), signedness, bits);
|
||||
}
|
||||
res.* = try intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
return overflowed;
|
||||
}
|
||||
|
||||
pub fn shr(lhs: Value, rhs: Value, ty: Type, comp: *Compilation) !Value {
|
||||
var lhs_space: Value.BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
|
||||
const shift = rhs.toInt(usize, comp) orelse return zero;
|
||||
|
||||
const result_limbs = lhs_bigint.limbs.len -| (shift / (@sizeOf(std.math.big.Limb) * 8));
|
||||
if (result_limbs == 0) {
|
||||
// The shift is enough to remove all the bits from the number, which means the
|
||||
// result is 0 or -1 depending on the sign.
|
||||
if (lhs_bigint.positive) {
|
||||
return zero;
|
||||
} else {
|
||||
return intern(comp, .{ .int = .{ .i64 = -1 } });
|
||||
}
|
||||
}
|
||||
|
||||
const bits: usize = @intCast(ty.bitSizeof(comp).?);
|
||||
const limbs = try comp.gpa.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcTwosCompLimbCount(bits),
|
||||
);
|
||||
defer comp.gpa.free(limbs);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
|
||||
result_bigint.shiftRight(lhs_bigint, shift);
|
||||
return intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
}
|
||||
|
||||
pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, comp: *const Compilation) bool {
|
||||
if (op == .eq) {
|
||||
return lhs.opt_ref == rhs.opt_ref;
|
||||
} else if (lhs.opt_ref == rhs.opt_ref) {
|
||||
return std.math.Order.eq.compare(op);
|
||||
}
|
||||
|
||||
const lhs_key = comp.interner.get(lhs.ref());
|
||||
const rhs_key = comp.interner.get(rhs.ref());
|
||||
if (lhs_key == .float or rhs_key == .float) {
|
||||
const lhs_f128 = lhs.toFloat(f128, comp);
|
||||
const rhs_f128 = rhs.toFloat(f128, comp);
|
||||
return std.math.compare(lhs_f128, op, rhs_f128);
|
||||
}
|
||||
|
||||
var lhs_bigint_space: BigIntSpace = undefined;
|
||||
var rhs_bigint_space: BigIntSpace = undefined;
|
||||
const lhs_bigint = lhs.toBigInt(&lhs_bigint_space, comp);
|
||||
const rhs_bigint = rhs.toBigInt(&rhs_bigint_space, comp);
|
||||
return lhs_bigint.order(rhs_bigint).compare(op);
|
||||
}
|
||||
|
||||
pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w).Error!void {
|
||||
if (ty.is(.bool)) {
|
||||
return w.writeAll(if (v.isZero(comp)) "false" else "true");
|
||||
}
|
||||
const key = comp.interner.get(v.ref());
|
||||
switch (key) {
|
||||
.null => return w.writeAll("nullptr_t"),
|
||||
.int => |repr| switch (repr) {
|
||||
inline else => |x| return w.print("{d}", .{x}),
|
||||
},
|
||||
.float => |repr| switch (repr) {
|
||||
.f16 => |x| return w.print("{d}", .{@round(@as(f64, @floatCast(x)) * 1000) / 1000}),
|
||||
.f32 => |x| return w.print("{d}", .{@round(@as(f64, @floatCast(x)) * 1000000) / 1000000}),
|
||||
inline else => |x| return w.print("{d}", .{@as(f64, @floatCast(x))}),
|
||||
},
|
||||
.bytes => |b| return printString(b, ty, comp, w),
|
||||
else => unreachable, // not a value
|
||||
}
|
||||
}
|
||||
|
||||
pub fn printString(bytes: []const u8, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w).Error!void {
|
||||
const size: Compilation.CharUnitSize = @enumFromInt(ty.elemType().sizeof(comp).?);
|
||||
const without_null = bytes[0 .. bytes.len - @intFromEnum(size)];
|
||||
switch (size) {
|
||||
inline .@"1", .@"2" => |sz| {
|
||||
const data_slice: []const sz.Type() = @alignCast(std.mem.bytesAsSlice(sz.Type(), without_null));
|
||||
const formatter = if (sz == .@"1") std.zig.fmtEscapes(data_slice) else std.unicode.fmtUtf16le(data_slice);
|
||||
try w.print("\"{}\"", .{formatter});
|
||||
},
|
||||
.@"4" => {
|
||||
try w.writeByte('"');
|
||||
const data_slice = std.mem.bytesAsSlice(u32, without_null);
|
||||
var buf: [4]u8 = undefined;
|
||||
for (data_slice) |item| {
|
||||
if (item <= std.math.maxInt(u21) and std.unicode.utf8ValidCodepoint(@intCast(item))) {
|
||||
const codepoint: u21 = @intCast(item);
|
||||
const written = std.unicode.utf8Encode(codepoint, &buf) catch unreachable;
|
||||
try w.print("{s}", .{buf[0..written]});
|
||||
} else {
|
||||
try w.print("\\x{x}", .{item});
|
||||
}
|
||||
}
|
||||
try w.writeByte('"');
|
||||
},
|
||||
}
|
||||
}
|
||||
1111
deps/aro/aro/char_info.zig
vendored
Normal file
1111
deps/aro/aro/char_info.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
627
deps/aro/aro/char_info/identifier_tables.zig
vendored
Normal file
627
deps/aro/aro/char_info/identifier_tables.zig
vendored
Normal file
@ -0,0 +1,627 @@
|
||||
//! Adapted from the `unicode-ident` crate: https://github.com/dtolnay/unicode-ident
|
||||
//! and Unicode Standard Annex #31 https://www.unicode.org/reports/tr31/
|
||||
//! Licensed under the MIT License and the Unicode license
|
||||
|
||||
pub const chunk = 64;
|
||||
|
||||
pub const trie_start: [402]u8 align(8) = .{
|
||||
0x04, 0x0B, 0x0F, 0x13, 0x17, 0x1B, 0x1F, 0x23, 0x27, 0x2D, 0x31, 0x34, 0x38, 0x3C, 0x40, 0x02,
|
||||
0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x4D, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x51, 0x54, 0x58, 0x5C, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x60, 0x64, 0x66,
|
||||
0x6A, 0x6E, 0x72, 0x28, 0x76, 0x78, 0x7C, 0x80, 0x84, 0x88, 0x8C, 0x90, 0x94, 0x98, 0x9E, 0xA2,
|
||||
0x05, 0x2B, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x99, 0x05, 0x05, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x05, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0xB1, 0x00, 0xB5, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x32, 0x05, 0x05, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x43, 0xBB, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC8, 0x00, 0x00, 0x00, 0xAF,
|
||||
0xCE, 0xD2, 0xD6, 0xBC, 0xDA, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0xE0, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x52, 0xE3, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE6, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0xE1, 0x05, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x05, 0xEB, 0x00, 0x00,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE4, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0xE7,
|
||||
};
|
||||
|
||||
pub const trie_continue: [1793]u8 align(8) = .{
|
||||
0x08, 0x0D, 0x11, 0x15, 0x19, 0x1D, 0x21, 0x25, 0x2A, 0x2F, 0x31, 0x36, 0x3A, 0x3E, 0x42, 0x02,
|
||||
0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x4F, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x51, 0x56, 0x5A, 0x5E, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, 0x64, 0x68,
|
||||
0x6C, 0x70, 0x74, 0x28, 0x76, 0x7A, 0x7E, 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9B, 0xA0, 0xA4,
|
||||
0x05, 0x2B, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x99, 0x05, 0x05, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x05, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0xB3, 0x00, 0xB7, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x32, 0x05, 0x05, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x43, 0xBB, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0xAC, 0xC4, 0xC6, 0xCA, 0x00, 0xCC, 0x00, 0xAF,
|
||||
0xD0, 0xD4, 0xD8, 0xBC, 0xDC, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0xE0, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x52, 0xE3, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE6, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0xE1, 0x05, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x05, 0xEB, 0x00, 0x00,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE4, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xC2,
|
||||
};
|
||||
|
||||
pub const leaf: [7584]u8 align(64) = .{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xAA, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x5F, 0xDC, 0x1F, 0xCF, 0x0F, 0xFF, 0x1F, 0xDC, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x04, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xA0, 0x04, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0x03, 0x00, 0x1F, 0x50, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xB8,
|
||||
0x40, 0xD7, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0x03, 0x00, 0x1F, 0x50, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xB8,
|
||||
0xC0, 0xD7, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x03, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x02, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x87, 0x07, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFB, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x02, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x01, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xB6, 0x00, 0xFF, 0xFF, 0xFF, 0x87, 0x07, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xC0, 0xFE, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x60, 0xC0, 0x00, 0x9C,
|
||||
0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x02, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x07, 0x30, 0x04,
|
||||
0x00, 0x00, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x9F, 0xFF, 0xFD, 0xFF, 0x9F,
|
||||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x24,
|
||||
0xFF, 0xFF, 0x3F, 0x04, 0x10, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x07, 0xFF, 0xFF,
|
||||
0xFF, 0x7E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x01, 0xFF, 0x03, 0x00, 0xFE, 0xFF,
|
||||
0xE1, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xC5, 0x23, 0x00, 0x40, 0x00, 0xB0, 0x03, 0x00, 0x03, 0x10,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x07, 0xFF, 0xFF,
|
||||
0xFF, 0x7E, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFE, 0xFF,
|
||||
0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xC5, 0xF3, 0x9F, 0x79, 0x80, 0xB0, 0xCF, 0xFF, 0x03, 0x50,
|
||||
0xE0, 0x87, 0xF9, 0xFF, 0xFF, 0xFD, 0x6D, 0x03, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x1C, 0x00,
|
||||
0xE0, 0xBF, 0xFB, 0xFF, 0xFF, 0xFD, 0xED, 0x23, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02,
|
||||
0xE0, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0x23, 0x00, 0x00, 0x00, 0xB0, 0x03, 0x00, 0x02, 0x00,
|
||||
0xE8, 0xC7, 0x3D, 0xD6, 0x18, 0xC7, 0xFF, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xEE, 0x87, 0xF9, 0xFF, 0xFF, 0xFD, 0x6D, 0xD3, 0x87, 0x39, 0x02, 0x5E, 0xC0, 0xFF, 0x3F, 0x00,
|
||||
0xEE, 0xBF, 0xFB, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0xBF, 0x3B, 0x01, 0x00, 0xCF, 0xFF, 0x00, 0xFE,
|
||||
0xEE, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0x9F, 0x39, 0xE0, 0xB0, 0xCF, 0xFF, 0x02, 0x00,
|
||||
0xEC, 0xC7, 0x3D, 0xD6, 0x18, 0xC7, 0xFF, 0xC3, 0xC7, 0x3D, 0x81, 0x00, 0xC0, 0xFF, 0x00, 0x00,
|
||||
0xE0, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x27, 0x03, 0x00, 0x00, 0x00,
|
||||
0xE1, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xEF, 0x23, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x06, 0x00,
|
||||
0xF0, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x27, 0x00, 0x40, 0x70, 0x80, 0x03, 0x00, 0x00, 0xFC,
|
||||
0xE0, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFB, 0x2F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xF3, 0xDF, 0x3D, 0x60, 0x27, 0xCF, 0xFF, 0x00, 0x00,
|
||||
0xEF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xEF, 0xF3, 0xDF, 0x3D, 0x60, 0x60, 0xCF, 0xFF, 0x0E, 0x00,
|
||||
0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x7D, 0xF0, 0x80, 0xCF, 0xFF, 0x00, 0xFC,
|
||||
0xEE, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFB, 0x2F, 0x7F, 0x84, 0x5F, 0xFF, 0xC0, 0xFF, 0x0C, 0x00,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xD6, 0xF7, 0xFF, 0xFF, 0xAF, 0xFF, 0x05, 0x20, 0x5F, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,
|
||||
0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x7F, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0xD6, 0xF7, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0x3F, 0x5F, 0x7F, 0xFF, 0xF3, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x03, 0xFF, 0x03, 0xA0, 0xC2, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF,
|
||||
0xDF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x80, 0x00, 0x00, 0x3F, 0x3C, 0x62, 0xC0, 0xE1, 0xFF,
|
||||
0x03, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00,
|
||||
0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0xFE, 0x03, 0x00,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF,
|
||||
0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0x01,
|
||||
0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xDF, 0x01, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF,
|
||||
0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0x01,
|
||||
0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0x1F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xDF, 0x0D, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x30, 0xFF, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xB8, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x0F, 0xFF, 0x0F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0x01, 0xC0, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||
0xFF, 0x03, 0xFF, 0x03, 0x80, 0x00, 0xFF, 0xBF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x03, 0x00, 0xF8, 0x0F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0x6F, 0x04,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0xF0, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80,
|
||||
0x00, 0x00, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x84, 0xFC, 0x2F, 0x3F, 0x50, 0xFD, 0xFF, 0xF3, 0xE0, 0x43, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x80,
|
||||
0x00, 0x00, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x1F, 0xE2, 0xFF, 0x01, 0x00,
|
||||
0x84, 0xFC, 0x2F, 0x3F, 0x50, 0xFD, 0xFF, 0xF3, 0xE0, 0x43, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x78, 0x0C, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x0F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x80,
|
||||
0xFF, 0xFF, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xE0, 0x00, 0x00, 0x00, 0xFE, 0x03, 0x3E, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x7F, 0xE0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7,
|
||||
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0xE0, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x3E, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x7F, 0xE6, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x1F, 0xFF, 0xFF, 0x00, 0x0C, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x80,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xEB, 0x03, 0x00, 0x00, 0xFC, 0xFF,
|
||||
0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xBF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
|
||||
0x00, 0x00, 0x80, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xEB, 0x03, 0x00, 0x00, 0xFC, 0xFF,
|
||||
0xBB, 0xF7, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x68,
|
||||
0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x80, 0x00, 0x00, 0xDF, 0xFF, 0x00, 0x7C,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xE8,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x7F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF7, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0xC4,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x3E, 0x05, 0x00, 0x00, 0x38, 0xFF, 0x07, 0x1C, 0x00,
|
||||
0x7E, 0x7E, 0x7E, 0x00, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0x03, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0x3F, 0xFF, 0x03, 0xFF, 0xFF, 0x7F, 0xFC,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0x7C, 0x00,
|
||||
0x7E, 0x7E, 0x7E, 0x00, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0x03, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0xFF, 0x03,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7F, 0x00, 0xF8, 0xA0, 0xFF, 0xFD, 0x7F, 0x5F, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7F, 0x00, 0xF8, 0xE0, 0xFF, 0xFD, 0x7F, 0x5F, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xAA,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFC, 0xFC, 0x1C, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xAA,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0x00, 0x00, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFC, 0xFC, 0x1C, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xEF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xB7, 0xFF, 0x3F, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xEF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xB7, 0xFF, 0x3F, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xF7,
|
||||
0xFF, 0xF7, 0xB7, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xF7,
|
||||
0xFF, 0xF7, 0xB7, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3F, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x91, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x7F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x37, 0x00,
|
||||
0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0xEF, 0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x07, 0x00,
|
||||
0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6F, 0xF0, 0xEF, 0xFE, 0xFF, 0xFF, 0x3F, 0x87, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x07, 0x00,
|
||||
0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00,
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00,
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00,
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x90, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0x00,
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x1E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x3F, 0x80,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x04, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x03,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xDE, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0x0F, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7F, 0xBD, 0xFF, 0xBF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00,
|
||||
0xE0, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0x23, 0x00, 0x00, 0x01, 0xE0, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7F, 0xBD, 0xFF, 0xBF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x03,
|
||||
0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xFB, 0x9F, 0x39, 0x81, 0xE0, 0xCF, 0x1F, 0x1F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x80, 0x07, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xC3, 0x03, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0x0F, 0xFF, 0x03, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x80,
|
||||
0x7F, 0xF2, 0x6F, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x80,
|
||||
0x7F, 0xF2, 0x6F, 0xFF, 0xFF, 0xFF, 0xBF, 0xF9, 0x0F, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1B, 0x00, 0x00, 0x00,
|
||||
0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x04, 0x00, 0x00, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x03, 0x00, 0x20, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x6F,
|
||||
0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7F, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0xBF, 0xFD, 0xFF, 0xFF,
|
||||
0xFF, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x01, 0x00, 0xFF, 0x03, 0x00, 0x00, 0xFC, 0xFF,
|
||||
0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7F, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xB4, 0xFF, 0x00, 0xFF, 0x03, 0xBF, 0xFD, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0xFB, 0x01, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x07, 0x00,
|
||||
0xF4, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00,
|
||||
0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x07, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE3, 0x07, 0xF8,
|
||||
0xE7, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x7F, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xE0,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x03, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x0F, 0x00, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0xE0,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x6F, 0xFF, 0x7F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x1F,
|
||||
0xFF, 0x01, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x1F,
|
||||
0xFF, 0x01, 0xFF, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xDF, 0x64, 0xDE, 0xFF, 0xEB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xBF, 0xE7, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7B, 0x5F, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xF7,
|
||||
0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF,
|
||||
0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xF7,
|
||||
0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF,
|
||||
0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x00,
|
||||
0x10, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x3F, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
|
||||
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xEF, 0xFF, 0xFF, 0xFF, 0x96, 0xFE, 0xF7, 0x0A, 0x84, 0xEA, 0x96, 0xAA, 0x96, 0xF7, 0xF7, 0x5E,
|
||||
0xFF, 0xFB, 0xFF, 0x0F, 0xEE, 0xFB, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
@ -38,18 +38,18 @@ const Directive = enum {
|
||||
|
||||
fn beforePreprocess(pragma: *Pragma, comp: *Compilation) void {
|
||||
var self = @fieldParentPtr(GCC, "pragma", pragma);
|
||||
self.original_options = comp.diag.options;
|
||||
self.original_options = comp.diagnostics.options;
|
||||
}
|
||||
|
||||
fn beforeParse(pragma: *Pragma, comp: *Compilation) void {
|
||||
var self = @fieldParentPtr(GCC, "pragma", pragma);
|
||||
comp.diag.options = self.original_options;
|
||||
comp.diagnostics.options = self.original_options;
|
||||
self.options_stack.items.len = 0;
|
||||
}
|
||||
|
||||
fn afterParse(pragma: *Pragma, comp: *Compilation) void {
|
||||
var self = @fieldParentPtr(GCC, "pragma", pragma);
|
||||
comp.diag.options = self.original_options;
|
||||
comp.diagnostics.options = self.original_options;
|
||||
self.options_stack.items.len = 0;
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ fn diagnosticHandler(self: *GCC, pp: *Preprocessor, start_idx: TokenIndex) Pragm
|
||||
.ignored, .warning, .@"error", .fatal => {
|
||||
const str = Pragma.pasteTokens(pp, start_idx + 1) catch |err| switch (err) {
|
||||
error.ExpectedStringLiteral => {
|
||||
return pp.comp.diag.add(.{
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .pragma_requires_string_literal,
|
||||
.loc = diagnostic_tok.loc,
|
||||
.extra = .{ .str = "GCC diagnostic" },
|
||||
@ -86,24 +86,24 @@ fn diagnosticHandler(self: *GCC, pp: *Preprocessor, start_idx: TokenIndex) Pragm
|
||||
};
|
||||
if (!mem.startsWith(u8, str, "-W")) {
|
||||
const next = pp.tokens.get(start_idx + 1);
|
||||
return pp.comp.diag.add(.{
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .malformed_warning_check,
|
||||
.loc = next.loc,
|
||||
.extra = .{ .str = "GCC diagnostic" },
|
||||
}, next.expansionSlice());
|
||||
}
|
||||
const new_kind = switch (diagnostic) {
|
||||
.ignored => Diagnostics.Kind.off,
|
||||
.warning => Diagnostics.Kind.warning,
|
||||
.@"error" => Diagnostics.Kind.@"error",
|
||||
.fatal => Diagnostics.Kind.@"fatal error",
|
||||
const new_kind: Diagnostics.Kind = switch (diagnostic) {
|
||||
.ignored => .off,
|
||||
.warning => .warning,
|
||||
.@"error" => .@"error",
|
||||
.fatal => .@"fatal error",
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
try pp.comp.diag.set(str[2..], new_kind);
|
||||
try pp.comp.diagnostics.set(str[2..], new_kind);
|
||||
},
|
||||
.push => try self.options_stack.append(pp.comp.gpa, pp.comp.diag.options),
|
||||
.pop => pp.comp.diag.options = self.options_stack.popOrNull() orelse self.original_options,
|
||||
.push => try self.options_stack.append(pp.comp.gpa, pp.comp.diagnostics.options),
|
||||
.pop => pp.comp.diagnostics.options = self.options_stack.popOrNull() orelse self.original_options,
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
if (directive_tok.id == .nl) return;
|
||||
|
||||
const gcc_pragma = std.meta.stringToEnum(Directive, pp.expandedSlice(directive_tok)) orelse
|
||||
return pp.comp.diag.add(.{
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .unknown_gcc_pragma,
|
||||
.loc = directive_tok.loc,
|
||||
}, directive_tok.expansionSlice());
|
||||
@ -122,7 +122,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
.warning, .@"error" => {
|
||||
const text = Pragma.pasteTokens(pp, start_idx + 2) catch |err| switch (err) {
|
||||
error.ExpectedStringLiteral => {
|
||||
return pp.comp.diag.add(.{
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .pragma_requires_string_literal,
|
||||
.loc = directive_tok.loc,
|
||||
.extra = .{ .str = @tagName(gcc_pragma) },
|
||||
@ -130,9 +130,9 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
const extra = Diagnostics.Message.Extra{ .str = try pp.comp.diag.arena.allocator().dupe(u8, text) };
|
||||
const extra = Diagnostics.Message.Extra{ .str = try pp.comp.diagnostics.arena.allocator().dupe(u8, text) };
|
||||
const diagnostic_tag: Diagnostics.Tag = if (gcc_pragma == .warning) .pragma_warning_message else .pragma_error_message;
|
||||
return pp.comp.diag.add(
|
||||
return pp.comp.addDiagnostic(
|
||||
.{ .tag = diagnostic_tag, .loc = directive_tok.loc, .extra = extra },
|
||||
directive_tok.expansionSlice(),
|
||||
);
|
||||
@ -140,7 +140,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
.diagnostic => return self.diagnosticHandler(pp, start_idx + 2) catch |err| switch (err) {
|
||||
error.UnknownPragma => {
|
||||
const tok = pp.tokens.get(start_idx + 2);
|
||||
return pp.comp.diag.add(.{
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .unknown_gcc_pragma_directive,
|
||||
.loc = tok.loc,
|
||||
}, tok.expansionSlice());
|
||||
@ -154,14 +154,14 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
if (tok.id == .nl) break;
|
||||
|
||||
if (!tok.id.isMacroIdentifier()) {
|
||||
return pp.comp.diag.add(.{
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .pragma_poison_identifier,
|
||||
.loc = tok.loc,
|
||||
}, tok.expansionSlice());
|
||||
}
|
||||
const str = pp.expandedSlice(tok);
|
||||
if (pp.defines.get(str) != null) {
|
||||
try pp.comp.diag.add(.{
|
||||
try pp.comp.addDiagnostic(.{
|
||||
.tag = .pragma_poison_macro,
|
||||
.loc = tok.loc,
|
||||
}, tok.expansionSlice());
|
||||
@ -22,7 +22,7 @@ pub fn init(allocator: mem.Allocator) !*Pragma {
|
||||
}
|
||||
|
||||
fn deinit(pragma: *Pragma, comp: *Compilation) void {
|
||||
var self = @fieldParentPtr(Message, "pragma", pragma);
|
||||
const self = @fieldParentPtr(Message, "pragma", pragma);
|
||||
comp.gpa.destroy(self);
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ fn preprocessorHandler(_: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pra
|
||||
|
||||
const str = Pragma.pasteTokens(pp, start_idx + 1) catch |err| switch (err) {
|
||||
error.ExpectedStringLiteral => {
|
||||
return pp.comp.diag.add(.{
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .pragma_requires_string_literal,
|
||||
.loc = message_tok.loc,
|
||||
.extra = .{ .str = "message" },
|
||||
@ -45,6 +45,6 @@ fn preprocessorHandler(_: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pra
|
||||
message_expansion_locs[message_expansion_locs.len - 1]
|
||||
else
|
||||
message_tok.loc;
|
||||
const extra = Diagnostics.Message.Extra{ .str = try pp.comp.diag.arena.allocator().dupe(u8, str) };
|
||||
return pp.comp.diag.add(.{ .tag = .pragma_message, .loc = loc, .extra = extra }, &.{});
|
||||
const extra = Diagnostics.Message.Extra{ .str = try pp.comp.diagnostics.arena.allocator().dupe(u8, str) };
|
||||
return pp.comp.addDiagnostic(.{ .tag = .pragma_message, .loc = loc, .extra = extra }, &.{});
|
||||
}
|
||||
@ -42,7 +42,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
const name_tok = pp.tokens.get(start_idx);
|
||||
const next = pp.tokens.get(start_idx + 1);
|
||||
if (next.id != .nl) {
|
||||
try pp.comp.diag.add(.{
|
||||
try pp.comp.addDiagnostic(.{
|
||||
.tag = .extra_tokens_directive_end,
|
||||
.loc = name_tok.loc,
|
||||
}, next.expansionSlice());
|
||||
@ -34,7 +34,7 @@ fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation
|
||||
var idx = start_idx + 1;
|
||||
const l_paren = p.pp.tokens.get(idx);
|
||||
if (l_paren.id != .l_paren) {
|
||||
return p.comp.diag.add(.{
|
||||
return p.comp.addDiagnostic(.{
|
||||
.tag = .pragma_pack_lparen,
|
||||
.loc = l_paren.loc,
|
||||
}, l_paren.expansionSlice());
|
||||
@ -127,7 +127,7 @@ fn packInt(p: *Parser, tok_i: TokenIndex) Compilation.Error!?u8 {
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
const int = if (res.val.tag == .int) res.val.getInt(u64) else 99;
|
||||
const int = res.val.toInt(u64, p.comp) orelse 99;
|
||||
switch (int) {
|
||||
1, 2, 4, 8, 16 => return @intCast(int),
|
||||
else => {
|
||||
@ -57,6 +57,7 @@ const SysVContext = struct {
|
||||
|
||||
fn layoutFields(self: *SysVContext, rec: *const Record) void {
|
||||
for (rec.fields, 0..) |*fld, fld_indx| {
|
||||
if (fld.ty.specifier == .invalid) continue;
|
||||
const type_layout = computeLayout(fld.ty, self.comp);
|
||||
|
||||
var field_attrs: ?[]const Attribute = null;
|
||||
@ -587,6 +588,7 @@ pub fn compute(rec: *Type.Record, ty: Type, comp: *const Compilation, pragma_pac
|
||||
.msvc => {
|
||||
var context = MsvcContext.init(ty, comp, pragma_pack);
|
||||
for (rec.fields, 0..) |*fld, fld_indx| {
|
||||
if (fld.ty.specifier == .invalid) continue;
|
||||
var field_attrs: ?[]const Attribute = null;
|
||||
if (rec.field_attributes) |attrs| {
|
||||
field_attrs = attrs[fld_indx];
|
||||
22
deps/aro/target.zig → deps/aro/aro/target.zig
vendored
22
deps/aro/target.zig → deps/aro/aro/target.zig
vendored
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const LangOpts = @import("LangOpts.zig");
|
||||
const Type = @import("Type.zig");
|
||||
const llvm = @import("zig").codegen.llvm;
|
||||
const llvm = @import("root").codegen.llvm;
|
||||
const TargetSet = @import("Builtins/Properties.zig").TargetSet;
|
||||
|
||||
/// intmax_t for this target
|
||||
@ -258,6 +258,21 @@ pub fn systemCompiler(target: std.Target) LangOpts.Compiler {
|
||||
return .clang;
|
||||
}
|
||||
|
||||
pub fn hasFloat128(target: std.Target) bool {
|
||||
if (target.cpu.arch.isWasm()) return true;
|
||||
if (target.isDarwin()) return false;
|
||||
if (target.cpu.arch.isPPC() or target.cpu.arch.isPPC64()) return std.Target.powerpc.featureSetHas(target.cpu.features, .float128);
|
||||
return switch (target.os.tag) {
|
||||
.dragonfly,
|
||||
.haiku,
|
||||
.linux,
|
||||
.openbsd,
|
||||
.solaris,
|
||||
=> 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;
|
||||
@ -809,3 +824,8 @@ test "target size/align tests" {
|
||||
try std.testing.expectEqual(@as(u64, 1), ct.alignof(&comp));
|
||||
try std.testing.expectEqual(true, ignoreNonZeroSizedBitfieldTypeAlignment(comp.target));
|
||||
}
|
||||
|
||||
/// The canonical integer representation of nullptr_t.
|
||||
pub fn nullRepr(_: std.Target) u64 {
|
||||
return 0;
|
||||
}
|
||||
@ -132,7 +132,7 @@ pub const Kind = enum {
|
||||
};
|
||||
}
|
||||
|
||||
/// Required alignment within aro (on compiler host) for writing to retained_strings
|
||||
/// Required alignment within aro (on compiler host) for writing to Interner.strings.
|
||||
pub fn internalStorageAlignment(kind: Kind, comp: *const Compilation) usize {
|
||||
return switch (kind.charUnitSize(comp)) {
|
||||
inline else => |size| @alignOf(size.Type()),
|
||||
@ -250,7 +250,7 @@ pub const Parser = struct {
|
||||
self.i += expected_len;
|
||||
|
||||
if (overflowed) {
|
||||
self.err(.escape_sequence_overflow, .{ .unsigned = start + self.prefixLen() });
|
||||
self.err(.escape_sequence_overflow, .{ .offset = start + self.prefixLen() });
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -260,7 +260,7 @@ pub const Parser = struct {
|
||||
}
|
||||
|
||||
if (val > std.math.maxInt(u21) or !std.unicode.utf8ValidCodepoint(@intCast(val))) {
|
||||
self.err(.invalid_universal_character, .{ .unsigned = start + self.prefixLen() });
|
||||
self.err(.invalid_universal_character, .{ .offset = start + self.prefixLen() });
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -270,7 +270,7 @@ pub const Parser = struct {
|
||||
}
|
||||
|
||||
if (val < 0xA0 and (val != '$' and val != '@' and val != '`')) {
|
||||
const is_error = !self.comp.langopts.standard.atLeast(.c2x);
|
||||
const is_error = !self.comp.langopts.standard.atLeast(.c23);
|
||||
if (val >= 0x20 and val <= 0x7F) {
|
||||
if (is_error) {
|
||||
self.err(.ucn_basic_char_error, .{ .ascii = @intCast(val) });
|
||||
@ -347,7 +347,7 @@ pub const Parser = struct {
|
||||
count += 1;
|
||||
}
|
||||
if (overflowed or val > self.kind.maxInt(self.comp)) {
|
||||
self.err(.escape_sequence_overflow, .{ .unsigned = start + self.prefixLen() });
|
||||
self.err(.escape_sequence_overflow, .{ .offset = start + self.prefixLen() });
|
||||
return 0;
|
||||
}
|
||||
if (count == 0) {
|
||||
@ -385,6 +385,7 @@ test Linux {
|
||||
comp.environment = .{
|
||||
.path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
};
|
||||
defer comp.environment = .{};
|
||||
|
||||
const raw_triple = "x86_64-linux-gnu";
|
||||
const cross = std.zig.CrossTarget.parse(.{ .arch_os_abi = raw_triple }) catch unreachable;
|
||||
310
deps/aro/aro/tracy.zig
vendored
Normal file
310
deps/aro/aro/tracy.zig
vendored
Normal file
@ -0,0 +1,310 @@
|
||||
//! Copied from https://github.com/ziglang/zig/blob/c9006d9479c619d9ed555164831e11a04d88d382/src/tracy.zig
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const build_options = @import("build_options");
|
||||
|
||||
pub const enable = if (builtin.is_test) false else build_options.enable_tracy;
|
||||
pub const enable_allocation = enable and build_options.enable_tracy_allocation;
|
||||
pub const enable_callstack = enable and build_options.enable_tracy_callstack;
|
||||
|
||||
// TODO: make this configurable
|
||||
const callstack_depth = 10;
|
||||
|
||||
const ___tracy_c_zone_context = extern struct {
|
||||
id: u32,
|
||||
active: c_int,
|
||||
|
||||
pub inline fn end(self: @This()) void {
|
||||
___tracy_emit_zone_end(self);
|
||||
}
|
||||
|
||||
pub inline fn addText(self: @This(), text: []const u8) void {
|
||||
___tracy_emit_zone_text(self, text.ptr, text.len);
|
||||
}
|
||||
|
||||
pub inline fn setName(self: @This(), name: []const u8) void {
|
||||
___tracy_emit_zone_name(self, name.ptr, name.len);
|
||||
}
|
||||
|
||||
pub inline fn setColor(self: @This(), color: u32) void {
|
||||
___tracy_emit_zone_color(self, color);
|
||||
}
|
||||
|
||||
pub inline fn setValue(self: @This(), value: u64) void {
|
||||
___tracy_emit_zone_value(self, value);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Ctx = if (enable) ___tracy_c_zone_context else struct {
|
||||
pub inline fn end(self: @This()) void {
|
||||
_ = self;
|
||||
}
|
||||
|
||||
pub inline fn addText(self: @This(), text: []const u8) void {
|
||||
_ = self;
|
||||
_ = text;
|
||||
}
|
||||
|
||||
pub inline fn setName(self: @This(), name: []const u8) void {
|
||||
_ = self;
|
||||
_ = name;
|
||||
}
|
||||
|
||||
pub inline fn setColor(self: @This(), color: u32) void {
|
||||
_ = self;
|
||||
_ = color;
|
||||
}
|
||||
|
||||
pub inline fn setValue(self: @This(), value: u64) void {
|
||||
_ = self;
|
||||
_ = value;
|
||||
}
|
||||
};
|
||||
|
||||
pub inline fn trace(comptime src: std.builtin.SourceLocation) Ctx {
|
||||
if (!enable) return .{};
|
||||
|
||||
if (enable_callstack) {
|
||||
return ___tracy_emit_zone_begin_callstack(&.{
|
||||
.name = null,
|
||||
.function = src.fn_name.ptr,
|
||||
.file = src.file.ptr,
|
||||
.line = src.line,
|
||||
.color = 0,
|
||||
}, callstack_depth, 1);
|
||||
} else {
|
||||
return ___tracy_emit_zone_begin(&.{
|
||||
.name = null,
|
||||
.function = src.fn_name.ptr,
|
||||
.file = src.file.ptr,
|
||||
.line = src.line,
|
||||
.color = 0,
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn traceNamed(comptime src: std.builtin.SourceLocation, comptime name: [:0]const u8) Ctx {
|
||||
if (!enable) return .{};
|
||||
|
||||
if (enable_callstack) {
|
||||
return ___tracy_emit_zone_begin_callstack(&.{
|
||||
.name = name.ptr,
|
||||
.function = src.fn_name.ptr,
|
||||
.file = src.file.ptr,
|
||||
.line = src.line,
|
||||
.color = 0,
|
||||
}, callstack_depth, 1);
|
||||
} else {
|
||||
return ___tracy_emit_zone_begin(&.{
|
||||
.name = name.ptr,
|
||||
.function = src.fn_name.ptr,
|
||||
.file = src.file.ptr,
|
||||
.line = src.line,
|
||||
.color = 0,
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tracyAllocator(allocator: std.mem.Allocator) TracyAllocator(null) {
|
||||
return TracyAllocator(null).init(allocator);
|
||||
}
|
||||
|
||||
pub fn TracyAllocator(comptime name: ?[:0]const u8) type {
|
||||
return struct {
|
||||
parent_allocator: std.mem.Allocator,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn init(parent_allocator: std.mem.Allocator) Self {
|
||||
return .{
|
||||
.parent_allocator = parent_allocator,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn allocator(self: *Self) std.mem.Allocator {
|
||||
return std.mem.Allocator.init(self, allocFn, resizeFn, freeFn);
|
||||
}
|
||||
|
||||
fn allocFn(self: *Self, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) std.mem.Allocator.Error![]u8 {
|
||||
const result = self.parent_allocator.rawAlloc(len, ptr_align, len_align, ret_addr);
|
||||
if (result) |data| {
|
||||
if (data.len != 0) {
|
||||
if (name) |n| {
|
||||
allocNamed(data.ptr, data.len, n);
|
||||
} else {
|
||||
alloc(data.ptr, data.len);
|
||||
}
|
||||
}
|
||||
} else |_| {
|
||||
messageColor("allocation failed", 0xFF0000);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn resizeFn(self: *Self, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) ?usize {
|
||||
if (self.parent_allocator.rawResize(buf, buf_align, new_len, len_align, ret_addr)) |resized_len| {
|
||||
if (name) |n| {
|
||||
freeNamed(buf.ptr, n);
|
||||
allocNamed(buf.ptr, resized_len, n);
|
||||
} else {
|
||||
free(buf.ptr);
|
||||
alloc(buf.ptr, resized_len);
|
||||
}
|
||||
|
||||
return resized_len;
|
||||
}
|
||||
|
||||
// during normal operation the compiler hits this case thousands of times due to this
|
||||
// emitting messages for it is both slow and causes clutter
|
||||
return null;
|
||||
}
|
||||
|
||||
fn freeFn(self: *Self, buf: []u8, buf_align: u29, ret_addr: usize) void {
|
||||
self.parent_allocator.rawFree(buf, buf_align, ret_addr);
|
||||
// this condition is to handle free being called on an empty slice that was never even allocated
|
||||
// example case: `std.process.getSelfExeSharedLibPaths` can return `&[_][:0]u8{}`
|
||||
if (buf.len != 0) {
|
||||
if (name) |n| {
|
||||
freeNamed(buf.ptr, n);
|
||||
} else {
|
||||
free(buf.ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// This function only accepts comptime known strings, see `messageCopy` for runtime strings
|
||||
pub inline fn message(comptime msg: [:0]const u8) void {
|
||||
if (!enable) return;
|
||||
___tracy_emit_messageL(msg.ptr, if (enable_callstack) callstack_depth else 0);
|
||||
}
|
||||
|
||||
// This function only accepts comptime known strings, see `messageColorCopy` for runtime strings
|
||||
pub inline fn messageColor(comptime msg: [:0]const u8, color: u32) void {
|
||||
if (!enable) return;
|
||||
___tracy_emit_messageLC(msg.ptr, color, if (enable_callstack) callstack_depth else 0);
|
||||
}
|
||||
|
||||
pub inline fn messageCopy(msg: []const u8) void {
|
||||
if (!enable) return;
|
||||
___tracy_emit_message(msg.ptr, msg.len, if (enable_callstack) callstack_depth else 0);
|
||||
}
|
||||
|
||||
pub inline fn messageColorCopy(msg: [:0]const u8, color: u32) void {
|
||||
if (!enable) return;
|
||||
___tracy_emit_messageC(msg.ptr, msg.len, color, if (enable_callstack) callstack_depth else 0);
|
||||
}
|
||||
|
||||
pub inline fn frameMark() void {
|
||||
if (!enable) return;
|
||||
___tracy_emit_frame_mark(null);
|
||||
}
|
||||
|
||||
pub inline fn frameMarkNamed(comptime name: [:0]const u8) void {
|
||||
if (!enable) return;
|
||||
___tracy_emit_frame_mark(name.ptr);
|
||||
}
|
||||
|
||||
pub inline fn namedFrame(comptime name: [:0]const u8) Frame(name) {
|
||||
frameMarkStart(name);
|
||||
return .{};
|
||||
}
|
||||
|
||||
pub fn Frame(comptime name: [:0]const u8) type {
|
||||
return struct {
|
||||
pub fn end(_: @This()) void {
|
||||
frameMarkEnd(name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline fn frameMarkStart(comptime name: [:0]const u8) void {
|
||||
if (!enable) return;
|
||||
___tracy_emit_frame_mark_start(name.ptr);
|
||||
}
|
||||
|
||||
inline fn frameMarkEnd(comptime name: [:0]const u8) void {
|
||||
if (!enable) return;
|
||||
___tracy_emit_frame_mark_end(name.ptr);
|
||||
}
|
||||
|
||||
extern fn ___tracy_emit_frame_mark_start(name: [*:0]const u8) void;
|
||||
extern fn ___tracy_emit_frame_mark_end(name: [*:0]const u8) void;
|
||||
|
||||
inline fn alloc(ptr: [*]u8, len: usize) void {
|
||||
if (!enable) return;
|
||||
|
||||
if (enable_callstack) {
|
||||
___tracy_emit_memory_alloc_callstack(ptr, len, callstack_depth, 0);
|
||||
} else {
|
||||
___tracy_emit_memory_alloc(ptr, len, 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline fn allocNamed(ptr: [*]u8, len: usize, comptime name: [:0]const u8) void {
|
||||
if (!enable) return;
|
||||
|
||||
if (enable_callstack) {
|
||||
___tracy_emit_memory_alloc_callstack_named(ptr, len, callstack_depth, 0, name.ptr);
|
||||
} else {
|
||||
___tracy_emit_memory_alloc_named(ptr, len, 0, name.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
inline fn free(ptr: [*]u8) void {
|
||||
if (!enable) return;
|
||||
|
||||
if (enable_callstack) {
|
||||
___tracy_emit_memory_free_callstack(ptr, callstack_depth, 0);
|
||||
} else {
|
||||
___tracy_emit_memory_free(ptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline fn freeNamed(ptr: [*]u8, comptime name: [:0]const u8) void {
|
||||
if (!enable) return;
|
||||
|
||||
if (enable_callstack) {
|
||||
___tracy_emit_memory_free_callstack_named(ptr, callstack_depth, 0, name.ptr);
|
||||
} else {
|
||||
___tracy_emit_memory_free_named(ptr, 0, name.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
extern fn ___tracy_emit_zone_begin(
|
||||
srcloc: *const ___tracy_source_location_data,
|
||||
active: c_int,
|
||||
) ___tracy_c_zone_context;
|
||||
extern fn ___tracy_emit_zone_begin_callstack(
|
||||
srcloc: *const ___tracy_source_location_data,
|
||||
depth: c_int,
|
||||
active: c_int,
|
||||
) ___tracy_c_zone_context;
|
||||
extern fn ___tracy_emit_zone_text(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void;
|
||||
extern fn ___tracy_emit_zone_name(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void;
|
||||
extern fn ___tracy_emit_zone_color(ctx: ___tracy_c_zone_context, color: u32) void;
|
||||
extern fn ___tracy_emit_zone_value(ctx: ___tracy_c_zone_context, value: u64) void;
|
||||
extern fn ___tracy_emit_zone_end(ctx: ___tracy_c_zone_context) void;
|
||||
extern fn ___tracy_emit_memory_alloc(ptr: *const anyopaque, size: usize, secure: c_int) void;
|
||||
extern fn ___tracy_emit_memory_alloc_callstack(ptr: *const anyopaque, size: usize, depth: c_int, secure: c_int) void;
|
||||
extern fn ___tracy_emit_memory_free(ptr: *const anyopaque, secure: c_int) void;
|
||||
extern fn ___tracy_emit_memory_free_callstack(ptr: *const anyopaque, depth: c_int, secure: c_int) void;
|
||||
extern fn ___tracy_emit_memory_alloc_named(ptr: *const anyopaque, size: usize, secure: c_int, name: [*:0]const u8) void;
|
||||
extern fn ___tracy_emit_memory_alloc_callstack_named(ptr: *const anyopaque, size: usize, depth: c_int, secure: c_int, name: [*:0]const u8) void;
|
||||
extern fn ___tracy_emit_memory_free_named(ptr: *const anyopaque, secure: c_int, name: [*:0]const u8) void;
|
||||
extern fn ___tracy_emit_memory_free_callstack_named(ptr: *const anyopaque, depth: c_int, secure: c_int, name: [*:0]const u8) void;
|
||||
extern fn ___tracy_emit_message(txt: [*]const u8, size: usize, callstack: c_int) void;
|
||||
extern fn ___tracy_emit_messageL(txt: [*:0]const u8, callstack: c_int) void;
|
||||
extern fn ___tracy_emit_messageC(txt: [*]const u8, size: usize, color: u32, callstack: c_int) void;
|
||||
extern fn ___tracy_emit_messageLC(txt: [*:0]const u8, color: u32, callstack: c_int) void;
|
||||
extern fn ___tracy_emit_frame_mark(name: ?[*:0]const u8) void;
|
||||
|
||||
const ___tracy_source_location_data = extern struct {
|
||||
name: ?[*:0]const u8,
|
||||
function: [*:0]const u8,
|
||||
file: [*:0]const u8,
|
||||
line: u32,
|
||||
color: u32,
|
||||
};
|
||||
13
deps/aro/backend.zig
vendored
Normal file
13
deps/aro/backend.zig
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
pub const Interner = @import("backend/Interner.zig");
|
||||
pub const Ir = @import("backend/Ir.zig");
|
||||
pub const Object = @import("backend/Object.zig");
|
||||
|
||||
pub const CallingConvention = enum {
|
||||
C,
|
||||
stdcall,
|
||||
thiscall,
|
||||
vectorcall,
|
||||
};
|
||||
|
||||
pub const version_str = @import("build_options").version_str;
|
||||
pub const version = @import("std").SemanticVersion.parse(version_str) catch unreachable;
|
||||
647
deps/aro/backend/Interner.zig
vendored
Normal file
647
deps/aro/backend/Interner.zig
vendored
Normal file
@ -0,0 +1,647 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const BigIntConst = std.math.big.int.Const;
|
||||
const BigIntMutable = std.math.big.int.Mutable;
|
||||
const Hash = std.hash.Wyhash;
|
||||
const Limb = std.math.big.Limb;
|
||||
|
||||
const Interner = @This();
|
||||
|
||||
map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
|
||||
items: std.MultiArrayList(struct {
|
||||
tag: Tag,
|
||||
data: u32,
|
||||
}) = .{},
|
||||
extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
limbs: std.ArrayListUnmanaged(Limb) = .{},
|
||||
strings: std.ArrayListUnmanaged(u8) = .{},
|
||||
|
||||
const KeyAdapter = struct {
|
||||
interner: *const Interner,
|
||||
|
||||
pub fn eql(adapter: KeyAdapter, a: Key, b_void: void, b_map_index: usize) bool {
|
||||
_ = b_void;
|
||||
return adapter.interner.get(@as(Ref, @enumFromInt(b_map_index))).eql(a);
|
||||
}
|
||||
|
||||
pub fn hash(adapter: KeyAdapter, a: Key) u32 {
|
||||
_ = adapter;
|
||||
return a.hash();
|
||||
}
|
||||
};
|
||||
|
||||
pub const Key = union(enum) {
|
||||
int_ty: u16,
|
||||
float_ty: u16,
|
||||
ptr_ty,
|
||||
noreturn_ty,
|
||||
void_ty,
|
||||
func_ty,
|
||||
array_ty: struct {
|
||||
len: u64,
|
||||
child: Ref,
|
||||
},
|
||||
vector_ty: struct {
|
||||
len: u32,
|
||||
child: Ref,
|
||||
},
|
||||
record_ty: []const Ref,
|
||||
/// May not be zero
|
||||
null,
|
||||
int: union(enum) {
|
||||
u64: u64,
|
||||
i64: i64,
|
||||
big_int: BigIntConst,
|
||||
|
||||
pub fn toBigInt(repr: @This(), space: *Tag.Int.BigIntSpace) BigIntConst {
|
||||
return switch (repr) {
|
||||
.big_int => |x| x,
|
||||
inline .u64, .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),
|
||||
};
|
||||
}
|
||||
},
|
||||
float: Float,
|
||||
bytes: []const u8,
|
||||
|
||||
pub const Float = union(enum) {
|
||||
f16: f16,
|
||||
f32: f32,
|
||||
f64: f64,
|
||||
f80: f80,
|
||||
f128: f128,
|
||||
};
|
||||
|
||||
pub fn hash(key: Key) u32 {
|
||||
var hasher = Hash.init(0);
|
||||
const tag = std.meta.activeTag(key);
|
||||
std.hash.autoHash(&hasher, tag);
|
||||
switch (key) {
|
||||
.bytes => |bytes| {
|
||||
hasher.update(bytes);
|
||||
},
|
||||
.record_ty => |elems| for (elems) |elem| {
|
||||
std.hash.autoHash(&hasher, elem);
|
||||
},
|
||||
.float => |repr| switch (repr) {
|
||||
inline else => |data| std.hash.autoHash(
|
||||
&hasher,
|
||||
@as(std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(data))), @bitCast(data)),
|
||||
),
|
||||
},
|
||||
.int => |repr| {
|
||||
var space: Tag.Int.BigIntSpace = undefined;
|
||||
const big = repr.toBigInt(&space);
|
||||
std.hash.autoHash(&hasher, big.positive);
|
||||
for (big.limbs) |limb| std.hash.autoHash(&hasher, limb);
|
||||
},
|
||||
inline else => |info| {
|
||||
std.hash.autoHash(&hasher, info);
|
||||
},
|
||||
}
|
||||
return @truncate(hasher.final());
|
||||
}
|
||||
|
||||
pub fn eql(a: Key, b: Key) bool {
|
||||
const KeyTag = std.meta.Tag(Key);
|
||||
const a_tag: KeyTag = a;
|
||||
const b_tag: KeyTag = b;
|
||||
if (a_tag != b_tag) return false;
|
||||
switch (a) {
|
||||
.record_ty => |a_elems| {
|
||||
const b_elems = b.record_ty;
|
||||
if (a_elems.len != b_elems.len) return false;
|
||||
for (a_elems, b_elems) |a_elem, b_elem| {
|
||||
if (a_elem != b_elem) return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
.bytes => |a_bytes| {
|
||||
const b_bytes = b.bytes;
|
||||
return std.mem.eql(u8, a_bytes, b_bytes);
|
||||
},
|
||||
.int => |a_repr| {
|
||||
var a_space: Tag.Int.BigIntSpace = undefined;
|
||||
const a_big = a_repr.toBigInt(&a_space);
|
||||
var b_space: Tag.Int.BigIntSpace = undefined;
|
||||
const b_big = b.int.toBigInt(&b_space);
|
||||
|
||||
return a_big.eql(b_big);
|
||||
},
|
||||
inline else => |a_info, tag| {
|
||||
const b_info = @field(b, @tagName(tag));
|
||||
return std.meta.eql(a_info, b_info);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn toRef(key: Key) ?Ref {
|
||||
switch (key) {
|
||||
.int_ty => |bits| switch (bits) {
|
||||
1 => return .i1,
|
||||
8 => return .i8,
|
||||
16 => return .i16,
|
||||
32 => return .i32,
|
||||
64 => return .i64,
|
||||
128 => return .i128,
|
||||
else => {},
|
||||
},
|
||||
.float_ty => |bits| switch (bits) {
|
||||
16 => return .f16,
|
||||
32 => return .f32,
|
||||
64 => return .f64,
|
||||
80 => return .f80,
|
||||
128 => return .f128,
|
||||
else => unreachable,
|
||||
},
|
||||
.ptr_ty => return .ptr,
|
||||
.func_ty => return .func,
|
||||
.noreturn_ty => return .noreturn,
|
||||
.void_ty => return .void,
|
||||
.int => |repr| {
|
||||
var space: Tag.Int.BigIntSpace = undefined;
|
||||
const big = repr.toBigInt(&space);
|
||||
if (big.eqlZero()) return .zero;
|
||||
const big_one = BigIntConst{ .limbs = &.{1}, .positive = true };
|
||||
if (big.eql(big_one)) return .one;
|
||||
},
|
||||
.float => |repr| switch (repr) {
|
||||
inline else => |data| {
|
||||
if (std.math.isPositiveZero(data)) return .zero;
|
||||
if (data == 1) return .one;
|
||||
},
|
||||
},
|
||||
.null => return .null,
|
||||
else => {},
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Ref = enum(u32) {
|
||||
const max = std.math.maxInt(u32);
|
||||
|
||||
ptr = max - 1,
|
||||
noreturn = max - 2,
|
||||
void = max - 3,
|
||||
i1 = max - 4,
|
||||
i8 = max - 5,
|
||||
i16 = max - 6,
|
||||
i32 = max - 7,
|
||||
i64 = max - 8,
|
||||
i128 = max - 9,
|
||||
f16 = max - 10,
|
||||
f32 = max - 11,
|
||||
f64 = max - 12,
|
||||
f80 = max - 13,
|
||||
f128 = max - 14,
|
||||
func = max - 15,
|
||||
zero = max - 16,
|
||||
one = max - 17,
|
||||
null = max - 18,
|
||||
_,
|
||||
};
|
||||
|
||||
pub const OptRef = enum(u32) {
|
||||
const max = std.math.maxInt(u32);
|
||||
|
||||
none = max - 0,
|
||||
ptr = max - 1,
|
||||
noreturn = max - 2,
|
||||
void = max - 3,
|
||||
i1 = max - 4,
|
||||
i8 = max - 5,
|
||||
i16 = max - 6,
|
||||
i32 = max - 7,
|
||||
i64 = max - 8,
|
||||
i128 = max - 9,
|
||||
f16 = max - 10,
|
||||
f32 = max - 11,
|
||||
f64 = max - 12,
|
||||
f80 = max - 13,
|
||||
f128 = max - 14,
|
||||
func = max - 15,
|
||||
zero = max - 16,
|
||||
one = max - 17,
|
||||
null = max - 18,
|
||||
_,
|
||||
};
|
||||
|
||||
pub const Tag = enum(u8) {
|
||||
/// `data` is `u16`
|
||||
int_ty,
|
||||
/// `data` is `u16`
|
||||
float_ty,
|
||||
/// `data` is index to `Array`
|
||||
array_ty,
|
||||
/// `data` is index to `Vector`
|
||||
vector_ty,
|
||||
/// `data` is `u32`
|
||||
u32,
|
||||
/// `data` is `i32`
|
||||
i32,
|
||||
/// `data` is `Int`
|
||||
int_positive,
|
||||
/// `data` is `Int`
|
||||
int_negative,
|
||||
/// `data` is `f16`
|
||||
f16,
|
||||
/// `data` is `f32`
|
||||
f32,
|
||||
/// `data` is `F64`
|
||||
f64,
|
||||
/// `data` is `F80`
|
||||
f80,
|
||||
/// `data` is `F128`
|
||||
f128,
|
||||
/// `data` is `Bytes`
|
||||
bytes,
|
||||
/// `data` is `Record`
|
||||
record_ty,
|
||||
|
||||
pub const Array = struct {
|
||||
len0: u32,
|
||||
len1: u32,
|
||||
child: Ref,
|
||||
|
||||
pub fn getLen(a: Array) u64 {
|
||||
return (PackedU64{
|
||||
.a = a.len0,
|
||||
.b = a.len1,
|
||||
}).get();
|
||||
}
|
||||
};
|
||||
|
||||
pub const Vector = struct {
|
||||
len: u32,
|
||||
child: Ref,
|
||||
};
|
||||
|
||||
pub const Int = struct {
|
||||
limbs_index: u32,
|
||||
limbs_len: u32,
|
||||
|
||||
/// Big enough to fit any non-BigInt value
|
||||
pub const BigIntSpace = struct {
|
||||
/// The +1 is headroom so that operations such as incrementing once
|
||||
/// or decrementing once are possible without using an allocator.
|
||||
limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb,
|
||||
};
|
||||
};
|
||||
|
||||
pub const F64 = struct {
|
||||
piece0: u32,
|
||||
piece1: u32,
|
||||
|
||||
pub fn get(self: F64) f64 {
|
||||
const int_bits = @as(u64, self.piece0) | (@as(u64, self.piece1) << 32);
|
||||
return @bitCast(int_bits);
|
||||
}
|
||||
|
||||
fn pack(val: f64) F64 {
|
||||
const bits = @as(u64, @bitCast(val));
|
||||
return .{
|
||||
.piece0 = @as(u32, @truncate(bits)),
|
||||
.piece1 = @as(u32, @truncate(bits >> 32)),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const F80 = struct {
|
||||
piece0: u32,
|
||||
piece1: u32,
|
||||
piece2: u32, // u16 part, top bits
|
||||
|
||||
pub fn get(self: F80) f80 {
|
||||
const int_bits = @as(u80, self.piece0) |
|
||||
(@as(u80, self.piece1) << 32) |
|
||||
(@as(u80, self.piece2) << 64);
|
||||
return @bitCast(int_bits);
|
||||
}
|
||||
|
||||
fn pack(val: f80) F80 {
|
||||
const bits = @as(u80, @bitCast(val));
|
||||
return .{
|
||||
.piece0 = @as(u32, @truncate(bits)),
|
||||
.piece1 = @as(u32, @truncate(bits >> 32)),
|
||||
.piece2 = @as(u16, @truncate(bits >> 64)),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const F128 = struct {
|
||||
piece0: u32,
|
||||
piece1: u32,
|
||||
piece2: u32,
|
||||
piece3: u32,
|
||||
|
||||
pub fn get(self: F128) f128 {
|
||||
const int_bits = @as(u128, self.piece0) |
|
||||
(@as(u128, self.piece1) << 32) |
|
||||
(@as(u128, self.piece2) << 64) |
|
||||
(@as(u128, self.piece3) << 96);
|
||||
return @bitCast(int_bits);
|
||||
}
|
||||
|
||||
fn pack(val: f128) F128 {
|
||||
const bits = @as(u128, @bitCast(val));
|
||||
return .{
|
||||
.piece0 = @as(u32, @truncate(bits)),
|
||||
.piece1 = @as(u32, @truncate(bits >> 32)),
|
||||
.piece2 = @as(u32, @truncate(bits >> 64)),
|
||||
.piece3 = @as(u32, @truncate(bits >> 96)),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Bytes = struct {
|
||||
strings_index: u32,
|
||||
len: u32,
|
||||
};
|
||||
|
||||
pub const Record = struct {
|
||||
elements_len: u32,
|
||||
// trailing
|
||||
// [elements_len]Ref
|
||||
};
|
||||
};
|
||||
|
||||
pub const PackedU64 = packed struct(u64) {
|
||||
a: u32,
|
||||
b: u32,
|
||||
|
||||
pub fn get(x: PackedU64) u64 {
|
||||
return @bitCast(x);
|
||||
}
|
||||
|
||||
pub fn init(x: u64) PackedU64 {
|
||||
return @bitCast(x);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn deinit(i: *Interner, gpa: Allocator) void {
|
||||
i.map.deinit(gpa);
|
||||
i.items.deinit(gpa);
|
||||
i.extra.deinit(gpa);
|
||||
i.limbs.deinit(gpa);
|
||||
i.strings.deinit(gpa);
|
||||
}
|
||||
|
||||
pub fn put(i: *Interner, gpa: Allocator, key: Key) !Ref {
|
||||
if (key.toRef()) |some| return some;
|
||||
const adapter: KeyAdapter = .{ .interner = i };
|
||||
const gop = try i.map.getOrPutAdapted(gpa, key, adapter);
|
||||
if (gop.found_existing) return @enumFromInt(gop.index);
|
||||
try i.items.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
switch (key) {
|
||||
.int_ty => |bits| {
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .int_ty,
|
||||
.data = bits,
|
||||
});
|
||||
},
|
||||
.float_ty => |bits| {
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .float_ty,
|
||||
.data = bits,
|
||||
});
|
||||
},
|
||||
.array_ty => |info| {
|
||||
const split_len = PackedU64.init(info.len);
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .array_ty,
|
||||
.data = try i.addExtra(gpa, Tag.Array{
|
||||
.len0 = split_len.a,
|
||||
.len1 = split_len.b,
|
||||
.child = info.child,
|
||||
}),
|
||||
});
|
||||
},
|
||||
.vector_ty => |info| {
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .vector_ty,
|
||||
.data = try i.addExtra(gpa, Tag.Vector{
|
||||
.len = info.len,
|
||||
.child = info.child,
|
||||
}),
|
||||
});
|
||||
},
|
||||
.int => |repr| int: {
|
||||
var space: Tag.Int.BigIntSpace = undefined;
|
||||
const big = repr.toBigInt(&space);
|
||||
switch (repr) {
|
||||
.u64 => |data| if (std.math.cast(u32, data)) |small| {
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .u32,
|
||||
.data = small,
|
||||
});
|
||||
break :int;
|
||||
},
|
||||
.i64 => |data| if (std.math.cast(i32, data)) |small| {
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .i32,
|
||||
.data = @bitCast(small),
|
||||
});
|
||||
break :int;
|
||||
},
|
||||
.big_int => |data| {
|
||||
if (data.fitsInTwosComp(.unsigned, 32)) {
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .u32,
|
||||
.data = data.to(u32) catch unreachable,
|
||||
});
|
||||
break :int;
|
||||
} else if (data.fitsInTwosComp(.signed, 32)) {
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .i32,
|
||||
.data = @bitCast(data.to(i32) catch unreachable),
|
||||
});
|
||||
break :int;
|
||||
}
|
||||
},
|
||||
}
|
||||
const limbs_index: u32 = @intCast(i.limbs.items.len);
|
||||
try i.limbs.appendSlice(gpa, big.limbs);
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = if (big.positive) .int_positive else .int_negative,
|
||||
.data = try i.addExtra(gpa, Tag.Int{
|
||||
.limbs_index = limbs_index,
|
||||
.limbs_len = @intCast(big.limbs.len),
|
||||
}),
|
||||
});
|
||||
},
|
||||
.float => |repr| switch (repr) {
|
||||
.f16 => |data| i.items.appendAssumeCapacity(.{
|
||||
.tag = .f16,
|
||||
.data = @as(u16, @bitCast(data)),
|
||||
}),
|
||||
.f32 => |data| i.items.appendAssumeCapacity(.{
|
||||
.tag = .f32,
|
||||
.data = @as(u32, @bitCast(data)),
|
||||
}),
|
||||
.f64 => |data| i.items.appendAssumeCapacity(.{
|
||||
.tag = .f64,
|
||||
.data = try i.addExtra(gpa, Tag.F64.pack(data)),
|
||||
}),
|
||||
.f80 => |data| i.items.appendAssumeCapacity(.{
|
||||
.tag = .f64,
|
||||
.data = try i.addExtra(gpa, Tag.F80.pack(data)),
|
||||
}),
|
||||
.f128 => |data| i.items.appendAssumeCapacity(.{
|
||||
.tag = .f64,
|
||||
.data = try i.addExtra(gpa, Tag.F128.pack(data)),
|
||||
}),
|
||||
},
|
||||
.bytes => |bytes| {
|
||||
const strings_index: u32 = @intCast(i.strings.items.len);
|
||||
try i.strings.appendSlice(gpa, bytes);
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .bytes,
|
||||
.data = try i.addExtra(gpa, Tag.Bytes{
|
||||
.strings_index = strings_index,
|
||||
.len = @intCast(bytes.len),
|
||||
}),
|
||||
});
|
||||
},
|
||||
.record_ty => |elems| {
|
||||
try i.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.Record).Struct.fields.len +
|
||||
elems.len);
|
||||
i.items.appendAssumeCapacity(.{
|
||||
.tag = .record_ty,
|
||||
.data = i.addExtraAssumeCapacity(Tag.Record{
|
||||
.elements_len = @intCast(elems.len),
|
||||
}),
|
||||
});
|
||||
i.extra.appendSliceAssumeCapacity(@ptrCast(elems));
|
||||
},
|
||||
.ptr_ty,
|
||||
.noreturn_ty,
|
||||
.void_ty,
|
||||
.func_ty,
|
||||
.null,
|
||||
=> unreachable,
|
||||
}
|
||||
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn addExtra(i: *Interner, gpa: Allocator, extra: anytype) Allocator.Error!u32 {
|
||||
const fields = @typeInfo(@TypeOf(extra)).Struct.fields;
|
||||
try i.extra.ensureUnusedCapacity(gpa, fields.len);
|
||||
return i.addExtraAssumeCapacity(extra);
|
||||
}
|
||||
|
||||
fn addExtraAssumeCapacity(i: *Interner, extra: anytype) u32 {
|
||||
const result = @as(u32, @intCast(i.extra.items.len));
|
||||
inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| {
|
||||
i.extra.appendAssumeCapacity(switch (field.type) {
|
||||
Ref => @intFromEnum(@field(extra, field.name)),
|
||||
u32 => @field(extra, field.name),
|
||||
else => @compileError("bad field type: " ++ @typeName(field.type)),
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn get(i: *const Interner, ref: Ref) Key {
|
||||
switch (ref) {
|
||||
.ptr => return .ptr_ty,
|
||||
.func => return .func_ty,
|
||||
.noreturn => return .noreturn_ty,
|
||||
.void => return .void_ty,
|
||||
.i1 => return .{ .int_ty = 1 },
|
||||
.i8 => return .{ .int_ty = 8 },
|
||||
.i16 => return .{ .int_ty = 16 },
|
||||
.i32 => return .{ .int_ty = 32 },
|
||||
.i64 => return .{ .int_ty = 64 },
|
||||
.i128 => return .{ .int_ty = 128 },
|
||||
.f16 => return .{ .float_ty = 16 },
|
||||
.f32 => return .{ .float_ty = 32 },
|
||||
.f64 => return .{ .float_ty = 64 },
|
||||
.f80 => return .{ .float_ty = 80 },
|
||||
.f128 => return .{ .float_ty = 128 },
|
||||
.zero => return .{ .int = .{ .u64 = 0 } },
|
||||
.one => return .{ .int = .{ .u64 = 1 } },
|
||||
.null => return .null,
|
||||
else => {},
|
||||
}
|
||||
|
||||
const item = i.items.get(@intFromEnum(ref));
|
||||
const data = item.data;
|
||||
return switch (item.tag) {
|
||||
.int_ty => .{ .int_ty = @intCast(data) },
|
||||
.float_ty => .{ .float_ty = @intCast(data) },
|
||||
.array_ty => {
|
||||
const array_ty = i.extraData(Tag.Array, data);
|
||||
return .{ .array_ty = .{
|
||||
.len = array_ty.getLen(),
|
||||
.child = array_ty.child,
|
||||
} };
|
||||
},
|
||||
.vector_ty => {
|
||||
const vector_ty = i.extraData(Tag.Vector, data);
|
||||
return .{ .vector_ty = .{
|
||||
.len = vector_ty.len,
|
||||
.child = vector_ty.child,
|
||||
} };
|
||||
},
|
||||
.u32 => .{ .int = .{ .u64 = data } },
|
||||
.i32 => .{ .int = .{ .i64 = @as(i32, @bitCast(data)) } },
|
||||
.int_positive, .int_negative => {
|
||||
const int_info = i.extraData(Tag.Int, data);
|
||||
const limbs = i.limbs.items[int_info.limbs_index..][0..int_info.limbs_len];
|
||||
return .{ .int = .{
|
||||
.big_int = .{
|
||||
.positive = item.tag == .int_positive,
|
||||
.limbs = limbs,
|
||||
},
|
||||
} };
|
||||
},
|
||||
.f16 => .{ .float = .{ .f16 = @bitCast(@as(u16, @intCast(data))) } },
|
||||
.f32 => .{ .float = .{ .f32 = @bitCast(data) } },
|
||||
.f64 => {
|
||||
const float = i.extraData(Tag.F64, data);
|
||||
return .{ .float = .{ .f64 = float.get() } };
|
||||
},
|
||||
.f80 => {
|
||||
const float = i.extraData(Tag.F80, data);
|
||||
return .{ .float = .{ .f80 = float.get() } };
|
||||
},
|
||||
.f128 => {
|
||||
const float = i.extraData(Tag.F128, data);
|
||||
return .{ .float = .{ .f128 = float.get() } };
|
||||
},
|
||||
.bytes => {
|
||||
const bytes = i.extraData(Tag.Bytes, data);
|
||||
return .{ .bytes = i.strings.items[bytes.strings_index..][0..bytes.len] };
|
||||
},
|
||||
.record_ty => {
|
||||
const extra = i.extraDataTrail(Tag.Record, data);
|
||||
return .{
|
||||
.record_ty = @ptrCast(i.extra.items[extra.end..][0..extra.data.elements_len]),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn extraData(i: *const Interner, comptime T: type, index: usize) T {
|
||||
return i.extraDataTrail(T, index).data;
|
||||
}
|
||||
|
||||
fn extraDataTrail(i: *const Interner, comptime T: type, index: usize) struct { data: T, end: u32 } {
|
||||
var result: T = undefined;
|
||||
const fields = @typeInfo(T).Struct.fields;
|
||||
inline for (fields, 0..) |field, field_i| {
|
||||
const int32 = i.extra.items[field_i + index];
|
||||
@field(result, field.name) = switch (field.type) {
|
||||
Ref => @enumFromInt(int32),
|
||||
u32 => int32,
|
||||
else => @compileError("bad field type: " ++ @typeName(field.type)),
|
||||
};
|
||||
}
|
||||
return .{
|
||||
.data = result,
|
||||
.end = @intCast(index + fields.len),
|
||||
};
|
||||
}
|
||||
385
deps/aro/Ir.zig → deps/aro/backend/Ir.zig
vendored
385
deps/aro/Ir.zig → deps/aro/backend/Ir.zig
vendored
@ -1,51 +1,79 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const assert = std.debug.assert;
|
||||
const Interner = @import("Interner.zig");
|
||||
const StringId = @import("StringInterner.zig").StringId;
|
||||
const Value = @import("Value.zig");
|
||||
const Object = @import("Object.zig");
|
||||
|
||||
const Ir = @This();
|
||||
|
||||
pool: Interner,
|
||||
strings: []const u8,
|
||||
// decls: std.StringArrayHashMapUnmanaged(Decl),
|
||||
interner: *Interner,
|
||||
decls: std.StringArrayHashMapUnmanaged(Decl),
|
||||
|
||||
// pub const Decl = struct {
|
||||
pub const Decl = struct {
|
||||
instructions: std.MultiArrayList(Inst),
|
||||
body: std.ArrayListUnmanaged(Ref),
|
||||
arena: std.heap.ArenaAllocator.State,
|
||||
// };
|
||||
|
||||
pub fn deinit(decl: *Decl, gpa: Allocator) void {
|
||||
decl.instructions.deinit(gpa);
|
||||
decl.body.deinit(gpa);
|
||||
decl.arena.promote(gpa).deinit();
|
||||
}
|
||||
};
|
||||
|
||||
pub const Builder = struct {
|
||||
gpa: Allocator,
|
||||
arena: std.heap.ArenaAllocator,
|
||||
interner: *Interner,
|
||||
|
||||
decls: std.StringArrayHashMapUnmanaged(Decl) = .{},
|
||||
instructions: std.MultiArrayList(Ir.Inst) = .{},
|
||||
body: std.ArrayListUnmanaged(Ref) = .{},
|
||||
alloc_count: u32 = 0,
|
||||
arg_count: u32 = 0,
|
||||
pool: Interner = .{},
|
||||
current_label: Ref = undefined,
|
||||
|
||||
pub fn deinit(b: *Builder) void {
|
||||
for (b.decls.values()) |*decl| {
|
||||
decl.deinit(b.gpa);
|
||||
}
|
||||
b.arena.deinit();
|
||||
b.instructions.deinit(b.gpa);
|
||||
b.body.deinit(b.gpa);
|
||||
b.pool.deinit(b.gpa);
|
||||
b.* = undefined;
|
||||
}
|
||||
|
||||
pub fn finish(b: *Builder) Ir {
|
||||
return .{
|
||||
.interner = b.interner,
|
||||
.decls = b.decls.move(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn startFn(b: *Builder) Allocator.Error!void {
|
||||
b.alloc_count = 0;
|
||||
b.arg_count = 0;
|
||||
b.instructions.len = 0;
|
||||
b.body.items.len = 0;
|
||||
const entry = try b.makeLabel("entry");
|
||||
try b.body.append(b.gpa, entry);
|
||||
b.current_label = entry;
|
||||
}
|
||||
|
||||
pub fn finishFn(b: *Builder, name: []const u8) !void {
|
||||
var duped_instructions = try b.instructions.clone(b.gpa);
|
||||
errdefer duped_instructions.deinit(b.gpa);
|
||||
var duped_body = try b.body.clone(b.gpa);
|
||||
errdefer duped_body.deinit(b.gpa);
|
||||
|
||||
try b.decls.put(b.gpa, name, .{
|
||||
.instructions = duped_instructions,
|
||||
.body = duped_body,
|
||||
.arena = b.arena.state,
|
||||
});
|
||||
b.instructions.shrinkRetainingCapacity(0);
|
||||
b.body.shrinkRetainingCapacity(0);
|
||||
b.arena = std.heap.ArenaAllocator.init(b.gpa);
|
||||
b.alloc_count = 0;
|
||||
b.arg_count = 0;
|
||||
}
|
||||
|
||||
pub fn startBlock(b: *Builder, label: Ref) !void {
|
||||
try b.body.append(b.gpa, label);
|
||||
b.current_label = label;
|
||||
@ -116,15 +144,13 @@ pub const Builder = struct {
|
||||
_ = try b.addInst(.store, .{ .bin = .{ .lhs = ptr, .rhs = val } }, .void);
|
||||
}
|
||||
|
||||
pub fn addConstant(b: *Builder, val: Value, ty: Interner.Ref) Allocator.Error!Ref {
|
||||
pub fn addConstant(b: *Builder, val: Interner.Ref, ty: Interner.Ref) Allocator.Error!Ref {
|
||||
const ref: Ref = @enumFromInt(b.instructions.len);
|
||||
const key: Interner.Key = .{
|
||||
.value = val,
|
||||
};
|
||||
const val_ref = try b.pool.put(b.gpa, key);
|
||||
try b.instructions.append(b.gpa, .{ .tag = .constant, .data = .{
|
||||
.constant = val_ref,
|
||||
}, .ty = ty });
|
||||
try b.instructions.append(b.gpa, .{
|
||||
.tag = .constant,
|
||||
.data = .{ .constant = val },
|
||||
.ty = ty,
|
||||
});
|
||||
return ref;
|
||||
}
|
||||
|
||||
@ -148,6 +174,65 @@ pub const Builder = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const Renderer = struct {
|
||||
gpa: Allocator,
|
||||
obj: *Object,
|
||||
ir: *const Ir,
|
||||
errors: ErrorList = .{},
|
||||
|
||||
pub const ErrorList = std.StringArrayHashMapUnmanaged([]const u8);
|
||||
|
||||
pub const Error = Allocator.Error || error{LowerFail};
|
||||
|
||||
pub fn deinit(r: *Renderer) void {
|
||||
for (r.errors.values()) |msg| r.gpa.free(msg);
|
||||
r.errors.deinit(r.gpa);
|
||||
}
|
||||
|
||||
pub fn render(r: *Renderer) !void {
|
||||
switch (r.obj.target.cpu.arch) {
|
||||
.x86, .x86_64 => return @import("Ir/x86/Renderer.zig").render(r),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fail(
|
||||
r: *Renderer,
|
||||
name: []const u8,
|
||||
comptime format: []const u8,
|
||||
args: anytype,
|
||||
) Error {
|
||||
try r.errors.ensureUnusedCapacity(r.gpa, 1);
|
||||
r.errors.putAssumeCapacity(name, try std.fmt.allocPrint(r.gpa, format, args));
|
||||
return error.LowerFail;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn render(
|
||||
ir: *const Ir,
|
||||
gpa: Allocator,
|
||||
target: std.Target,
|
||||
errors: ?*Renderer.ErrorList,
|
||||
) !*Object {
|
||||
const obj = try Object.create(gpa, target);
|
||||
errdefer obj.deinit();
|
||||
|
||||
var renderer: Renderer = .{
|
||||
.gpa = gpa,
|
||||
.obj = obj,
|
||||
.ir = ir,
|
||||
};
|
||||
defer {
|
||||
if (errors) |some| {
|
||||
some.* = renderer.errors.move();
|
||||
}
|
||||
renderer.deinit();
|
||||
}
|
||||
|
||||
try renderer.render();
|
||||
return obj;
|
||||
}
|
||||
|
||||
pub const Ref = enum(u32) { none = std.math.maxInt(u32), _ };
|
||||
|
||||
pub const Inst = struct {
|
||||
@ -281,23 +366,30 @@ pub const Inst = struct {
|
||||
};
|
||||
|
||||
pub fn deinit(ir: *Ir, gpa: std.mem.Allocator) void {
|
||||
ir.arena.promote(gpa).deinit();
|
||||
ir.instructions.deinit(gpa);
|
||||
for (ir.decls.values()) |*decl| {
|
||||
decl.deinit(gpa);
|
||||
}
|
||||
ir.decls.deinit(gpa);
|
||||
ir.* = undefined;
|
||||
}
|
||||
|
||||
const util = @import("util.zig");
|
||||
const TYPE = util.Color.purple;
|
||||
const INST = util.Color.cyan;
|
||||
const REF = util.Color.blue;
|
||||
const LITERAL = util.Color.green;
|
||||
const ATTRIBUTE = util.Color.yellow;
|
||||
const TYPE = std.io.tty.Color.bright_magenta;
|
||||
const INST = std.io.tty.Color.bright_cyan;
|
||||
const REF = std.io.tty.Color.bright_blue;
|
||||
const LITERAL = std.io.tty.Color.bright_green;
|
||||
const ATTRIBUTE = std.io.tty.Color.bright_yellow;
|
||||
|
||||
const RefMap = std.AutoArrayHashMap(Ref, void);
|
||||
|
||||
pub fn dump(ir: Ir, gpa: Allocator, name: []const u8, color: bool, w: anytype) !void {
|
||||
const tags = ir.instructions.items(.tag);
|
||||
const data = ir.instructions.items(.data);
|
||||
pub fn dump(ir: *const Ir, gpa: Allocator, config: std.io.tty.Config, w: anytype) !void {
|
||||
for (ir.decls.keys(), ir.decls.values()) |name, *decl| {
|
||||
try ir.dumpDecl(decl, gpa, name, config, w);
|
||||
}
|
||||
}
|
||||
|
||||
fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8, config: std.io.tty.Config, w: anytype) !void {
|
||||
const tags = decl.instructions.items(.tag);
|
||||
const data = decl.instructions.items(.data);
|
||||
|
||||
var ref_map = RefMap.init(gpa);
|
||||
defer ref_map.deinit();
|
||||
@ -305,40 +397,40 @@ pub fn dump(ir: Ir, gpa: Allocator, name: []const u8, color: bool, w: anytype) !
|
||||
var label_map = RefMap.init(gpa);
|
||||
defer label_map.deinit();
|
||||
|
||||
const ret_inst = ir.body.items[ir.body.items.len - 1];
|
||||
const ret_inst = decl.body.items[decl.body.items.len - 1];
|
||||
const ret_operand = data[@intFromEnum(ret_inst)].un;
|
||||
const ret_ty = ir.instructions.items(.ty)[@intFromEnum(ret_operand)];
|
||||
try ir.writeType(ret_ty, color, w);
|
||||
if (color) util.setColor(REF, w);
|
||||
const ret_ty = decl.instructions.items(.ty)[@intFromEnum(ret_operand)];
|
||||
try ir.writeType(ret_ty, config, w);
|
||||
try config.setColor(w, REF);
|
||||
try w.print(" @{s}", .{name});
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll("(");
|
||||
|
||||
var arg_count: u32 = 0;
|
||||
while (true) : (arg_count += 1) {
|
||||
const ref = ir.body.items[arg_count];
|
||||
const ref = decl.body.items[arg_count];
|
||||
if (tags[@intFromEnum(ref)] != .arg) break;
|
||||
if (arg_count != 0) try w.writeAll(", ");
|
||||
try ref_map.put(ref, {});
|
||||
try ir.writeRef(&ref_map, ref, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, ref, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
try w.writeAll(") {\n");
|
||||
for (ir.body.items[arg_count..]) |ref| {
|
||||
for (decl.body.items[arg_count..]) |ref| {
|
||||
switch (tags[@intFromEnum(ref)]) {
|
||||
.label => try label_map.put(ref, {}),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
for (ir.body.items[arg_count..]) |ref| {
|
||||
for (decl.body.items[arg_count..]) |ref| {
|
||||
const i = @intFromEnum(ref);
|
||||
const tag = tags[i];
|
||||
switch (tag) {
|
||||
.arg, .constant, .symbol => unreachable,
|
||||
.label => {
|
||||
const label_index = label_map.getIndex(ref).?;
|
||||
if (color) util.setColor(REF, w);
|
||||
try config.setColor(w, REF);
|
||||
try w.print("{s}.{d}:\n", .{ data[i].label, label_index });
|
||||
},
|
||||
// .label_val => {
|
||||
@ -347,35 +439,35 @@ pub fn dump(ir: Ir, gpa: Allocator, name: []const u8, color: bool, w: anytype) !
|
||||
// },
|
||||
.jmp => {
|
||||
const un = data[i].un;
|
||||
if (color) util.setColor(INST, w);
|
||||
try config.setColor(w, INST);
|
||||
try w.writeAll(" jmp ");
|
||||
try ir.writeLabel(&label_map, un, color, w);
|
||||
try writeLabel(decl, &label_map, un, config, w);
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
.branch => {
|
||||
const br = data[i].branch;
|
||||
if (color) util.setColor(INST, w);
|
||||
try config.setColor(w, INST);
|
||||
try w.writeAll(" branch ");
|
||||
try ir.writeRef(&ref_map, br.cond, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, br.cond, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(", ");
|
||||
try ir.writeLabel(&label_map, br.then, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try writeLabel(decl, &label_map, br.then, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(", ");
|
||||
try ir.writeLabel(&label_map, br.@"else", color, w);
|
||||
try writeLabel(decl, &label_map, br.@"else", config, w);
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
.select => {
|
||||
const br = data[i].branch;
|
||||
try ir.writeNewRef(&ref_map, ref, color, w);
|
||||
try ir.writeNewRef(decl, &ref_map, ref, config, w);
|
||||
try w.writeAll("select ");
|
||||
try ir.writeRef(&ref_map, br.cond, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, br.cond, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(", ");
|
||||
try ir.writeRef(&ref_map, br.then, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, br.then, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(", ");
|
||||
try ir.writeRef(&ref_map, br.@"else", color, w);
|
||||
try ir.writeRef(decl, &ref_map, br.@"else", config, w);
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
// .jmp_val => {
|
||||
@ -384,91 +476,91 @@ pub fn dump(ir: Ir, gpa: Allocator, name: []const u8, color: bool, w: anytype) !
|
||||
// },
|
||||
.@"switch" => {
|
||||
const @"switch" = data[i].@"switch";
|
||||
if (color) util.setColor(INST, w);
|
||||
try config.setColor(w, INST);
|
||||
try w.writeAll(" switch ");
|
||||
try ir.writeRef(&ref_map, @"switch".target, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, @"switch".target, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(" {");
|
||||
for (@"switch".case_vals[0..@"switch".cases_len], @"switch".case_labels) |val_ref, label_ref| {
|
||||
try w.writeAll("\n ");
|
||||
try ir.writeValue(val_ref, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeValue(val_ref, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(" => ");
|
||||
try ir.writeLabel(&label_map, label_ref, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try writeLabel(decl, &label_map, label_ref, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
if (color) util.setColor(LITERAL, w);
|
||||
try config.setColor(w, LITERAL);
|
||||
try w.writeAll("\n default ");
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll("=> ");
|
||||
try ir.writeLabel(&label_map, @"switch".default, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try writeLabel(decl, &label_map, @"switch".default, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll("\n }\n");
|
||||
},
|
||||
.call => {
|
||||
const call = data[i].call;
|
||||
try ir.writeNewRef(&ref_map, ref, color, w);
|
||||
try ir.writeNewRef(decl, &ref_map, ref, config, w);
|
||||
try w.writeAll("call ");
|
||||
try ir.writeRef(&ref_map, call.func, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, call.func, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll("(");
|
||||
for (call.args(), 0..) |arg, arg_i| {
|
||||
if (arg_i != 0) try w.writeAll(", ");
|
||||
try ir.writeRef(&ref_map, arg, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, arg, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
try w.writeAll(")\n");
|
||||
},
|
||||
.alloc => {
|
||||
const alloc = data[i].alloc;
|
||||
try ir.writeNewRef(&ref_map, ref, color, w);
|
||||
try ir.writeNewRef(decl, &ref_map, ref, config, w);
|
||||
try w.writeAll("alloc ");
|
||||
if (color) util.setColor(ATTRIBUTE, w);
|
||||
try config.setColor(w, ATTRIBUTE);
|
||||
try w.writeAll("size ");
|
||||
if (color) util.setColor(LITERAL, w);
|
||||
try config.setColor(w, LITERAL);
|
||||
try w.print("{d}", .{alloc.size});
|
||||
if (color) util.setColor(ATTRIBUTE, w);
|
||||
try config.setColor(w, ATTRIBUTE);
|
||||
try w.writeAll(" align ");
|
||||
if (color) util.setColor(LITERAL, w);
|
||||
try config.setColor(w, LITERAL);
|
||||
try w.print("{d}", .{alloc.@"align"});
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
.phi => {
|
||||
try ir.writeNewRef(&ref_map, ref, color, w);
|
||||
try ir.writeNewRef(decl, &ref_map, ref, config, w);
|
||||
try w.writeAll("phi");
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(" {");
|
||||
for (data[i].phi.inputs()) |input| {
|
||||
try w.writeAll("\n ");
|
||||
try ir.writeLabel(&label_map, input.label, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try writeLabel(decl, &label_map, input.label, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(" => ");
|
||||
try ir.writeRef(&ref_map, input.value, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, input.value, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
}
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll("\n }\n");
|
||||
},
|
||||
.store => {
|
||||
const bin = data[i].bin;
|
||||
if (color) util.setColor(INST, w);
|
||||
try config.setColor(w, INST);
|
||||
try w.writeAll(" store ");
|
||||
try ir.writeRef(&ref_map, bin.lhs, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, bin.lhs, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(", ");
|
||||
try ir.writeRef(&ref_map, bin.rhs, color, w);
|
||||
try ir.writeRef(decl, &ref_map, bin.rhs, config, w);
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
.ret => {
|
||||
if (color) util.setColor(INST, w);
|
||||
try config.setColor(w, INST);
|
||||
try w.writeAll(" ret ");
|
||||
if (data[i].un != .none) try ir.writeRef(&ref_map, data[i].un, color, w);
|
||||
if (data[i].un != .none) try ir.writeRef(decl, &ref_map, data[i].un, config, w);
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
.load => {
|
||||
try ir.writeNewRef(&ref_map, ref, color, w);
|
||||
try ir.writeNewRef(decl, &ref_map, ref, config, w);
|
||||
try w.writeAll("load ");
|
||||
try ir.writeRef(&ref_map, data[i].un, color, w);
|
||||
try ir.writeRef(decl, &ref_map, data[i].un, config, w);
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
.bit_or,
|
||||
@ -489,12 +581,12 @@ pub fn dump(ir: Ir, gpa: Allocator, name: []const u8, color: bool, w: anytype) !
|
||||
.mod,
|
||||
=> {
|
||||
const bin = data[i].bin;
|
||||
try ir.writeNewRef(&ref_map, ref, color, w);
|
||||
try ir.writeNewRef(decl, &ref_map, ref, config, w);
|
||||
try w.print("{s} ", .{@tagName(tag)});
|
||||
try ir.writeRef(&ref_map, bin.lhs, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, &ref_map, bin.lhs, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(", ");
|
||||
try ir.writeRef(&ref_map, bin.rhs, color, w);
|
||||
try ir.writeRef(decl, &ref_map, bin.rhs, config, w);
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
.bit_not,
|
||||
@ -504,98 +596,101 @@ pub fn dump(ir: Ir, gpa: Allocator, name: []const u8, color: bool, w: anytype) !
|
||||
.sext,
|
||||
=> {
|
||||
const un = data[i].un;
|
||||
try ir.writeNewRef(&ref_map, ref, color, w);
|
||||
try ir.writeNewRef(decl, &ref_map, ref, config, w);
|
||||
try w.print("{s} ", .{@tagName(tag)});
|
||||
try ir.writeRef(&ref_map, un, color, w);
|
||||
try ir.writeRef(decl, &ref_map, un, config, w);
|
||||
try w.writeByte('\n');
|
||||
},
|
||||
.label_addr, .jmp_val => {},
|
||||
}
|
||||
}
|
||||
if (color) util.setColor(.reset, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll("}\n\n");
|
||||
}
|
||||
|
||||
fn writeType(ir: Ir, ty_ref: Interner.Ref, color: bool, w: anytype) !void {
|
||||
const ty = ir.pool.get(ty_ref);
|
||||
if (color) util.setColor(TYPE, w);
|
||||
fn writeType(ir: Ir, ty_ref: Interner.Ref, config: std.io.tty.Config, w: anytype) !void {
|
||||
const ty = ir.interner.get(ty_ref);
|
||||
try config.setColor(w, TYPE);
|
||||
switch (ty) {
|
||||
.value => unreachable,
|
||||
.ptr, .noreturn, .void, .func => try w.writeAll(@tagName(ty)),
|
||||
.int => |bits| try w.print("i{d}", .{bits}),
|
||||
.float => |bits| try w.print("f{d}", .{bits}),
|
||||
.array => |info| {
|
||||
.ptr_ty, .noreturn_ty, .void_ty, .func_ty => try w.writeAll(@tagName(ty)),
|
||||
.int_ty => |bits| try w.print("i{d}", .{bits}),
|
||||
.float_ty => |bits| try w.print("f{d}", .{bits}),
|
||||
.array_ty => |info| {
|
||||
try w.print("[{d} * ", .{info.len});
|
||||
try ir.writeType(info.child, false, w);
|
||||
try ir.writeType(info.child, .no_color, w);
|
||||
try w.writeByte(']');
|
||||
},
|
||||
.vector => |info| {
|
||||
.vector_ty => |info| {
|
||||
try w.print("<{d} * ", .{info.len});
|
||||
try ir.writeType(info.child, false, w);
|
||||
try ir.writeType(info.child, .no_color, w);
|
||||
try w.writeByte('>');
|
||||
},
|
||||
.record => |info| {
|
||||
.record_ty => |elems| {
|
||||
// TODO collect into buffer and only print once
|
||||
try w.writeAll("{ ");
|
||||
for (info.elements, 0..) |elem, i| {
|
||||
for (elems, 0..) |elem, i| {
|
||||
if (i != 0) try w.writeAll(", ");
|
||||
try ir.writeType(elem, color, w);
|
||||
try ir.writeType(elem, config, w);
|
||||
}
|
||||
try w.writeAll(" }");
|
||||
},
|
||||
else => unreachable, // not a type
|
||||
}
|
||||
}
|
||||
|
||||
fn writeValue(ir: Ir, val_ref: Interner.Ref, color: bool, w: anytype) !void {
|
||||
const v = ir.pool.get(val_ref).value;
|
||||
if (color) util.setColor(LITERAL, w);
|
||||
switch (v.tag) {
|
||||
.unavailable => try w.writeAll(" unavailable"),
|
||||
.int => try w.print("{d}", .{v.data.int}),
|
||||
.bytes => try w.print("\"{s}\"", .{v.data.bytes.slice(ir.strings, .@"1")}),
|
||||
// std.fmt does @as instead of @floatCast
|
||||
.float => try w.print("{d}", .{@as(f64, @floatCast(v.data.float))}),
|
||||
else => try w.print("({s})", .{@tagName(v.tag)}),
|
||||
fn writeValue(ir: Ir, val: Interner.Ref, config: std.io.tty.Config, w: anytype) !void {
|
||||
try config.setColor(w, LITERAL);
|
||||
const key = ir.interner.get(val);
|
||||
switch (key) {
|
||||
.null => return w.writeAll("nullptr_t"),
|
||||
.int => |repr| switch (repr) {
|
||||
inline else => |x| return w.print("{d}", .{x}),
|
||||
},
|
||||
.float => |repr| switch (repr) {
|
||||
inline else => |x| return w.print("{d}", .{@as(f64, @floatCast(x))}),
|
||||
},
|
||||
.bytes => |b| return std.zig.fmt.stringEscape(b, "", .{}, w),
|
||||
else => unreachable, // not a value
|
||||
}
|
||||
}
|
||||
|
||||
fn writeRef(ir: Ir, ref_map: *RefMap, ref: Ref, color: bool, w: anytype) !void {
|
||||
fn writeRef(ir: Ir, decl: *const Decl, ref_map: *RefMap, ref: Ref, config: std.io.tty.Config, w: anytype) !void {
|
||||
assert(ref != .none);
|
||||
const index = @intFromEnum(ref);
|
||||
const ty_ref = ir.instructions.items(.ty)[index];
|
||||
if (ir.instructions.items(.tag)[index] == .constant) {
|
||||
try ir.writeType(ty_ref, color, w);
|
||||
const v_ref = ir.instructions.items(.data)[index].constant;
|
||||
const ty_ref = decl.instructions.items(.ty)[index];
|
||||
if (decl.instructions.items(.tag)[index] == .constant) {
|
||||
try ir.writeType(ty_ref, config, w);
|
||||
const v_ref = decl.instructions.items(.data)[index].constant;
|
||||
try w.writeByte(' ');
|
||||
try ir.writeValue(v_ref, color, w);
|
||||
try ir.writeValue(v_ref, config, w);
|
||||
return;
|
||||
} else if (ir.instructions.items(.tag)[index] == .symbol) {
|
||||
const name = ir.instructions.items(.data)[index].label;
|
||||
try ir.writeType(ty_ref, color, w);
|
||||
if (color) util.setColor(REF, w);
|
||||
} else if (decl.instructions.items(.tag)[index] == .symbol) {
|
||||
const name = decl.instructions.items(.data)[index].label;
|
||||
try ir.writeType(ty_ref, config, w);
|
||||
try config.setColor(w, REF);
|
||||
try w.print(" @{s}", .{name});
|
||||
return;
|
||||
}
|
||||
try ir.writeType(ty_ref, color, w);
|
||||
if (color) util.setColor(REF, w);
|
||||
try ir.writeType(ty_ref, config, w);
|
||||
try config.setColor(w, REF);
|
||||
const ref_index = ref_map.getIndex(ref).?;
|
||||
try w.print(" %{d}", .{ref_index});
|
||||
}
|
||||
|
||||
fn writeNewRef(ir: Ir, ref_map: *RefMap, ref: Ref, color: bool, w: anytype) !void {
|
||||
fn writeNewRef(ir: Ir, decl: *const Decl, ref_map: *RefMap, ref: Ref, config: std.io.tty.Config, w: anytype) !void {
|
||||
try ref_map.put(ref, {});
|
||||
try w.writeAll(" ");
|
||||
try ir.writeRef(ref_map, ref, color, w);
|
||||
if (color) util.setColor(.reset, w);
|
||||
try ir.writeRef(decl, ref_map, ref, config, w);
|
||||
try config.setColor(w, .reset);
|
||||
try w.writeAll(" = ");
|
||||
if (color) util.setColor(INST, w);
|
||||
try config.setColor(w, INST);
|
||||
}
|
||||
|
||||
fn writeLabel(ir: Ir, label_map: *RefMap, ref: Ref, color: bool, w: anytype) !void {
|
||||
fn writeLabel(decl: *const Decl, label_map: *RefMap, ref: Ref, config: std.io.tty.Config, w: anytype) !void {
|
||||
assert(ref != .none);
|
||||
const index = @intFromEnum(ref);
|
||||
const label = ir.instructions.items(.data)[index].label;
|
||||
if (color) util.setColor(REF, w);
|
||||
const label = decl.instructions.items(.data)[index].label;
|
||||
try config.setColor(w, REF);
|
||||
const label_index = label_map.getIndex(ref).?;
|
||||
try w.print("{s}.{d}", .{ label, label_index });
|
||||
}
|
||||
65
deps/aro/backend/Ir/x86/Renderer.zig
vendored
Normal file
65
deps/aro/backend/Ir/x86/Renderer.zig
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const Interner = @import("../../Interner.zig");
|
||||
const Ir = @import("../../Ir.zig");
|
||||
const BaseRenderer = Ir.Renderer;
|
||||
const zig = @import("zig");
|
||||
const abi = zig.arch.x86_64.abi;
|
||||
const bits = zig.arch.x86_64.bits;
|
||||
|
||||
const Condition = bits.Condition;
|
||||
const Immediate = bits.Immediate;
|
||||
const Memory = bits.Memory;
|
||||
const Register = bits.Register;
|
||||
const RegisterLock = RegisterManager.RegisterLock;
|
||||
const FrameIndex = bits.FrameIndex;
|
||||
|
||||
const RegisterManager = zig.RegisterManager(Renderer, Register, Ir.Ref, abi.allocatable_regs);
|
||||
|
||||
// Register classes
|
||||
const RegisterBitSet = RegisterManager.RegisterBitSet;
|
||||
const RegisterClass = struct {
|
||||
const gp: RegisterBitSet = blk: {
|
||||
var set = RegisterBitSet.initEmpty();
|
||||
for (abi.allocatable_regs, 0..) |reg, index| if (reg.class() == .general_purpose) set.set(index);
|
||||
break :blk set;
|
||||
};
|
||||
const x87: RegisterBitSet = blk: {
|
||||
var set = RegisterBitSet.initEmpty();
|
||||
for (abi.allocatable_regs, 0..) |reg, index| if (reg.class() == .x87) set.set(index);
|
||||
break :blk set;
|
||||
};
|
||||
const sse: RegisterBitSet = blk: {
|
||||
var set = RegisterBitSet.initEmpty();
|
||||
for (abi.allocatable_regs, 0..) |reg, index| if (reg.class() == .sse) set.set(index);
|
||||
break :blk set;
|
||||
};
|
||||
};
|
||||
|
||||
const Renderer = @This();
|
||||
|
||||
base: *BaseRenderer,
|
||||
interner: *Interner,
|
||||
|
||||
register_manager: RegisterManager = .{},
|
||||
|
||||
pub fn render(base: *BaseRenderer) !void {
|
||||
var renderer: Renderer = .{
|
||||
.base = base,
|
||||
.interner = base.ir.interner,
|
||||
};
|
||||
|
||||
for (renderer.base.ir.decls.keys(), renderer.base.ir.decls.values()) |name, decl| {
|
||||
renderer.renderFn(name, decl) catch |e| switch (e) {
|
||||
error.OutOfMemory => return e,
|
||||
error.LowerFail => continue,
|
||||
};
|
||||
}
|
||||
if (renderer.base.errors.entries.len != 0) return error.LowerFail;
|
||||
}
|
||||
|
||||
fn renderFn(r: *Renderer, name: []const u8, decl: Ir.Decl) !void {
|
||||
_ = decl;
|
||||
return r.base.fail(name, "TODO implement lowering functions", .{});
|
||||
}
|
||||
@ -1,15 +1,15 @@
|
||||
const std = @import("std");
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Elf = @import("object/Elf.zig");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Elf = @import("Object/Elf.zig");
|
||||
|
||||
const Object = @This();
|
||||
|
||||
format: std.Target.ObjectFormat,
|
||||
comp: *Compilation,
|
||||
target: std.Target,
|
||||
|
||||
pub fn create(comp: *Compilation) !*Object {
|
||||
switch (comp.target.ofmt) {
|
||||
.elf => return Elf.create(comp),
|
||||
pub fn create(gpa: Allocator, target: std.Target) !*Object {
|
||||
switch (target.ofmt) {
|
||||
.elf => return Elf.create(gpa, target),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,8 @@
|
||||
const std = @import("std");
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Target = std.Target;
|
||||
const Object = @import("../Object.zig");
|
||||
|
||||
const Elf = @This();
|
||||
|
||||
const Section = struct {
|
||||
data: std.ArrayList(u8),
|
||||
relocations: std.ArrayListUnmanaged(Relocation) = .{},
|
||||
@ -34,6 +33,8 @@ const strtab_default = "\x00.strtab\x00.symtab\x00";
|
||||
const strtab_name = 1;
|
||||
const symtab_name = "\x00.strtab\x00".len;
|
||||
|
||||
const Elf = @This();
|
||||
|
||||
obj: Object,
|
||||
/// The keys are owned by the Codegen.tree
|
||||
sections: std.StringHashMapUnmanaged(*Section) = .{},
|
||||
@ -43,11 +44,11 @@ unnamed_symbol_mangle: u32 = 0,
|
||||
strtab_len: u64 = strtab_default.len,
|
||||
arena: std.heap.ArenaAllocator,
|
||||
|
||||
pub fn create(comp: *Compilation) !*Object {
|
||||
const elf = try comp.gpa.create(Elf);
|
||||
pub fn create(gpa: Allocator, target: Target) !*Object {
|
||||
const elf = try gpa.create(Elf);
|
||||
elf.* = .{
|
||||
.obj = .{ .format = .elf, .comp = comp },
|
||||
.arena = std.heap.ArenaAllocator.init(comp.gpa),
|
||||
.obj = .{ .format = .elf, .target = target },
|
||||
.arena = std.heap.ArenaAllocator.init(gpa),
|
||||
};
|
||||
return &elf.obj;
|
||||
}
|
||||
@ -195,10 +196,10 @@ pub fn finish(elf: *Elf, file: std.fs.File) !void {
|
||||
const sh_offset = strtab_offset + elf.strtab_len;
|
||||
const sh_offset_aligned = std.mem.alignForward(u64, sh_offset, 16);
|
||||
|
||||
var elf_header = std.elf.Elf64_Ehdr{
|
||||
const elf_header = std.elf.Elf64_Ehdr{
|
||||
.e_ident = .{ 0x7F, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.e_type = std.elf.ET.REL, // we only produce relocatables
|
||||
.e_machine = elf.obj.comp.target.cpu.arch.toElfMachine(),
|
||||
.e_machine = elf.obj.target.cpu.arch.toElfMachine(),
|
||||
.e_version = 1,
|
||||
.e_entry = 0, // linker will handle this
|
||||
.e_phoff = 0, // no program header
|
||||
@ -298,7 +299,7 @@ pub fn finish(elf: *Elf, file: std.fs.File) !void {
|
||||
|
||||
// write strtab section header
|
||||
{
|
||||
var sect_header = std.elf.Elf64_Shdr{
|
||||
const sect_header = std.elf.Elf64_Shdr{
|
||||
.sh_name = strtab_name,
|
||||
.sh_type = std.elf.SHT_STRTAB,
|
||||
.sh_flags = 0,
|
||||
@ -315,7 +316,7 @@ pub fn finish(elf: *Elf, file: std.fs.File) !void {
|
||||
|
||||
// write symtab section header
|
||||
{
|
||||
var sect_header = std.elf.Elf64_Shdr{
|
||||
const sect_header = std.elf.Elf64_Shdr{
|
||||
.sh_name = symtab_name,
|
||||
.sh_type = std.elf.SHT_SYMTAB,
|
||||
.sh_flags = 0,
|
||||
98
deps/aro/build/GenerateDef.zig
vendored
98
deps/aro/build/GenerateDef.zig
vendored
@ -1,25 +1,31 @@
|
||||
const std = @import("std");
|
||||
const GenerateDef = @This();
|
||||
const Step = std.Build.Step;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const GeneratedFile = std.Build.GeneratedFile;
|
||||
|
||||
const GenerateDef = @This();
|
||||
|
||||
step: Step,
|
||||
path: []const u8,
|
||||
name: []const u8,
|
||||
kind: Options.Kind,
|
||||
generated_file: GeneratedFile,
|
||||
|
||||
pub const base_id: Step.Id = .custom;
|
||||
|
||||
pub fn add(
|
||||
owner: *std.Build,
|
||||
def_file_path: []const u8,
|
||||
import_path: []const u8,
|
||||
compile_step: *Step.Compile,
|
||||
aro_module: *std.Build.Module,
|
||||
) void {
|
||||
const self = owner.allocator.create(GenerateDef) catch @panic("OOM");
|
||||
pub const Options = struct {
|
||||
name: []const u8,
|
||||
src_prefix: []const u8 = "src/aro",
|
||||
kind: Kind = .dafsa,
|
||||
|
||||
const name = owner.fmt("GenerateDef {s}", .{def_file_path});
|
||||
pub const Kind = enum { dafsa, named };
|
||||
};
|
||||
|
||||
pub fn create(owner: *std.Build, options: Options) std.Build.ModuleDependency {
|
||||
const self = owner.allocator.create(GenerateDef) catch @panic("OOM");
|
||||
const path = owner.pathJoin(&.{ options.src_prefix, options.name });
|
||||
|
||||
const name = owner.fmt("GenerateDef {s}", .{options.name});
|
||||
self.* = .{
|
||||
.step = Step.init(.{
|
||||
.id = base_id,
|
||||
@ -27,16 +33,18 @@ pub fn add(
|
||||
.owner = owner,
|
||||
.makeFn = make,
|
||||
}),
|
||||
.path = def_file_path,
|
||||
.path = path,
|
||||
.name = options.name,
|
||||
.kind = options.kind,
|
||||
.generated_file = .{ .step = &self.step },
|
||||
};
|
||||
|
||||
const module = owner.createModule(.{
|
||||
const module = self.step.owner.createModule(.{
|
||||
.source_file = .{ .generated = &self.generated_file },
|
||||
});
|
||||
compile_step.addModule(import_path, module);
|
||||
compile_step.step.dependOn(&self.step);
|
||||
aro_module.dependencies.put(import_path, module) catch @panic("OOM");
|
||||
return .{
|
||||
.module = module,
|
||||
.name = self.name,
|
||||
};
|
||||
}
|
||||
|
||||
fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
||||
@ -132,7 +140,7 @@ fn generate(self: *GenerateDef, input: []const u8) ![]const u8 {
|
||||
}
|
||||
|
||||
{
|
||||
var sorted_list = try arena.dupe([]const u8, values.keys());
|
||||
const sorted_list = try arena.dupe([]const u8, values.keys());
|
||||
defer arena.free(sorted_list);
|
||||
std.mem.sort([]const u8, sorted_list, {}, struct {
|
||||
pub fn lessThan(_: void, a: []const u8, b: []const u8) bool {
|
||||
@ -168,15 +176,6 @@ fn generate(self: *GenerateDef, input: []const u8) ![]const u8 {
|
||||
}
|
||||
}
|
||||
|
||||
var values_array = try arena.alloc(Value, values.count());
|
||||
defer arena.free(values_array);
|
||||
|
||||
for (values.keys(), values.values()) |name, props| {
|
||||
const unique_index = builder.getUniqueIndex(name).?;
|
||||
const data_index = unique_index - 1;
|
||||
values_array[data_index] = .{ .name = name, .properties = props };
|
||||
}
|
||||
|
||||
var out_buf = std.ArrayList(u8).init(arena);
|
||||
defer out_buf.deinit();
|
||||
const writer = out_buf.writer();
|
||||
@ -193,6 +192,49 @@ fn generate(self: *GenerateDef, input: []const u8) ![]const u8 {
|
||||
for (headers.items) |line| {
|
||||
try writer.print("{s}\n", .{line});
|
||||
}
|
||||
if (self.kind == .named) {
|
||||
try writer.writeAll("pub const Tag = enum {\n");
|
||||
for (values.keys()) |property| {
|
||||
try writer.print(" {s},\n", .{std.zig.fmtId(property)});
|
||||
}
|
||||
try writer.writeAll(
|
||||
\\
|
||||
\\ pub fn property(tag: Tag) Properties {
|
||||
\\ return named_data[@intFromEnum(tag)];
|
||||
\\ }
|
||||
\\
|
||||
\\ const named_data = [_]Properties{
|
||||
\\
|
||||
);
|
||||
for (values.values()) |val_props| {
|
||||
try writer.writeAll(" .{");
|
||||
for (val_props, 0..) |val_prop, j| {
|
||||
if (j != 0) try writer.writeByte(',');
|
||||
try writer.writeByte(' ');
|
||||
try writer.writeAll(val_prop);
|
||||
}
|
||||
try writer.writeAll(" },\n");
|
||||
}
|
||||
try writer.writeAll(
|
||||
\\ };
|
||||
\\};
|
||||
\\};
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
|
||||
return out_buf.toOwnedSlice();
|
||||
}
|
||||
|
||||
var values_array = try arena.alloc(Value, values.count());
|
||||
defer arena.free(values_array);
|
||||
|
||||
for (values.keys(), values.values()) |name, props| {
|
||||
const unique_index = builder.getUniqueIndex(name).?;
|
||||
const data_index = unique_index - 1;
|
||||
values_array[data_index] = .{ .name = name, .properties = props };
|
||||
}
|
||||
|
||||
try writer.writeAll(
|
||||
\\
|
||||
\\tag: Tag,
|
||||
@ -418,7 +460,7 @@ const DafsaBuilder = struct {
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
errdefer arena.deinit();
|
||||
|
||||
var root = try arena.allocator().create(Node);
|
||||
const root = try arena.allocator().create(Node);
|
||||
root.* = .{};
|
||||
return DafsaBuilder{
|
||||
.root = root,
|
||||
@ -498,7 +540,7 @@ const DafsaBuilder = struct {
|
||||
std.debug.assert(node.children[c] == null);
|
||||
|
||||
var arena = self.arena.promote(self.allocator);
|
||||
var child = try arena.allocator().create(Node);
|
||||
const child = try arena.allocator().create(Node);
|
||||
self.arena = arena.state;
|
||||
|
||||
child.* = .{};
|
||||
|
||||
221
deps/aro/codegen/x86_64.zig
vendored
221
deps/aro/codegen/x86_64.zig
vendored
@ -1,221 +0,0 @@
|
||||
const std = @import("std");
|
||||
const Codegen = @import("../Codegen_legacy.zig");
|
||||
const Tree = @import("../Tree.zig");
|
||||
const NodeIndex = Tree.NodeIndex;
|
||||
const x86_64 = @import("zig").codegen.x86_64;
|
||||
const Register = x86_64.Register;
|
||||
const RegisterManager = @import("zig").RegisterManager;
|
||||
|
||||
const Fn = @This();
|
||||
|
||||
const Value = union(enum) {
|
||||
symbol: []const u8,
|
||||
immediate: i64,
|
||||
register: Register,
|
||||
none,
|
||||
};
|
||||
|
||||
register_manager: RegisterManager(Fn, Register, &x86_64.callee_preserved_regs) = .{},
|
||||
data: *std.ArrayList(u8),
|
||||
c: *Codegen,
|
||||
|
||||
pub fn deinit(func: *Fn) void {
|
||||
func.* = undefined;
|
||||
}
|
||||
|
||||
pub fn genFn(c: *Codegen, decl: NodeIndex, data: *std.ArrayList(u8)) Codegen.Error!void {
|
||||
var func = Fn{ .data = data, .c = c };
|
||||
defer func.deinit();
|
||||
|
||||
// function prologue
|
||||
try func.data.appendSlice(&.{
|
||||
0x55, // push rbp
|
||||
0x48, 0x89, 0xe5, // mov rbp,rsp
|
||||
});
|
||||
_ = try func.genNode(c.node_data[@intFromEnum(decl)].decl.node);
|
||||
// all functions are guaranteed to end in a return statement so no extra work required here
|
||||
}
|
||||
|
||||
pub fn spillInst(f: *Fn, reg: Register, inst: u32) !void {
|
||||
_ = inst;
|
||||
_ = reg;
|
||||
_ = f;
|
||||
}
|
||||
|
||||
fn setReg(func: *Fn, val: Value, reg: Register) !void {
|
||||
switch (val) {
|
||||
.none => unreachable,
|
||||
.symbol => |sym| {
|
||||
// lea address with 0 and add relocation
|
||||
const encoder = try x86_64.Encoder.init(func.data, 8);
|
||||
encoder.rex(.{ .w = true });
|
||||
encoder.opcode_1byte(0x8D);
|
||||
encoder.modRm_RIPDisp32(reg.low_id());
|
||||
|
||||
const offset = func.data.items.len;
|
||||
encoder.imm32(0);
|
||||
|
||||
try func.c.obj.addRelocation(sym, .func, offset, -4);
|
||||
},
|
||||
.immediate => |x| if (x == 0) {
|
||||
// 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
|
||||
// register is the fastest way to zero a register.
|
||||
// The encoding for `xor r32, r32` is `0x31 /r`.
|
||||
const encoder = try x86_64.Encoder.init(func.data, 3);
|
||||
|
||||
// If we're accessing e.g. r8d, we need to use a REX prefix before the actual operation. Since
|
||||
// this is a 32-bit operation, the W flag is set to zero. X is also zero, as we're not using a SIB.
|
||||
// Both R and B are set, as we're extending, in effect, the register bits *and* the operand.
|
||||
encoder.rex(.{ .r = reg.isExtended(), .b = reg.isExtended() });
|
||||
encoder.opcode_1byte(0x31);
|
||||
// Section 3.1.1.1 of the Intel x64 Manual states that "/r indicates that the
|
||||
// ModR/M byte of the instruction contains a register operand and an r/m operand."
|
||||
encoder.modRm_direct(reg.low_id(), reg.low_id());
|
||||
} else if (x <= std.math.maxInt(i32)) {
|
||||
// Next best case: if we set the lower four bytes, the upper four will be zeroed.
|
||||
//
|
||||
// The encoding for `mov IMM32 -> REG` is (0xB8 + R) IMM.
|
||||
|
||||
const encoder = try x86_64.Encoder.init(func.data, 6);
|
||||
// Just as with XORing, we need a REX prefix. This time though, we only
|
||||
// need the B bit set, as we're extending the opcode's register field,
|
||||
// and there is no Mod R/M byte.
|
||||
encoder.rex(.{ .b = reg.isExtended() });
|
||||
encoder.opcode_withReg(0xB8, reg.low_id());
|
||||
|
||||
// no ModR/M byte
|
||||
|
||||
// IMM
|
||||
encoder.imm32(@intCast(x));
|
||||
} else {
|
||||
// Worst case: we need to load the 64-bit register with the IMM. GNU's assemblers calls
|
||||
// this `movabs`, though this is officially just a different variant of the plain `mov`
|
||||
// instruction.
|
||||
//
|
||||
// This encoding is, in fact, the *same* as the one used for 32-bit loads. The only
|
||||
// difference is that we set REX.W before the instruction, which extends the load to
|
||||
// 64-bit and uses the full bit-width of the register.
|
||||
{
|
||||
const encoder = try x86_64.Encoder.init(func.data, 10);
|
||||
encoder.rex(.{ .w = true, .b = reg.isExtended() });
|
||||
encoder.opcode_withReg(0xB8, reg.low_id());
|
||||
encoder.imm64(@bitCast(x));
|
||||
}
|
||||
},
|
||||
.register => |src_reg| {
|
||||
// If the registers are the same, nothing to do.
|
||||
if (src_reg.id() == reg.id())
|
||||
return;
|
||||
|
||||
// This is a variant of 8B /r.
|
||||
const encoder = try x86_64.Encoder.init(func.data, 3);
|
||||
encoder.rex(.{
|
||||
.w = true,
|
||||
.r = reg.isExtended(),
|
||||
.b = src_reg.isExtended(),
|
||||
});
|
||||
encoder.opcode_1byte(0x8B);
|
||||
encoder.modRm_direct(reg.low_id(), src_reg.low_id());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn genNode(func: *Fn, node: NodeIndex) Codegen.Error!Value {
|
||||
if (func.c.tree.value_map.get(node)) |some| {
|
||||
if (some.tag == .int)
|
||||
return Value{ .immediate = @bitCast(some.data.int) };
|
||||
}
|
||||
|
||||
const data = func.c.node_data[@intFromEnum(node)];
|
||||
switch (func.c.node_tag[@intFromEnum(node)]) {
|
||||
.static_assert => return Value{ .none = {} },
|
||||
.compound_stmt_two => {
|
||||
if (data.bin.lhs != .none) _ = try func.genNode(data.bin.lhs);
|
||||
if (data.bin.rhs != .none) _ = try func.genNode(data.bin.rhs);
|
||||
return Value{ .none = {} };
|
||||
},
|
||||
.compound_stmt => {
|
||||
for (func.c.tree.data[data.range.start..data.range.end]) |stmt| {
|
||||
_ = try func.genNode(stmt);
|
||||
}
|
||||
return Value{ .none = {} };
|
||||
},
|
||||
.call_expr_one => if (data.bin.rhs != .none)
|
||||
return func.genCall(data.bin.lhs, &.{data.bin.rhs})
|
||||
else
|
||||
return func.genCall(data.bin.lhs, &.{}),
|
||||
.call_expr => return func.genCall(func.c.tree.data[data.range.start], func.c.tree.data[data.range.start + 1 .. data.range.end]),
|
||||
.explicit_cast, .implicit_cast => {
|
||||
switch (data.cast.kind) {
|
||||
.function_to_pointer,
|
||||
.array_to_pointer,
|
||||
=> return func.genNode(data.cast.operand), // no-op
|
||||
else => return func.c.comp.diag.fatalNoSrc("TODO x86_64 genNode for cast {s}\n", .{@tagName(data.cast.kind)}),
|
||||
}
|
||||
},
|
||||
.decl_ref_expr => {
|
||||
// TODO locals and arguments
|
||||
return Value{ .symbol = func.c.tree.tokSlice(data.decl_ref) };
|
||||
},
|
||||
.return_stmt => {
|
||||
const value = try func.genNode(data.un);
|
||||
try func.setReg(value, x86_64.c_abi_int_return_regs[0]);
|
||||
try func.data.appendSlice(&.{
|
||||
0x5d, // pop rbp
|
||||
0xc3, // ret
|
||||
});
|
||||
return Value{ .none = {} };
|
||||
},
|
||||
.implicit_return => {
|
||||
try func.setReg(.{ .immediate = 0 }, x86_64.c_abi_int_return_regs[0]);
|
||||
try func.data.appendSlice(&.{
|
||||
0x5d, // pop rbp
|
||||
0xc3, // ret
|
||||
});
|
||||
return Value{ .none = {} };
|
||||
},
|
||||
.int_literal => return Value{ .immediate = @bitCast(data.int) },
|
||||
.string_literal_expr => {
|
||||
const range = func.c.tree.value_map.get(node).?.data.bytes;
|
||||
const str_bytes = range.slice(func.c.tree.strings, .@"1");
|
||||
const section = try func.c.obj.getSection(.strings);
|
||||
const start = section.items.len;
|
||||
try section.appendSlice(str_bytes);
|
||||
const symbol_name = try func.c.obj.declareSymbol(.strings, null, .Internal, .variable, start, str_bytes.len);
|
||||
return Value{ .symbol = symbol_name };
|
||||
},
|
||||
else => return func.c.comp.diag.fatalNoSrc("TODO x86_64 genNode {}\n", .{func.c.node_tag[@intFromEnum(node)]}),
|
||||
}
|
||||
}
|
||||
|
||||
fn genCall(func: *Fn, lhs: NodeIndex, args: []const NodeIndex) Codegen.Error!Value {
|
||||
if (args.len > x86_64.c_abi_int_param_regs.len)
|
||||
return func.c.comp.diag.fatalNoSrc("TODO more than args {d}\n", .{x86_64.c_abi_int_param_regs.len});
|
||||
|
||||
const func_value = try func.genNode(lhs);
|
||||
for (args, 0..) |arg, i| {
|
||||
const value = try func.genNode(arg);
|
||||
try func.setReg(value, x86_64.c_abi_int_param_regs[i]);
|
||||
}
|
||||
|
||||
switch (func_value) {
|
||||
.none => unreachable,
|
||||
.symbol => |sym| {
|
||||
const encoder = try x86_64.Encoder.init(func.data, 5);
|
||||
encoder.opcode_1byte(0xe8);
|
||||
|
||||
const offset = func.data.items.len;
|
||||
encoder.imm32(0);
|
||||
|
||||
try func.c.obj.addRelocation(sym, .func, offset, -4);
|
||||
},
|
||||
.immediate => return func.c.comp.diag.fatalNoSrc("TODO call immediate\n", .{}),
|
||||
.register => return func.c.comp.diag.fatalNoSrc("TODO call reg\n", .{}),
|
||||
}
|
||||
return Value{ .register = x86_64.c_abi_int_return_regs[0] };
|
||||
}
|
||||
|
||||
pub fn genVar(c: *Codegen, decl: NodeIndex) Codegen.Error!void {
|
||||
_ = c;
|
||||
_ = decl;
|
||||
}
|
||||
27
deps/aro/lib.zig
vendored
27
deps/aro/lib.zig
vendored
@ -1,27 +0,0 @@
|
||||
/// Deprecated
|
||||
pub const Codegen = @import("Codegen_legacy.zig");
|
||||
pub const CodeGen = @import("CodeGen.zig");
|
||||
pub const Compilation = @import("Compilation.zig");
|
||||
pub const Diagnostics = @import("Diagnostics.zig");
|
||||
pub const Driver = @import("Driver.zig");
|
||||
pub const Interner = @import("Interner.zig");
|
||||
pub const Ir = @import("Ir.zig");
|
||||
pub const Object = @import("Object.zig");
|
||||
pub const Parser = @import("Parser.zig");
|
||||
pub const Preprocessor = @import("Preprocessor.zig");
|
||||
pub const Source = @import("Source.zig");
|
||||
pub const Tokenizer = @import("Tokenizer.zig");
|
||||
pub const Tree = @import("Tree.zig");
|
||||
pub const Type = @import("Type.zig");
|
||||
pub const TypeMapper = @import("StringInterner.zig").TypeMapper;
|
||||
pub const target_util = @import("target.zig");
|
||||
|
||||
pub const version_str = "0.0.0-dev";
|
||||
pub const version = @import("std").SemanticVersion.parse(version_str) catch unreachable;
|
||||
|
||||
pub const CallingConvention = enum {
|
||||
C,
|
||||
stdcall,
|
||||
thiscall,
|
||||
vectorcall,
|
||||
};
|
||||
83
deps/aro/util.zig
vendored
83
deps/aro/util.zig
vendored
@ -1,83 +0,0 @@
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const builtin = @import("builtin");
|
||||
const is_windows = builtin.os.tag == .windows;
|
||||
|
||||
pub const Color = enum {
|
||||
reset,
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
cyan,
|
||||
purple,
|
||||
yellow,
|
||||
white,
|
||||
};
|
||||
|
||||
pub fn fileSupportsColor(file: std.fs.File) bool {
|
||||
return file.supportsAnsiEscapeCodes() or (is_windows and file.isTty());
|
||||
}
|
||||
|
||||
pub fn setColor(color: Color, w: anytype) void {
|
||||
if (is_windows) {
|
||||
const stderr_file = std.io.getStdErr();
|
||||
if (!stderr_file.isTty()) return;
|
||||
const windows = std.os.windows;
|
||||
const S = struct {
|
||||
var attrs: windows.WORD = undefined;
|
||||
var init_attrs = false;
|
||||
};
|
||||
if (!S.init_attrs) {
|
||||
S.init_attrs = true;
|
||||
var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
|
||||
_ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info);
|
||||
S.attrs = info.wAttributes;
|
||||
_ = windows.kernel32.SetConsoleOutputCP(65001);
|
||||
}
|
||||
|
||||
// need to flush bufferedWriter
|
||||
const T = if (@typeInfo(@TypeOf(w.context)) == .Pointer) @TypeOf(w.context.*) else @TypeOf(w.context);
|
||||
if (T != void and @hasDecl(T, "flush")) w.context.flush() catch {};
|
||||
|
||||
switch (color) {
|
||||
.reset => _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {},
|
||||
.red => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY) catch {},
|
||||
.green => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {},
|
||||
.blue => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {},
|
||||
.cyan => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {},
|
||||
.purple => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {},
|
||||
.yellow => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {},
|
||||
.white => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {},
|
||||
}
|
||||
} else switch (color) {
|
||||
.reset => w.writeAll("\x1b[0m") catch {},
|
||||
.red => w.writeAll("\x1b[31;1m") catch {},
|
||||
.green => w.writeAll("\x1b[32;1m") catch {},
|
||||
.blue => w.writeAll("\x1b[34;1m") catch {},
|
||||
.cyan => w.writeAll("\x1b[36;1m") catch {},
|
||||
.purple => w.writeAll("\x1b[35;1m") catch {},
|
||||
.yellow => w.writeAll("\x1b[93;1m") catch {},
|
||||
.white => w.writeAll("\x1b[0m\x1b[1m") catch {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn errorDescription(err: anyerror) []const u8 {
|
||||
return switch (err) {
|
||||
error.OutOfMemory => "ran out of memory",
|
||||
error.FileNotFound => "file not found",
|
||||
error.IsDir => "is a directory",
|
||||
error.NotDir => "is not a directory",
|
||||
error.NotOpenForReading => "file is not open for reading",
|
||||
error.NotOpenForWriting => "file is not open for writing",
|
||||
error.InvalidUtf8 => "input is not valid UTF-8",
|
||||
error.FileBusy => "file is busy",
|
||||
error.NameTooLong => "file name is too long",
|
||||
error.AccessDenied => "access denied",
|
||||
error.FileTooBig => "file is too big",
|
||||
error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded => "ran out of file descriptors",
|
||||
error.SystemResources => "ran out of system resources",
|
||||
error.FatalError => "a fatal error occurred",
|
||||
error.Unexpected => "an unexpected error occurred",
|
||||
else => @errorName(err),
|
||||
};
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user