mirror of
https://github.com/ziglang/zig.git
synced 2024-11-26 23:22:44 +00:00
Merge remote-tracking branch 'origin/master' into layneson-cpus_and_features
This commit is contained in:
commit
9dffc369f1
@ -1689,7 +1689,9 @@ pub const LibExeObjStep = struct {
|
||||
}
|
||||
|
||||
pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {
|
||||
self.link_objects.append(LinkObject{ .AssemblyFile = self.builder.dupe(path) }) catch unreachable;
|
||||
self.link_objects.append(LinkObject{
|
||||
.AssemblyFile = .{ .path = self.builder.dupe(path) },
|
||||
}) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn addAssemblyFileFromWriteFileStep(self: *LibExeObjStep, wfs: *WriteFileStep, basename: []const u8) void {
|
||||
|
@ -379,16 +379,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
|
||||
}
|
||||
} else {
|
||||
// we have no information to add to the address
|
||||
if (tty_color) {
|
||||
try out_stream.print("???:?:?: ", .{});
|
||||
setTtyColor(TtyColor.Dim);
|
||||
try out_stream.print("0x{x} in ??? (???)", .{relocated_address});
|
||||
setTtyColor(TtyColor.Reset);
|
||||
try out_stream.print("\n\n\n", .{});
|
||||
} else {
|
||||
try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{relocated_address});
|
||||
}
|
||||
return;
|
||||
return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_color, printLineFromFileAnyOs);
|
||||
};
|
||||
|
||||
const mod = &di.modules[mod_index];
|
||||
@ -510,66 +501,15 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
|
||||
}
|
||||
};
|
||||
|
||||
if (tty_color) {
|
||||
setTtyColor(TtyColor.White);
|
||||
if (opt_line_info) |li| {
|
||||
try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column });
|
||||
} else {
|
||||
try out_stream.print("???:?:?", .{});
|
||||
}
|
||||
setTtyColor(TtyColor.Reset);
|
||||
try out_stream.print(": ", .{});
|
||||
setTtyColor(TtyColor.Dim);
|
||||
try out_stream.print("0x{x} in {} ({})", .{ relocated_address, symbol_name, obj_basename });
|
||||
setTtyColor(TtyColor.Reset);
|
||||
|
||||
if (opt_line_info) |line_info| {
|
||||
try out_stream.print("\n", .{});
|
||||
if (printLineFromFileAnyOs(out_stream, line_info)) {
|
||||
if (line_info.column == 0) {
|
||||
try out_stream.write("\n");
|
||||
} else {
|
||||
{
|
||||
var col_i: usize = 1;
|
||||
while (col_i < line_info.column) : (col_i += 1) {
|
||||
try out_stream.writeByte(' ');
|
||||
}
|
||||
}
|
||||
setTtyColor(TtyColor.Green);
|
||||
try out_stream.write("^");
|
||||
setTtyColor(TtyColor.Reset);
|
||||
try out_stream.write("\n");
|
||||
}
|
||||
} else |err| switch (err) {
|
||||
error.EndOfFile => {},
|
||||
error.FileNotFound => {
|
||||
setTtyColor(TtyColor.Dim);
|
||||
try out_stream.write("file not found\n\n");
|
||||
setTtyColor(TtyColor.White);
|
||||
},
|
||||
else => return err,
|
||||
}
|
||||
} else {
|
||||
try out_stream.print("\n\n\n", .{});
|
||||
}
|
||||
} else {
|
||||
if (opt_line_info) |li| {
|
||||
try out_stream.print("{}:{}:{}: 0x{x} in {} ({})\n\n\n", .{
|
||||
li.file_name,
|
||||
li.line,
|
||||
li.column,
|
||||
relocated_address,
|
||||
symbol_name,
|
||||
obj_basename,
|
||||
});
|
||||
} else {
|
||||
try out_stream.print("???:?:?: 0x{x} in {} ({})\n\n\n", .{
|
||||
relocated_address,
|
||||
symbol_name,
|
||||
obj_basename,
|
||||
});
|
||||
}
|
||||
}
|
||||
try printLineInfo(
|
||||
out_stream,
|
||||
opt_line_info,
|
||||
relocated_address,
|
||||
symbol_name,
|
||||
obj_basename,
|
||||
tty_color,
|
||||
printLineFromFileAnyOs,
|
||||
);
|
||||
}
|
||||
|
||||
const TtyColor = enum {
|
||||
@ -605,7 +545,11 @@ fn setTtyColor(tty_color: TtyColor) void {
|
||||
stderr_file.write(RESET) catch return;
|
||||
},
|
||||
}
|
||||
} else {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (builtin.os == .windows) {
|
||||
const S = struct {
|
||||
var attrs: windows.WORD = undefined;
|
||||
var init_attrs = false;
|
||||
@ -711,12 +655,7 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
|
||||
const adjusted_addr = 0x100000000 + (address - base_addr);
|
||||
|
||||
const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse {
|
||||
if (tty_color) {
|
||||
try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", .{address});
|
||||
} else {
|
||||
try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{address});
|
||||
}
|
||||
return;
|
||||
return printLineInfo(out_stream, null, address, "???", "???", tty_color, printLineFromFileAnyOs);
|
||||
};
|
||||
|
||||
const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + symbol.nlist.n_strx));
|
||||
@ -724,29 +663,22 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
|
||||
const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
|
||||
break :blk fs.path.basename(ofile_path);
|
||||
} else "???";
|
||||
if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
|
||||
defer line_info.deinit();
|
||||
try printLineInfo(
|
||||
out_stream,
|
||||
line_info,
|
||||
address,
|
||||
symbol_name,
|
||||
compile_unit_name,
|
||||
tty_color,
|
||||
printLineFromFileAnyOs,
|
||||
);
|
||||
} else |err| switch (err) {
|
||||
error.MissingDebugInfo, error.InvalidDebugInfo => {
|
||||
if (tty_color) {
|
||||
try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in {} ({})" ++ RESET ++ "\n\n\n", .{
|
||||
address, symbol_name, compile_unit_name,
|
||||
});
|
||||
} else {
|
||||
try out_stream.print("???:?:?: 0x{x} in {} ({})\n\n\n", .{ address, symbol_name, compile_unit_name });
|
||||
}
|
||||
},
|
||||
|
||||
const line_info = getLineNumberInfoMacOs(di, symbol.*, adjusted_addr) catch |err| switch (err) {
|
||||
error.MissingDebugInfo, error.InvalidDebugInfo => null,
|
||||
else => return err,
|
||||
}
|
||||
};
|
||||
defer if (line_info) |li| li.deinit();
|
||||
|
||||
try printLineInfo(
|
||||
out_stream,
|
||||
line_info,
|
||||
address,
|
||||
symbol_name,
|
||||
compile_unit_name,
|
||||
tty_color,
|
||||
printLineFromFileAnyOs,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
|
||||
@ -755,47 +687,46 @@ pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, addres
|
||||
|
||||
fn printLineInfo(
|
||||
out_stream: var,
|
||||
line_info: LineInfo,
|
||||
line_info: ?LineInfo,
|
||||
address: usize,
|
||||
symbol_name: []const u8,
|
||||
compile_unit_name: []const u8,
|
||||
tty_color: bool,
|
||||
comptime printLineFromFile: var,
|
||||
) !void {
|
||||
if (tty_color) {
|
||||
try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ DIM ++ "0x{x} in {} ({})" ++ RESET ++ "\n", .{
|
||||
line_info.file_name,
|
||||
line_info.line,
|
||||
line_info.column,
|
||||
address,
|
||||
symbol_name,
|
||||
compile_unit_name,
|
||||
});
|
||||
if (printLineFromFile(out_stream, line_info)) {
|
||||
if (line_info.column == 0) {
|
||||
try out_stream.write("\n");
|
||||
} else {
|
||||
{
|
||||
var col_i: usize = 1;
|
||||
while (col_i < line_info.column) : (col_i += 1) {
|
||||
try out_stream.writeByte(' ');
|
||||
}
|
||||
}
|
||||
try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n");
|
||||
if (tty_color) setTtyColor(.White);
|
||||
|
||||
if (line_info) |*li| {
|
||||
try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column });
|
||||
} else {
|
||||
try out_stream.print("???:?:?", .{});
|
||||
}
|
||||
|
||||
if (tty_color) setTtyColor(.Reset);
|
||||
try out_stream.write(": ");
|
||||
if (tty_color) setTtyColor(.Dim);
|
||||
try out_stream.print("0x{x} in {} ({})", .{ address, symbol_name, compile_unit_name });
|
||||
if (tty_color) setTtyColor(.Reset);
|
||||
try out_stream.write("\n");
|
||||
|
||||
// Show the matching source code line if possible
|
||||
if (line_info) |li| {
|
||||
if (noasync printLineFromFile(out_stream, li)) {
|
||||
if (li.column > 0) {
|
||||
// The caret already takes one char
|
||||
const space_needed = @intCast(usize, li.column - 1);
|
||||
|
||||
try out_stream.writeByteNTimes(' ', space_needed);
|
||||
if (tty_color) setTtyColor(.Green);
|
||||
try out_stream.write("^");
|
||||
if (tty_color) setTtyColor(.Reset);
|
||||
}
|
||||
try out_stream.write("\n");
|
||||
} else |err| switch (err) {
|
||||
error.EndOfFile, error.FileNotFound => {},
|
||||
error.BadPathName => {},
|
||||
else => return err,
|
||||
}
|
||||
} else {
|
||||
try out_stream.print("{}:{}:{}: 0x{x} in {} ({})\n", .{
|
||||
line_info.file_name,
|
||||
line_info.line,
|
||||
line_info.column,
|
||||
address,
|
||||
symbol_name,
|
||||
compile_unit_name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1240,38 +1171,26 @@ pub const DwarfInfo = struct {
|
||||
comptime printLineFromFile: var,
|
||||
) !void {
|
||||
const compile_unit = self.findCompileUnit(address) catch {
|
||||
if (tty_color) {
|
||||
try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", .{address});
|
||||
} else {
|
||||
try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{address});
|
||||
}
|
||||
return;
|
||||
return printLineInfo(out_stream, null, address, "???", "???", tty_color, printLineFromFile);
|
||||
};
|
||||
|
||||
const compile_unit_name = try compile_unit.die.getAttrString(self, DW.AT_name);
|
||||
if (self.getLineNumberInfo(compile_unit.*, address)) |line_info| {
|
||||
defer line_info.deinit();
|
||||
const symbol_name = self.getSymbolName(address) orelse "???";
|
||||
try printLineInfo(
|
||||
out_stream,
|
||||
line_info,
|
||||
address,
|
||||
symbol_name,
|
||||
compile_unit_name,
|
||||
tty_color,
|
||||
printLineFromFile,
|
||||
);
|
||||
} else |err| switch (err) {
|
||||
error.MissingDebugInfo, error.InvalidDebugInfo => {
|
||||
if (tty_color) {
|
||||
try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? ({})" ++ RESET ++ "\n\n\n", .{
|
||||
address, compile_unit_name,
|
||||
});
|
||||
} else {
|
||||
try out_stream.print("???:?:?: 0x{x} in ??? ({})\n\n\n", .{ address, compile_unit_name });
|
||||
}
|
||||
},
|
||||
const symbol_name = self.getSymbolName(address) orelse "???";
|
||||
const line_info = self.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) {
|
||||
error.MissingDebugInfo, error.InvalidDebugInfo => null,
|
||||
else => return err,
|
||||
}
|
||||
};
|
||||
defer if (line_info) |li| li.deinit();
|
||||
|
||||
try printLineInfo(
|
||||
out_stream,
|
||||
line_info,
|
||||
address,
|
||||
symbol_name,
|
||||
compile_unit_name,
|
||||
tty_color,
|
||||
printLineFromFile,
|
||||
);
|
||||
}
|
||||
|
||||
fn getSymbolName(di: *DwarfInfo, address: u64) ?[]const u8 {
|
||||
@ -1458,9 +1377,13 @@ pub const DwarfInfo = struct {
|
||||
if (compile_unit.pc_range) |range| {
|
||||
if (target_address >= range.start and target_address < range.end) return compile_unit;
|
||||
}
|
||||
if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
|
||||
var base_address: usize = 0;
|
||||
if (di.debug_ranges) |debug_ranges| {
|
||||
if (di.debug_ranges) |debug_ranges| {
|
||||
if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
|
||||
// All the addresses in the list are relative to the value
|
||||
// specified by DW_AT_low_pc or to some other value encoded
|
||||
// in the list itself
|
||||
var base_address = try compile_unit.die.getAttrAddr(DW.AT_low_pc);
|
||||
|
||||
try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
|
||||
while (true) {
|
||||
const begin_addr = try di.dwarf_in_stream.readIntLittle(usize);
|
||||
@ -1468,18 +1391,21 @@ pub const DwarfInfo = struct {
|
||||
if (begin_addr == 0 and end_addr == 0) {
|
||||
break;
|
||||
}
|
||||
// This entry selects a new value for the base address
|
||||
if (begin_addr == maxInt(usize)) {
|
||||
base_address = begin_addr;
|
||||
base_address = end_addr;
|
||||
continue;
|
||||
}
|
||||
if (target_address >= begin_addr and target_address < end_addr) {
|
||||
if (target_address >= base_address + begin_addr and target_address < base_address + end_addr) {
|
||||
return compile_unit;
|
||||
}
|
||||
}
|
||||
|
||||
return error.InvalidDebugInfo;
|
||||
} else |err| {
|
||||
if (err != error.MissingDebugInfo) return err;
|
||||
continue;
|
||||
}
|
||||
} else |err| {
|
||||
if (err != error.MissingDebugInfo) return err;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return error.MissingDebugInfo;
|
||||
@ -1552,7 +1478,8 @@ pub const DwarfInfo = struct {
|
||||
|
||||
assert(line_info_offset < di.debug_line.size);
|
||||
|
||||
try di.dwarf_seekable_stream.seekTo(di.debug_line.offset + line_info_offset);
|
||||
const this_unit_offset = di.debug_line.offset + line_info_offset;
|
||||
try di.dwarf_seekable_stream.seekTo(this_unit_offset);
|
||||
|
||||
var is_64: bool = undefined;
|
||||
const unit_length = try readInitialLength(@TypeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
|
||||
@ -1620,7 +1547,9 @@ pub const DwarfInfo = struct {
|
||||
|
||||
try di.dwarf_seekable_stream.seekTo(prog_start_offset);
|
||||
|
||||
while (true) {
|
||||
const next_unit_pos = this_unit_offset + next_offset;
|
||||
|
||||
while ((try di.dwarf_seekable_stream.getPos()) < next_unit_pos) {
|
||||
const opcode = try di.dwarf_in_stream.readByte();
|
||||
|
||||
if (opcode == DW.LNS_extended_op) {
|
||||
@ -1631,7 +1560,7 @@ pub const DwarfInfo = struct {
|
||||
DW.LNE_end_sequence => {
|
||||
prog.end_sequence = true;
|
||||
if (try prog.checkLineMatch()) |info| return info;
|
||||
return error.MissingDebugInfo;
|
||||
prog.reset();
|
||||
},
|
||||
DW.LNE_set_address => {
|
||||
const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
|
||||
@ -1888,6 +1817,7 @@ const LineNumberProgram = struct {
|
||||
basic_block: bool,
|
||||
end_sequence: bool,
|
||||
|
||||
default_is_stmt: bool,
|
||||
target_address: usize,
|
||||
include_dirs: []const []const u8,
|
||||
file_entries: *ArrayList(FileEntry),
|
||||
@ -1900,6 +1830,25 @@ const LineNumberProgram = struct {
|
||||
prev_basic_block: bool,
|
||||
prev_end_sequence: bool,
|
||||
|
||||
// Reset the state machine following the DWARF specification
|
||||
pub fn reset(self: *LineNumberProgram) void {
|
||||
self.address = 0;
|
||||
self.file = 1;
|
||||
self.line = 1;
|
||||
self.column = 0;
|
||||
self.is_stmt = self.default_is_stmt;
|
||||
self.basic_block = false;
|
||||
self.end_sequence = false;
|
||||
// Invalidate all the remaining fields
|
||||
self.prev_address = 0;
|
||||
self.prev_file = undefined;
|
||||
self.prev_line = undefined;
|
||||
self.prev_column = undefined;
|
||||
self.prev_is_stmt = undefined;
|
||||
self.prev_basic_block = undefined;
|
||||
self.prev_end_sequence = undefined;
|
||||
}
|
||||
|
||||
pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: *ArrayList(FileEntry), target_address: usize) LineNumberProgram {
|
||||
return LineNumberProgram{
|
||||
.address = 0,
|
||||
@ -1911,6 +1860,7 @@ const LineNumberProgram = struct {
|
||||
.end_sequence = false,
|
||||
.include_dirs = include_dirs,
|
||||
.file_entries = file_entries,
|
||||
.default_is_stmt = is_stmt,
|
||||
.target_address = target_address,
|
||||
.prev_address = 0,
|
||||
.prev_file = undefined,
|
||||
|
@ -431,7 +431,7 @@ pub fn formatType(
|
||||
},
|
||||
else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
|
||||
},
|
||||
.Many => {
|
||||
.Many, .C => {
|
||||
if (ptr_info.child == u8) {
|
||||
if (fmt.len > 0 and fmt[0] == 's') {
|
||||
const len = mem.len(u8, value);
|
||||
@ -449,9 +449,6 @@ pub fn formatType(
|
||||
}
|
||||
return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
|
||||
},
|
||||
.C => {
|
||||
return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
|
||||
},
|
||||
},
|
||||
.Array => |info| {
|
||||
const Slice = @Type(builtin.TypeInfo{
|
||||
@ -1290,8 +1287,16 @@ test "pointer" {
|
||||
}
|
||||
|
||||
test "cstr" {
|
||||
try testFmt("cstr: Test C\n", "cstr: {s}\n", .{"Test C"});
|
||||
try testFmt("cstr: Test C \n", "cstr: {s:10}\n", .{"Test C"});
|
||||
try testFmt(
|
||||
"cstr: Test C\n",
|
||||
"cstr: {s}\n",
|
||||
.{@ptrCast([*c]const u8, "Test C")},
|
||||
);
|
||||
try testFmt(
|
||||
"cstr: Test C \n",
|
||||
"cstr: {s:10}\n",
|
||||
.{@ptrCast([*c]const u8, "Test C")},
|
||||
);
|
||||
}
|
||||
|
||||
test "filesize" {
|
||||
|
@ -45,10 +45,14 @@ pub fn OutStream(comptime WriteError: type) type {
|
||||
}
|
||||
|
||||
pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) Error!void {
|
||||
const slice = @as(*const [1]u8, &byte)[0..];
|
||||
var i: usize = 0;
|
||||
while (i < n) : (i += 1) {
|
||||
try self.writeFn(self, slice);
|
||||
var bytes: [256]u8 = undefined;
|
||||
mem.set(u8, bytes[0..], byte);
|
||||
|
||||
var remaining: usize = n;
|
||||
while (remaining > 0) {
|
||||
const to_write = std.math.min(remaining, bytes.len);
|
||||
try self.writeFn(self, bytes[0..to_write]);
|
||||
remaining -= to_write;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,7 @@ comptime {
|
||||
@export(@import("compiler_rt/int.zig").__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage });
|
||||
@export(@import("compiler_rt/popcountdi2.zig").__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/int.zig").__mulsi3, .{ .name = "__mulsi3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/muldi3.zig").__muldi3, .{ .name = "__muldi3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/int.zig").__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage });
|
||||
@export(@import("compiler_rt/int.zig").__divsi3, .{ .name = "__divsi3", .linkage = linkage });
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Builtin functions that operate on integer types
|
||||
const builtin = @import("builtin");
|
||||
const testing = @import("std").testing;
|
||||
const maxInt = @import("std").math.maxInt;
|
||||
const minInt = @import("std").math.minInt;
|
||||
|
||||
const udivmod = @import("udivmod.zig").udivmod;
|
||||
|
||||
@ -578,3 +580,61 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) void {
|
||||
const r: u32 = __umodsi3(a, b);
|
||||
testing.expect(r == expected_r);
|
||||
}
|
||||
|
||||
pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
|
||||
var ua = @bitCast(u32, a);
|
||||
var ub = @bitCast(u32, b);
|
||||
var r: u32 = 0;
|
||||
|
||||
while (ua > 0) {
|
||||
if ((ua & 1) != 0) r +%= ub;
|
||||
ua >>= 1;
|
||||
ub <<= 1;
|
||||
}
|
||||
|
||||
return @bitCast(i32, r);
|
||||
}
|
||||
|
||||
fn test_one_mulsi3(a: i32, b: i32, result: i32) void {
|
||||
testing.expectEqual(result, __mulsi3(a, b));
|
||||
}
|
||||
|
||||
test "mulsi3" {
|
||||
test_one_mulsi3(0, 0, 0);
|
||||
test_one_mulsi3(0, 1, 0);
|
||||
test_one_mulsi3(1, 0, 0);
|
||||
test_one_mulsi3(0, 10, 0);
|
||||
test_one_mulsi3(10, 0, 0);
|
||||
test_one_mulsi3(0, maxInt(i32), 0);
|
||||
test_one_mulsi3(maxInt(i32), 0, 0);
|
||||
test_one_mulsi3(0, -1, 0);
|
||||
test_one_mulsi3(-1, 0, 0);
|
||||
test_one_mulsi3(0, -10, 0);
|
||||
test_one_mulsi3(-10, 0, 0);
|
||||
test_one_mulsi3(0, minInt(i32), 0);
|
||||
test_one_mulsi3(minInt(i32), 0, 0);
|
||||
test_one_mulsi3(1, 1, 1);
|
||||
test_one_mulsi3(1, 10, 10);
|
||||
test_one_mulsi3(10, 1, 10);
|
||||
test_one_mulsi3(1, maxInt(i32), maxInt(i32));
|
||||
test_one_mulsi3(maxInt(i32), 1, maxInt(i32));
|
||||
test_one_mulsi3(1, -1, -1);
|
||||
test_one_mulsi3(1, -10, -10);
|
||||
test_one_mulsi3(-10, 1, -10);
|
||||
test_one_mulsi3(1, minInt(i32), minInt(i32));
|
||||
test_one_mulsi3(minInt(i32), 1, minInt(i32));
|
||||
test_one_mulsi3(46340, 46340, 2147395600);
|
||||
test_one_mulsi3(-46340, 46340, -2147395600);
|
||||
test_one_mulsi3(46340, -46340, -2147395600);
|
||||
test_one_mulsi3(-46340, -46340, 2147395600);
|
||||
test_one_mulsi3(4194303, 8192, @truncate(i32, 34359730176));
|
||||
test_one_mulsi3(-4194303, 8192, @truncate(i32, -34359730176));
|
||||
test_one_mulsi3(4194303, -8192, @truncate(i32, -34359730176));
|
||||
test_one_mulsi3(-4194303, -8192, @truncate(i32, 34359730176));
|
||||
test_one_mulsi3(8192, 4194303, @truncate(i32, 34359730176));
|
||||
test_one_mulsi3(-8192, 4194303, @truncate(i32, -34359730176));
|
||||
test_one_mulsi3(8192, -4194303, @truncate(i32, -34359730176));
|
||||
test_one_mulsi3(-8192, -4194303, @truncate(i32, 34359730176));
|
||||
}
|
||||
|
@ -768,6 +768,7 @@ pub extern fn ZigClangFieldDecl_getCanonicalDecl(field_decl: ?*const struct_ZigC
|
||||
pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
|
||||
pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;
|
||||
pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl;
|
||||
pub extern fn ZigClangParmVarDecl_getOriginalType(self: ?*const struct_ZigClangParmVarDecl) struct_ZigClangQualType;
|
||||
pub extern fn ZigClangVarDecl_getCanonicalDecl(self: ?*const struct_ZigClangVarDecl) ?*const struct_ZigClangVarDecl;
|
||||
pub extern fn ZigClangVarDecl_getSectionAttribute(self: *const ZigClangVarDecl, len: *usize) ?[*]const u8;
|
||||
pub extern fn ZigClangFunctionDecl_getAlignedAttribute(self: *const ZigClangFunctionDecl, *const ZigClangASTContext) c_uint;
|
||||
@ -809,6 +810,7 @@ pub extern fn ZigClangQualType_isRestrictQualified(self: struct_ZigClangQualType
|
||||
pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
|
||||
pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
|
||||
pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
|
||||
pub extern fn ZigClangType_isConstantArrayType(self: ?*const struct_ZigClangType) bool;
|
||||
pub extern fn ZigClangType_isRecordType(self: ?*const struct_ZigClangType) bool;
|
||||
pub extern fn ZigClangType_isArrayType(self: ?*const struct_ZigClangType) bool;
|
||||
pub extern fn ZigClangType_isBooleanType(self: ?*const struct_ZigClangType) bool;
|
||||
|
@ -485,6 +485,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
||||
block_scope.block_node = block_node;
|
||||
|
||||
var it = proto_node.params.iterator(0);
|
||||
var param_id: c_uint = 0;
|
||||
while (it.next()) |p| {
|
||||
const param = @fieldParentPtr(ast.Node.ParamDecl, "base", p.*);
|
||||
const param_name = if (param.name_token) |name_tok|
|
||||
@ -498,18 +499,27 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
||||
|
||||
const mangled_param_name = try block_scope.makeMangledName(c, param_name);
|
||||
|
||||
const c_param = ZigClangFunctionDecl_getParamDecl(fn_decl, param_id);
|
||||
const qual_type = ZigClangParmVarDecl_getOriginalType(c_param);
|
||||
const is_const = ZigClangQualType_isConstQualified(qual_type);
|
||||
|
||||
const arg_name = blk: {
|
||||
const bare_arg_name = try std.fmt.allocPrint(c.a(), "arg_{}", .{mangled_param_name});
|
||||
const param_prefix = if (is_const) "" else "arg_";
|
||||
const bare_arg_name = try std.fmt.allocPrint(c.a(), "{}{}", .{param_prefix, mangled_param_name});
|
||||
break :blk try block_scope.makeMangledName(c, bare_arg_name);
|
||||
};
|
||||
|
||||
const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name);
|
||||
node.eq_token = try appendToken(c, .Equal, "=");
|
||||
node.init_node = try transCreateNodeIdentifier(c, arg_name);
|
||||
node.semicolon_token = try appendToken(c, .Semicolon, ";");
|
||||
try block_node.statements.push(&node.base);
|
||||
param.name_token = try appendIdentifier(c, arg_name);
|
||||
_ = try appendToken(c, .Colon, ":");
|
||||
if (!is_const) {
|
||||
const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name);
|
||||
node.eq_token = try appendToken(c, .Equal, "=");
|
||||
node.init_node = try transCreateNodeIdentifier(c, arg_name);
|
||||
node.semicolon_token = try appendToken(c, .Semicolon, ";");
|
||||
try block_node.statements.push(&node.base);
|
||||
param.name_token = try appendIdentifier(c, arg_name);
|
||||
_ = try appendToken(c, .Colon, ":");
|
||||
}
|
||||
|
||||
param_id += 1;
|
||||
}
|
||||
|
||||
transCompoundStmtInline(rp, &block_scope.base, @ptrCast(*const ZigClangCompoundStmt, body_stmt), block_node) catch |err| switch (err) {
|
||||
@ -1982,7 +1992,8 @@ fn transInitListExprArray(
|
||||
const arr_type = ZigClangType_getAsArrayTypeUnsafe(ty);
|
||||
const child_qt = ZigClangArrayType_getElementType(arr_type);
|
||||
const init_count = ZigClangInitListExpr_getNumInits(expr);
|
||||
const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, ty);
|
||||
assert(ZigClangType_isConstantArrayType(@ptrCast(*const ZigClangType, arr_type)));
|
||||
const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, arr_type);
|
||||
const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
|
||||
const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, math.maxInt(usize));
|
||||
const leftover_count = all_count - init_count;
|
||||
|
2318
src/all_types.hpp
2318
src/all_types.hpp
File diff suppressed because it is too large
Load Diff
155
src/analyze.cpp
155
src/analyze.cpp
@ -199,7 +199,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent) {
|
||||
return scope;
|
||||
}
|
||||
|
||||
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime) {
|
||||
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime) {
|
||||
ScopeRuntime *scope = allocate<ScopeRuntime>(1);
|
||||
scope->is_comptime = is_comptime;
|
||||
init_scope(g, &scope->base, ScopeIdRuntime, node, parent);
|
||||
@ -3350,7 +3350,7 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i
|
||||
|
||||
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) {
|
||||
ZigFn *fn_entry = allocate<ZigFn>(1, "ZigFn");
|
||||
fn_entry->ir_executable = allocate<IrExecutable>(1, "IrExecutablePass1");
|
||||
fn_entry->ir_executable = allocate<IrExecutableSrc>(1, "IrExecutableSrc");
|
||||
|
||||
fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota;
|
||||
|
||||
@ -4097,7 +4097,7 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
|
||||
if (type_is_invalid(result->type)) {
|
||||
dest_decls_scope->any_imports_failed = true;
|
||||
using_namespace->base.resolution = TldResolutionInvalid;
|
||||
using_namespace->using_namespace_value = g->invalid_instruction->value;
|
||||
using_namespace->using_namespace_value = g->invalid_inst_gen->value;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4106,7 +4106,7 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
|
||||
buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&result->data.x_type->name)));
|
||||
dest_decls_scope->any_imports_failed = true;
|
||||
using_namespace->base.resolution = TldResolutionInvalid;
|
||||
using_namespace->using_namespace_value = g->invalid_instruction->value;
|
||||
using_namespace->using_namespace_value = g->invalid_inst_gen->value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -4667,12 +4667,12 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < fn->call_list.length; i += 1) {
|
||||
IrInstructionCallGen *call = fn->call_list.at(i);
|
||||
IrInstGenCall *call = fn->call_list.at(i);
|
||||
if (call->fn_entry == nullptr) {
|
||||
// TODO function pointer call here, could be anything
|
||||
continue;
|
||||
}
|
||||
switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async,
|
||||
switch (analyze_callee_async(g, fn, call->fn_entry, call->base.base.source_node, must_not_be_async,
|
||||
call->modifier))
|
||||
{
|
||||
case ErrorSemanticAnalyzeFail:
|
||||
@ -4690,10 +4690,10 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < fn->await_list.length; i += 1) {
|
||||
IrInstructionAwaitGen *await = fn->await_list.at(i);
|
||||
IrInstGenAwait *await = fn->await_list.at(i);
|
||||
// TODO If this is a noasync await, it doesn't count
|
||||
// https://github.com/ziglang/zig/issues/3157
|
||||
switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async,
|
||||
switch (analyze_callee_async(g, fn, await->target_fn, await->base.base.source_node, must_not_be_async,
|
||||
CallModifierNone))
|
||||
{
|
||||
case ErrorSemanticAnalyzeFail:
|
||||
@ -4784,7 +4784,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
|
||||
|
||||
if (g->verbose_ir) {
|
||||
fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name));
|
||||
ir_print(g, stderr, &fn->analyzed_executable, 4, IrPassGen);
|
||||
ir_print_gen(g, stderr, &fn->analyzed_executable, 4);
|
||||
fprintf(stderr, "}\n");
|
||||
}
|
||||
fn->anal_state = FnAnalStateComplete;
|
||||
@ -4827,7 +4827,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
|
||||
fprintf(stderr, "\n");
|
||||
ast_render(stderr, fn_table_entry->body_node, 4);
|
||||
fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name));
|
||||
ir_print(g, stderr, fn_table_entry->ir_executable, 4, IrPassSrc);
|
||||
ir_print_src(g, stderr, fn_table_entry->ir_executable, 4);
|
||||
fprintf(stderr, "}\n");
|
||||
}
|
||||
|
||||
@ -6191,13 +6191,13 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
ZigType *fn_type = get_async_fn_type(g, fn->type_entry);
|
||||
|
||||
if (fn->analyzed_executable.need_err_code_spill) {
|
||||
IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
|
||||
alloca_gen->base.id = IrInstructionIdAllocaGen;
|
||||
alloca_gen->base.source_node = fn->proto_node;
|
||||
alloca_gen->base.scope = fn->child_scope;
|
||||
IrInstGenAlloca *alloca_gen = allocate<IrInstGenAlloca>(1);
|
||||
alloca_gen->base.id = IrInstGenIdAlloca;
|
||||
alloca_gen->base.base.source_node = fn->proto_node;
|
||||
alloca_gen->base.base.scope = fn->child_scope;
|
||||
alloca_gen->base.value = allocate<ZigValue>(1, "ZigValue");
|
||||
alloca_gen->base.value->type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
|
||||
alloca_gen->base.ref_count = 1;
|
||||
alloca_gen->base.base.ref_count = 1;
|
||||
alloca_gen->name_hint = "";
|
||||
fn->alloca_gen_list.append(alloca_gen);
|
||||
fn->err_code_spill = &alloca_gen->base;
|
||||
@ -6205,18 +6205,18 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
|
||||
ZigType *largest_call_frame_type = nullptr;
|
||||
// Later we'll change this to be largest_call_frame_type instead of void.
|
||||
IrInstruction *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node,
|
||||
IrInstGen *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node,
|
||||
fn, g->builtin_types.entry_void, "@async_call_frame");
|
||||
|
||||
for (size_t i = 0; i < fn->call_list.length; i += 1) {
|
||||
IrInstructionCallGen *call = fn->call_list.at(i);
|
||||
IrInstGenCall *call = fn->call_list.at(i);
|
||||
if (call->new_stack != nullptr) {
|
||||
// don't need to allocate a frame for this
|
||||
continue;
|
||||
}
|
||||
ZigFn *callee = call->fn_entry;
|
||||
if (callee == nullptr) {
|
||||
add_node_error(g, call->base.source_node,
|
||||
add_node_error(g, call->base.base.source_node,
|
||||
buf_sprintf("function is not comptime-known; @asyncCall required"));
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
@ -6226,14 +6226,14 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
if (callee->anal_state == FnAnalStateProbing) {
|
||||
ErrorMsg *msg = add_node_error(g, fn->proto_node,
|
||||
buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name)));
|
||||
g->trace_err = add_error_note(g, msg, call->base.source_node,
|
||||
g->trace_err = add_error_note(g, msg, call->base.base.source_node,
|
||||
buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name)));
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
ZigType *callee_frame_type = get_fn_frame_type(g, callee);
|
||||
frame_type->data.frame.resolve_loop_type = callee_frame_type;
|
||||
frame_type->data.frame.resolve_loop_src_node = call->base.source_node;
|
||||
frame_type->data.frame.resolve_loop_src_node = call->base.base.source_node;
|
||||
|
||||
analyze_fn_body(g, callee);
|
||||
if (callee->anal_state == FnAnalStateInvalid) {
|
||||
@ -6249,7 +6249,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
if (!fn_is_async(callee))
|
||||
continue;
|
||||
|
||||
mark_suspension_point(call->base.scope);
|
||||
mark_suspension_point(call->base.base.scope);
|
||||
|
||||
if ((err = type_resolve(g, callee_frame_type, ResolveStatusSizeKnown))) {
|
||||
return err;
|
||||
@ -6271,7 +6271,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
// For example: foo() + await z
|
||||
// The funtion call result of foo() must be spilled.
|
||||
for (size_t i = 0; i < fn->await_list.length; i += 1) {
|
||||
IrInstructionAwaitGen *await = fn->await_list.at(i);
|
||||
IrInstGenAwait *await = fn->await_list.at(i);
|
||||
// TODO If this is a noasync await, it doesn't suspend
|
||||
// https://github.com/ziglang/zig/issues/3157
|
||||
if (await->base.value->special != ConstValSpecialRuntime) {
|
||||
@ -6293,52 +6293,51 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
}
|
||||
// This await is a suspend point, but it might not need a spill.
|
||||
// We do need to mark the ExprScope as having a suspend point in it.
|
||||
mark_suspension_point(await->base.scope);
|
||||
mark_suspension_point(await->base.base.scope);
|
||||
|
||||
if (await->result_loc != nullptr) {
|
||||
// If there's a result location, that is the spill
|
||||
continue;
|
||||
}
|
||||
if (await->base.ref_count == 0)
|
||||
if (await->base.base.ref_count == 0)
|
||||
continue;
|
||||
if (!type_has_bits(await->base.value->type))
|
||||
continue;
|
||||
await->result_loc = ir_create_alloca(g, await->base.scope, await->base.source_node, fn,
|
||||
await->result_loc = ir_create_alloca(g, await->base.base.scope, await->base.base.source_node, fn,
|
||||
await->base.value->type, "");
|
||||
}
|
||||
for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) {
|
||||
IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i);
|
||||
IrBasicBlockGen *block = fn->analyzed_executable.basic_block_list.at(block_i);
|
||||
for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) {
|
||||
IrInstruction *instruction = block->instruction_list.at(instr_i);
|
||||
if (instruction->id == IrInstructionIdSuspendFinish) {
|
||||
mark_suspension_point(instruction->scope);
|
||||
IrInstGen *instruction = block->instruction_list.at(instr_i);
|
||||
if (instruction->id == IrInstGenIdSuspendFinish) {
|
||||
mark_suspension_point(instruction->base.scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now that we've marked all the expr scopes that have to spill, we go over the instructions
|
||||
// and spill the relevant ones.
|
||||
for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) {
|
||||
IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i);
|
||||
IrBasicBlockGen *block = fn->analyzed_executable.basic_block_list.at(block_i);
|
||||
for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) {
|
||||
IrInstruction *instruction = block->instruction_list.at(instr_i);
|
||||
if (instruction->id == IrInstructionIdAwaitGen ||
|
||||
instruction->id == IrInstructionIdVarPtr ||
|
||||
instruction->id == IrInstructionIdDeclRef ||
|
||||
instruction->id == IrInstructionIdAllocaGen)
|
||||
IrInstGen *instruction = block->instruction_list.at(instr_i);
|
||||
if (instruction->id == IrInstGenIdAwait ||
|
||||
instruction->id == IrInstGenIdVarPtr ||
|
||||
instruction->id == IrInstGenIdAlloca)
|
||||
{
|
||||
// This instruction does its own spilling specially, or otherwise doesn't need it.
|
||||
continue;
|
||||
}
|
||||
if (instruction->value->special != ConstValSpecialRuntime)
|
||||
continue;
|
||||
if (instruction->ref_count == 0)
|
||||
if (instruction->base.ref_count == 0)
|
||||
continue;
|
||||
if ((err = type_resolve(g, instruction->value->type, ResolveStatusZeroBitsKnown)))
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
if (!type_has_bits(instruction->value->type))
|
||||
continue;
|
||||
if (scope_needs_spill(instruction->scope)) {
|
||||
instruction->spill = ir_create_alloca(g, instruction->scope, instruction->source_node,
|
||||
if (scope_needs_spill(instruction->base.scope)) {
|
||||
instruction->spill = ir_create_alloca(g, instruction->base.scope, instruction->base.source_node,
|
||||
fn, instruction->value->type, "");
|
||||
}
|
||||
}
|
||||
@ -6389,14 +6388,14 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
}
|
||||
|
||||
for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
|
||||
IrInstructionAllocaGen *instruction = fn->alloca_gen_list.at(alloca_i);
|
||||
IrInstGenAlloca *instruction = fn->alloca_gen_list.at(alloca_i);
|
||||
instruction->field_index = SIZE_MAX;
|
||||
ZigType *ptr_type = instruction->base.value->type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *child_type = ptr_type->data.pointer.child_type;
|
||||
if (!type_has_bits(child_type))
|
||||
continue;
|
||||
if (instruction->base.ref_count == 0)
|
||||
if (instruction->base.base.ref_count == 0)
|
||||
continue;
|
||||
if (instruction->base.value->special != ConstValSpecialRuntime) {
|
||||
if (const_ptr_pointee(nullptr, g, instruction->base.value, nullptr)->special !=
|
||||
@ -6407,7 +6406,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
}
|
||||
|
||||
frame_type->data.frame.resolve_loop_type = child_type;
|
||||
frame_type->data.frame.resolve_loop_src_node = instruction->base.source_node;
|
||||
frame_type->data.frame.resolve_loop_src_node = instruction->base.base.source_node;
|
||||
if ((err = type_resolve(g, child_type, ResolveStatusSizeKnown))) {
|
||||
return err;
|
||||
}
|
||||
@ -6421,7 +6420,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
instruction->field_index = fields.length;
|
||||
|
||||
src_assert(child_type->id != ZigTypeIdPointer || child_type->data.pointer.inferred_struct_field == nullptr,
|
||||
instruction->base.source_node);
|
||||
instruction->base.base.source_node);
|
||||
fields.append({name, child_type, instruction->align});
|
||||
}
|
||||
|
||||
@ -6554,8 +6553,10 @@ bool ir_get_var_is_comptime(ZigVar *var) {
|
||||
// As an optimization, is_comptime values which are constant are allowed
|
||||
// to be omitted from analysis. In this case, there is no child instruction
|
||||
// and we simply look at the unanalyzed const parent instruction.
|
||||
assert(var->is_comptime->value->type->id == ZigTypeIdBool);
|
||||
var->is_comptime_memoized_value = var->is_comptime->value->data.x_bool;
|
||||
assert(var->is_comptime->id == IrInstSrcIdConst);
|
||||
IrInstSrcConst *const_inst = reinterpret_cast<IrInstSrcConst *>(var->is_comptime);
|
||||
assert(const_inst->value->type->id == ZigTypeIdBool);
|
||||
var->is_comptime_memoized_value = const_inst->value->data.x_bool;
|
||||
var->is_comptime = nullptr;
|
||||
return var->is_comptime_memoized_value;
|
||||
}
|
||||
@ -9193,21 +9194,6 @@ void src_assert(bool ok, AstNode *source_node) {
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
|
||||
IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
|
||||
ZigType *var_type, const char *name_hint)
|
||||
{
|
||||
IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
|
||||
alloca_gen->base.id = IrInstructionIdAllocaGen;
|
||||
alloca_gen->base.source_node = source_node;
|
||||
alloca_gen->base.scope = scope;
|
||||
alloca_gen->base.value = allocate<ZigValue>(1, "ZigValue");
|
||||
alloca_gen->base.value->type = get_pointer_to_type(g, var_type, false);
|
||||
alloca_gen->base.ref_count = 1;
|
||||
alloca_gen->name_hint = name_hint;
|
||||
fn->alloca_gen_list.append(alloca_gen);
|
||||
return &alloca_gen->base;
|
||||
}
|
||||
|
||||
Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
|
||||
ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path)
|
||||
{
|
||||
@ -9268,8 +9254,17 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
|
||||
}
|
||||
|
||||
|
||||
void IrExecutable::src() {
|
||||
IrExecutable *it;
|
||||
void IrExecutableSrc::src() {
|
||||
if (this->source_node != nullptr) {
|
||||
this->source_node->src();
|
||||
}
|
||||
if (this->parent_exec != nullptr) {
|
||||
this->parent_exec->src();
|
||||
}
|
||||
}
|
||||
|
||||
void IrExecutableGen::src() {
|
||||
IrExecutableGen *it;
|
||||
for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) {
|
||||
it->source_node->src();
|
||||
}
|
||||
@ -9357,3 +9352,41 @@ bool type_is_numeric(ZigType *ty) {
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
// float ops that take a single argument
|
||||
//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign, lround, llround, lrint, llrint
|
||||
const char *float_op_to_name(BuiltinFnId op) {
|
||||
switch (op) {
|
||||
case BuiltinFnIdSqrt:
|
||||
return "sqrt";
|
||||
case BuiltinFnIdSin:
|
||||
return "sin";
|
||||
case BuiltinFnIdCos:
|
||||
return "cos";
|
||||
case BuiltinFnIdExp:
|
||||
return "exp";
|
||||
case BuiltinFnIdExp2:
|
||||
return "exp2";
|
||||
case BuiltinFnIdLog:
|
||||
return "log";
|
||||
case BuiltinFnIdLog10:
|
||||
return "log10";
|
||||
case BuiltinFnIdLog2:
|
||||
return "log2";
|
||||
case BuiltinFnIdFabs:
|
||||
return "fabs";
|
||||
case BuiltinFnIdFloor:
|
||||
return "floor";
|
||||
case BuiltinFnIdCeil:
|
||||
return "ceil";
|
||||
case BuiltinFnIdTrunc:
|
||||
return "trunc";
|
||||
case BuiltinFnIdNearbyInt:
|
||||
return "nearbyint";
|
||||
case BuiltinFnIdRound:
|
||||
return "round";
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent);
|
||||
ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);
|
||||
ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);
|
||||
Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
|
||||
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
|
||||
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime);
|
||||
Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent);
|
||||
ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
|
||||
|
||||
@ -271,8 +271,6 @@ ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);
|
||||
|
||||
void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn);
|
||||
|
||||
IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
|
||||
ZigType *var_type, const char *name_hint);
|
||||
Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,
|
||||
ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
|
||||
ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
|
||||
@ -281,4 +279,5 @@ void copy_const_val(ZigValue *dest, ZigValue *src);
|
||||
bool type_has_optional_repr(ZigType *ty);
|
||||
bool is_opt_err_set(ZigType *ty);
|
||||
bool type_is_numeric(ZigType *ty);
|
||||
const char *float_op_to_name(BuiltinFnId op);
|
||||
#endif
|
||||
|
893
src/codegen.cpp
893
src/codegen.cpp
File diff suppressed because it is too large
Load Diff
13735
src/ir.cpp
13735
src/ir.cpp
File diff suppressed because it is too large
Load Diff
20
src/ir.hpp
20
src/ir.hpp
@ -10,33 +10,33 @@
|
||||
|
||||
#include "all_types.hpp"
|
||||
|
||||
enum IrPass {
|
||||
IrPassSrc,
|
||||
IrPassGen,
|
||||
};
|
||||
|
||||
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
|
||||
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable);
|
||||
bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
|
||||
|
||||
IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
|
||||
ZigType *var_type, const char *name_hint);
|
||||
|
||||
ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
||||
ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
|
||||
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
||||
IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
|
||||
IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
|
||||
|
||||
Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val);
|
||||
|
||||
ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
|
||||
ZigType *ir_analyze(CodeGen *g, IrExecutableSrc *old_executable, IrExecutableGen *new_executable,
|
||||
ZigType *expected_type, AstNode *expected_type_source_node);
|
||||
|
||||
bool ir_has_side_effects(IrInstruction *instruction);
|
||||
bool ir_inst_gen_has_side_effects(IrInstGen *inst);
|
||||
bool ir_inst_src_has_side_effects(IrInstSrc *inst);
|
||||
|
||||
struct IrAnalyze;
|
||||
ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val,
|
||||
AstNode *source_node);
|
||||
const char *float_op_to_name(BuiltinFnId op);
|
||||
|
||||
// for debugging purposes
|
||||
void dbg_ir_break(const char *src_file, uint32_t line);
|
||||
void dbg_ir_clear(void);
|
||||
|
||||
void destroy_instruction_gen(IrInstGen *inst);
|
||||
|
||||
#endif
|
||||
|
3389
src/ir_print.cpp
3389
src/ir_print.cpp
File diff suppressed because it is too large
Load Diff
@ -12,11 +12,14 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass);
|
||||
void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass);
|
||||
void ir_print_const_expr(CodeGen *codegen, FILE *f, ZigValue *value, int indent_size, IrPass pass);
|
||||
void ir_print_basic_block(CodeGen *codegen, FILE *f, IrBasicBlock *bb, int indent_size, IrPass pass);
|
||||
void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int indent_size);
|
||||
void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size);
|
||||
void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *inst, int indent_size);
|
||||
void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *inst, int indent_size);
|
||||
void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size);
|
||||
void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, int indent_size);
|
||||
|
||||
const char* ir_instruction_type_str(IrInstructionId id);
|
||||
const char* ir_inst_src_type_str(IrInstSrcId id);
|
||||
const char* ir_inst_gen_type_str(IrInstGenId id);
|
||||
|
||||
#endif
|
||||
|
10
src/main.cpp
10
src/main.cpp
@ -144,15 +144,15 @@ static int print_libc_usage(const char *arg0, FILE *file, int return_code) {
|
||||
"You can save this into a file and then edit the paths to create a cross\n"
|
||||
"compilation libc kit. Then you can pass `--libc [file]` for Zig to use it.\n"
|
||||
"\n"
|
||||
"When compiling natively and no `--libc` argument provided, Zig automatically\n"
|
||||
"creates zig-cache/native_libc.txt so that it does not have to detect libc\n"
|
||||
"on every invocation. You can remove this file to have Zig re-detect the\n"
|
||||
"native libc.\n"
|
||||
"When compiling natively and no `--libc` argument provided, Zig will create\n"
|
||||
"`%s/native_libc.txt`\n"
|
||||
"so that it does not have to detect libc on every invocation. You can remove\n"
|
||||
"this file to have Zig re-detect the native libc.\n"
|
||||
"\n\n"
|
||||
"Usage: %s libc [file]\n"
|
||||
"\n"
|
||||
"Parse a libc installation text file and validate it.\n"
|
||||
, arg0, arg0);
|
||||
, arg0, buf_ptr(get_global_cache_dir()), arg0);
|
||||
return return_code;
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) {
|
||||
}
|
||||
|
||||
static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) {
|
||||
AstNode *node = allocate<AstNode>(1);
|
||||
AstNode *node = allocate<AstNode>(1, "AstNode");
|
||||
node->type = type;
|
||||
node->owner = pc->owner;
|
||||
return node;
|
||||
|
@ -1625,6 +1625,10 @@ unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionD
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self) {
|
||||
return bitcast(reinterpret_cast<const clang::ParmVarDecl *>(self)->getOriginalType());
|
||||
}
|
||||
|
||||
const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) {
|
||||
const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl);
|
||||
const clang::RecordDecl *definition = record_decl->getDefinition();
|
||||
@ -1877,6 +1881,11 @@ bool ZigClangType_isRecordType(const ZigClangType *self) {
|
||||
return casted->isRecordType();
|
||||
}
|
||||
|
||||
bool ZigClangType_isConstantArrayType(const ZigClangType *self) {
|
||||
auto casted = reinterpret_cast<const clang::Type *>(self);
|
||||
return casted->isConstantArrayType();
|
||||
}
|
||||
|
||||
const char *ZigClangType_getTypeClassName(const ZigClangType *self) {
|
||||
auto casted = reinterpret_cast<const clang::Type *>(self);
|
||||
return casted->getTypeClassName();
|
||||
|
@ -866,6 +866,8 @@ ZIG_EXTERN_C const char* ZigClangVarDecl_getSectionAttribute(const struct ZigCla
|
||||
ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx);
|
||||
ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx);
|
||||
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self);
|
||||
|
||||
ZIG_EXTERN_C bool ZigClangRecordDecl_getPackedAttribute(const struct ZigClangRecordDecl *);
|
||||
ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *);
|
||||
ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *);
|
||||
@ -945,6 +947,7 @@ ZIG_EXTERN_C bool ZigClangType_isBooleanType(const struct ZigClangType *self);
|
||||
ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
|
||||
ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self);
|
||||
ZIG_EXTERN_C bool ZigClangType_isRecordType(const struct ZigClangType *self);
|
||||
ZIG_EXTERN_C bool ZigClangType_isConstantArrayType(const ZigClangType *self);
|
||||
ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);
|
||||
ZIG_EXTERN_C const struct ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const struct ZigClangType *self);
|
||||
ZIG_EXTERN_C const ZigClangRecordType *ZigClangType_getAsRecordType(const ZigClangType *self);
|
||||
|
@ -51,11 +51,15 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in main (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in std.start.main (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-fast
|
||||
@ -74,13 +78,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in foo (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in main (test)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in std.start.main (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in std.start.main (test)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-fast
|
||||
@ -99,17 +111,33 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:12:5: [address] in make_error (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in bar (test)
|
||||
\\ return make_error();
|
||||
\\ ^
|
||||
\\source.zig:4:5: [address] in foo (test)
|
||||
\\ try bar();
|
||||
\\ ^
|
||||
\\source.zig:16:5: [address] in main (test)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:12:5: [address] in std.start.main (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in std.start.main (test)
|
||||
\\ return make_error();
|
||||
\\ ^
|
||||
\\source.zig:4:5: [address] in std.start.main (test)
|
||||
\\ try bar();
|
||||
\\ ^
|
||||
\\source.zig:16:5: [address] in std.start.main (test)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-fast
|
||||
@ -130,11 +158,15 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in main (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-fast
|
||||
@ -153,13 +185,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in foo (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in main (test)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in std.start.posixCallMainAndExit (test)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-fast
|
||||
@ -178,17 +218,33 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:12:5: [address] in make_error (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in bar (test)
|
||||
\\ return make_error();
|
||||
\\ ^
|
||||
\\source.zig:4:5: [address] in foo (test)
|
||||
\\ try bar();
|
||||
\\ ^
|
||||
\\source.zig:16:5: [address] in main (test)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:12:5: [address] in std.start.posixCallMainAndExit (test)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in std.start.posixCallMainAndExit (test)
|
||||
\\ return make_error();
|
||||
\\ ^
|
||||
\\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test)
|
||||
\\ try bar();
|
||||
\\ ^
|
||||
\\source.zig:16:5: [address] in std.start.posixCallMainAndExit (test)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-fast
|
||||
@ -209,11 +265,15 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in _main.0 (test.o)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in _main (test.o)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-fast
|
||||
@ -232,13 +292,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in _foo (test.o)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in _main.0 (test.o)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in _main (test.o)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in _main (test.o)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-fast
|
||||
@ -257,17 +325,33 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:12:5: [address] in _make_error (test.o)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in _bar (test.o)
|
||||
\\ return make_error();
|
||||
\\ ^
|
||||
\\source.zig:4:5: [address] in _foo (test.o)
|
||||
\\ try bar();
|
||||
\\ ^
|
||||
\\source.zig:16:5: [address] in _main.0 (test.o)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:12:5: [address] in _main (test.o)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in _main (test.o)
|
||||
\\ return make_error();
|
||||
\\ ^
|
||||
\\source.zig:4:5: [address] in _main (test.o)
|
||||
\\ try bar();
|
||||
\\ ^
|
||||
\\source.zig:16:5: [address] in _main (test.o)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-fast
|
||||
@ -288,6 +372,8 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in main (test.obj)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
@ -309,7 +395,11 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:4:5: [address] in foo (test.obj)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in main (test.obj)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
@ -331,9 +421,17 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
// debug
|
||||
\\error: TheSkyIsFalling
|
||||
\\source.zig:12:5: [address] in make_error (test.obj)
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\ ^
|
||||
\\source.zig:8:5: [address] in bar (test.obj)
|
||||
\\ return make_error();
|
||||
\\ ^
|
||||
\\source.zig:4:5: [address] in foo (test.obj)
|
||||
\\ try bar();
|
||||
\\ ^
|
||||
\\source.zig:16:5: [address] in main (test.obj)
|
||||
\\ try foo();
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
// release-safe
|
||||
|
@ -3,6 +3,31 @@ const builtin = @import("builtin");
|
||||
const Target = @import("std").Target;
|
||||
|
||||
pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
cases.add("array initializer w/ typedef",
|
||||
\\typedef unsigned char uuid_t[16];
|
||||
\\static const uuid_t UUID_NULL __attribute__ ((unused)) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
, &[_][]const u8{
|
||||
\\pub const uuid_t = [16]u8;
|
||||
\\pub const UUID_NULL: uuid_t = .{
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
|
||||
\\};
|
||||
});
|
||||
|
||||
cases.add("empty declaration",
|
||||
\\;
|
||||
, &[_][]const u8{""});
|
||||
@ -2606,4 +2631,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return foo((@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(c)))) != @intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(b))))));
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("Don't make const parameters mutable",
|
||||
\\int max(const int x, int y) {
|
||||
\\ return (x > y) ? x : y;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(x: c_int, arg_y: c_int) c_int {
|
||||
\\ var y = arg_y;
|
||||
\\ return if (x > y) x else y;
|
||||
\\}
|
||||
});
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user