Support Asahi Linux (aarch64-linux)
This commit is contained in:
parent
3c6aaf67d0
commit
128a3ee508
@ -648,12 +648,22 @@ pub fn compileCSourceFile(context: *const Context, arguments: []const []const u8
|
|||||||
"/usr/lib/clang/17/include",
|
"/usr/lib/clang/17/include",
|
||||||
"/usr/include",
|
"/usr/include",
|
||||||
"/usr/include/x86_64-linux-gnu",
|
"/usr/include/x86_64-linux-gnu",
|
||||||
} else &.{
|
} else switch (@import("builtin").cpu.arch) {
|
||||||
"/usr/include/c++/13.2.1",
|
.x86_64 => &.{
|
||||||
"/usr/include/c++/13.2.1/x86_64-pc-linux-gnu",
|
"/usr/include/c++/13.2.1",
|
||||||
"/usr/lib/clang/17/include",
|
"/usr/include/c++/13.2.1/x86_64-pc-linux-gnu",
|
||||||
"/usr/include",
|
"/usr/lib/clang/17/include",
|
||||||
"/usr/include/linux",
|
"/usr/include",
|
||||||
|
"/usr/include/linux",
|
||||||
|
},
|
||||||
|
.aarch64 => &.{
|
||||||
|
"/usr/include/c++/13",
|
||||||
|
"/usr/include/c++/13/aarch64-redhat-linux",
|
||||||
|
"/usr/lib/clang/17/include",
|
||||||
|
"/usr/include",
|
||||||
|
"/usr/include/linux",
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
},
|
},
|
||||||
else => unreachable, //@compileError("ABI not supported"),
|
else => unreachable, //@compileError("ABI not supported"),
|
||||||
},
|
},
|
||||||
@ -2771,28 +2781,25 @@ const Abi = enum {
|
|||||||
pub fn buildExecutable(context: *const Context, arguments: []const []const u8, options: ExecutableOptions) !void {
|
pub fn buildExecutable(context: *const Context, arguments: []const []const u8, options: ExecutableOptions) !void {
|
||||||
var maybe_executable_path: ?[]const u8 = null;
|
var maybe_executable_path: ?[]const u8 = null;
|
||||||
var maybe_main_package_path: ?[]const u8 = null;
|
var maybe_main_package_path: ?[]const u8 = null;
|
||||||
var arch: Arch = undefined;
|
|
||||||
var os: Os = undefined;
|
|
||||||
var abi: Abi = undefined;
|
|
||||||
|
|
||||||
switch (@import("builtin").os.tag) {
|
// TODO: make these mutable
|
||||||
.linux => {
|
const arch: Arch = switch (@import("builtin").cpu.arch) {
|
||||||
arch = .x86_64;
|
.aarch64 => .aarch64,
|
||||||
os = .linux;
|
.x86_64 => .x86_64,
|
||||||
abi = .gnu;
|
|
||||||
},
|
|
||||||
.macos => {
|
|
||||||
arch = .aarch64;
|
|
||||||
os = .macos;
|
|
||||||
abi = .none;
|
|
||||||
},
|
|
||||||
.windows => {
|
|
||||||
arch = .x86_64;
|
|
||||||
os = .windows;
|
|
||||||
abi = .gnu;
|
|
||||||
},
|
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
};
|
||||||
|
const os: Os = switch (@import("builtin").os.tag) {
|
||||||
|
.linux => .linux,
|
||||||
|
.macos => .macos,
|
||||||
|
.windows => .windows,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
const abi: Abi = switch (@import("builtin").os.tag) {
|
||||||
|
.linux => .gnu,
|
||||||
|
.macos => .none,
|
||||||
|
.windows => .gnu,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
var maybe_only_parse: ?bool = null;
|
var maybe_only_parse: ?bool = null;
|
||||||
var link_libc = false;
|
var link_libc = false;
|
||||||
@ -2982,7 +2989,7 @@ pub fn buildExecutable(context: *const Context, arguments: []const []const u8, o
|
|||||||
try unit.compile(context);
|
try unit.compile(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createUnit(context: *const Context, arguments: struct{
|
fn createUnit(context: *const Context, arguments: struct {
|
||||||
main_package_path: []const u8,
|
main_package_path: []const u8,
|
||||||
executable_path: []const u8,
|
executable_path: []const u8,
|
||||||
object_path: []const u8,
|
object_path: []const u8,
|
||||||
@ -2996,7 +3003,7 @@ fn createUnit(context: *const Context, arguments: struct{
|
|||||||
name: []const u8,
|
name: []const u8,
|
||||||
is_test: bool,
|
is_test: bool,
|
||||||
c_source_files: []const []const u8,
|
c_source_files: []const []const u8,
|
||||||
}) !*Unit{
|
}) !*Unit {
|
||||||
const unit = try context.allocator.create(Unit);
|
const unit = try context.allocator.create(Unit);
|
||||||
unit.* = .{
|
unit.* = .{
|
||||||
.descriptor = .{
|
.descriptor = .{
|
||||||
@ -4687,86 +4694,89 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
.@"asm" => {
|
.@"asm" => {
|
||||||
const architecture = InlineAssembly.x86_64;
|
switch (unit.descriptor.arch) {
|
||||||
|
inline else => |arch| {
|
||||||
|
const architecture = @field(InlineAssembly, @tagName(arch));
|
||||||
|
assert(argument_node_list.len == 1);
|
||||||
|
const assembly_block_node = unit.getNode(argument_node_list[0]);
|
||||||
|
const instruction_node_list = unit.getNodeList(assembly_block_node.left);
|
||||||
|
var instructions = try context.arena.new_array(InlineAssembly.Instruction.Index, instruction_node_list.len);
|
||||||
|
instructions.len = 0;
|
||||||
|
|
||||||
assert(argument_node_list.len == 1);
|
for (instruction_node_list) |assembly_statement_node_index| {
|
||||||
const assembly_block_node = unit.getNode(argument_node_list[0]);
|
const assembly_instruction_node = unit.getNode(assembly_statement_node_index);
|
||||||
const instruction_node_list = unit.getNodeList(assembly_block_node.left);
|
const assembly_instruction_name_node = unit.getNode(assembly_instruction_node.left);
|
||||||
var instructions = try context.arena.new_array(InlineAssembly.Instruction.Index, instruction_node_list.len);
|
const instruction_name = unit.getExpectedTokenBytes(assembly_instruction_name_node.token, .identifier);
|
||||||
instructions.len = 0;
|
const instruction = inline for (@typeInfo(architecture.Instruction).Enum.fields) |instruction_enum_field| {
|
||||||
|
if (byte_equal(instruction_name, instruction_enum_field.name)) {
|
||||||
|
break @field(architecture.Instruction, instruction_enum_field.name);
|
||||||
|
}
|
||||||
|
} else unreachable;
|
||||||
|
const operand_nodes = unit.getNodeList(assembly_instruction_node.right);
|
||||||
|
|
||||||
for (instruction_node_list) |assembly_statement_node_index| {
|
var operands = try context.arena.new_array(InlineAssembly.Operand, operand_nodes.len);
|
||||||
const assembly_instruction_node = unit.getNode(assembly_statement_node_index);
|
operands.len = 0;
|
||||||
const assembly_instruction_name_node = unit.getNode(assembly_instruction_node.left);
|
|
||||||
const instruction_name = unit.getExpectedTokenBytes(assembly_instruction_name_node.token, .identifier);
|
|
||||||
const instruction = inline for (@typeInfo(architecture.Instruction).Enum.fields) |instruction_enum_field| {
|
|
||||||
if (byte_equal(instruction_name, instruction_enum_field.name)) {
|
|
||||||
break @field(architecture.Instruction, instruction_enum_field.name);
|
|
||||||
}
|
|
||||||
} else unreachable;
|
|
||||||
const operand_nodes = unit.getNodeList(assembly_instruction_node.right);
|
|
||||||
|
|
||||||
var operands = try context.arena.new_array(InlineAssembly.Operand, operand_nodes.len);
|
for (operand_nodes) |operand_node_index| {
|
||||||
operands.len = 0;
|
const operand_node = unit.getNode(operand_node_index);
|
||||||
|
const operand: InlineAssembly.Operand = switch (operand_node.id) {
|
||||||
|
.assembly_register => blk: {
|
||||||
|
const register_name = unit.getExpectedTokenBytes(operand_node.token, .identifier);
|
||||||
|
|
||||||
for (operand_nodes) |operand_node_index| {
|
const register = inline for (@typeInfo(architecture.Register).Enum.fields) |register_enum_field| {
|
||||||
const operand_node = unit.getNode(operand_node_index);
|
if (byte_equal(register_name, register_enum_field.name)) {
|
||||||
const operand: InlineAssembly.Operand = switch (operand_node.id) {
|
break @field(architecture.Register, register_enum_field.name);
|
||||||
.assembly_register => blk: {
|
}
|
||||||
const register_name = unit.getExpectedTokenBytes(operand_node.token, .identifier);
|
} else unreachable;
|
||||||
|
break :blk .{
|
||||||
const register = inline for (@typeInfo(architecture.Register).Enum.fields) |register_enum_field| {
|
.register = @intFromEnum(register),
|
||||||
if (byte_equal(register_name, register_enum_field.name)) {
|
};
|
||||||
break @field(architecture.Register, register_enum_field.name);
|
},
|
||||||
}
|
.number_literal => switch (std.zig.parseNumberLiteral(unit.getExpectedTokenBytes(operand_node.token, .number_literal))) {
|
||||||
} else unreachable;
|
.int => |integer| .{
|
||||||
break :blk .{
|
.number_literal = integer,
|
||||||
.register = @intFromEnum(register),
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
.assembly_code_expression => .{
|
||||||
|
.value = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, operand_node.left, .left),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const index = operands.len;
|
||||||
|
operands.len += 1;
|
||||||
|
operands[index] = operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
const instruction_index = unit.assembly_instructions.append_index(.{
|
||||||
|
.id = @intFromEnum(instruction),
|
||||||
|
.operands = operands,
|
||||||
|
});
|
||||||
|
|
||||||
|
const index = instructions.len;
|
||||||
|
instructions.len += 1;
|
||||||
|
instructions[index] = instruction_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
const inline_assembly = unit.inline_assembly.append_index(.{
|
||||||
|
.instructions = instructions,
|
||||||
|
});
|
||||||
|
|
||||||
|
const inline_asm = unit.instructions.append_index(.{
|
||||||
|
.inline_assembly = inline_assembly,
|
||||||
|
});
|
||||||
|
try builder.appendInstruction(unit, inline_asm);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.value = .{
|
||||||
|
.runtime = inline_asm,
|
||||||
},
|
},
|
||||||
.number_literal => switch (std.zig.parseNumberLiteral(unit.getExpectedTokenBytes(operand_node.token, .number_literal))) {
|
// TODO: WARN fix
|
||||||
.int => |integer| .{
|
.type = .noreturn,
|
||||||
.number_literal = integer,
|
|
||||||
},
|
|
||||||
else => |t| @panic(@tagName(t)),
|
|
||||||
},
|
|
||||||
.assembly_code_expression => .{
|
|
||||||
.value = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, operand_node.left, .left),
|
|
||||||
},
|
|
||||||
else => |t| @panic(@tagName(t)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const index = operands.len;
|
|
||||||
operands.len += 1;
|
|
||||||
operands[index] = operand;
|
|
||||||
}
|
|
||||||
|
|
||||||
const instruction_index = unit.assembly_instructions.append_index(.{
|
|
||||||
.id = @intFromEnum(instruction),
|
|
||||||
.operands = operands,
|
|
||||||
});
|
|
||||||
|
|
||||||
const index = instructions.len;
|
|
||||||
instructions.len += 1;
|
|
||||||
instructions[index] = instruction_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
const inline_assembly = unit.inline_assembly.append_index(.{
|
|
||||||
.instructions = instructions,
|
|
||||||
});
|
|
||||||
|
|
||||||
const inline_asm = unit.instructions.append_index(.{
|
|
||||||
.inline_assembly = inline_assembly,
|
|
||||||
});
|
|
||||||
try builder.appendInstruction(unit, inline_asm);
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.value = .{
|
|
||||||
.runtime = inline_asm,
|
|
||||||
},
|
},
|
||||||
// TODO: WARN fix
|
}
|
||||||
.type = .noreturn,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
.cast => {
|
.cast => {
|
||||||
assert(argument_node_list.len == 1);
|
assert(argument_node_list.len == 1);
|
||||||
@ -6289,7 +6299,7 @@ pub const Builder = struct {
|
|||||||
const pointer_to_global = try unit.getPointerType(.{
|
const pointer_to_global = try unit.getPointerType(.{
|
||||||
.type = global.declaration.type,
|
.type = global.declaration.type,
|
||||||
.termination = switch (type_expect) {
|
.termination = switch (type_expect) {
|
||||||
.none => .none,
|
.none, .cast => .none,
|
||||||
.type => |type_index| switch (unit.types.get(type_index).*) {
|
.type => |type_index| switch (unit.types.get(type_index).*) {
|
||||||
.pointer => |pointer| pointer.termination,
|
.pointer => |pointer| pointer.termination,
|
||||||
else => .none,
|
else => .none,
|
||||||
@ -6297,7 +6307,7 @@ pub const Builder = struct {
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
.mutability = switch (type_expect) {
|
.mutability = switch (type_expect) {
|
||||||
.none => .@"var",
|
.none, .cast => .@"var",
|
||||||
.type => |type_index| switch (unit.types.get(type_index).*) {
|
.type => |type_index| switch (unit.types.get(type_index).*) {
|
||||||
.pointer => |pointer| pointer.mutability,
|
.pointer => |pointer| pointer.mutability,
|
||||||
else => .@"var",
|
else => .@"var",
|
||||||
@ -10034,6 +10044,73 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.character_literal => return try unit.resolve_character_literal(node_index),
|
.character_literal => return try unit.resolve_character_literal(node_index),
|
||||||
|
.negation => {
|
||||||
|
assert(node.left != .null);
|
||||||
|
assert(node.right == .null);
|
||||||
|
|
||||||
|
const value = try builder.resolveComptimeValue(unit, context, type_expect, .{}, node.left, null, .right, &.{}, null, &.{});
|
||||||
|
switch (value) {
|
||||||
|
.constant_int => |constant_int| switch (type_expect) {
|
||||||
|
.type => |type_index| {
|
||||||
|
assert(type_index == value.type);
|
||||||
|
const expected_type = unit.types.get(type_index);
|
||||||
|
switch (expected_type.*) {
|
||||||
|
.integer => |integer| switch (integer.kind) {
|
||||||
|
.materialized_int => {
|
||||||
|
assert(integer.signedness == .signed);
|
||||||
|
var v: i64 = @intCast(constant_int.value);
|
||||||
|
v = 0 - v;
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.constant_int = .{
|
||||||
|
.value = @bitCast(v),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
.comptime_int => |ct_int| switch (type_expect) {
|
||||||
|
.type => |type_index| switch (unit.types.get(type_index).*) {
|
||||||
|
.integer => |integer| switch (integer.kind) {
|
||||||
|
.materialized_int => {
|
||||||
|
assert(integer.signedness == .signed);
|
||||||
|
var v = switch (ct_int.signedness) {
|
||||||
|
.signed => 0 - @as(i64, @intCast(ct_int.value)),
|
||||||
|
.unsigned => @as(i64, @intCast(ct_int.value)),
|
||||||
|
};
|
||||||
|
v = 0 - v;
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.constant_int = .{
|
||||||
|
.value = @bitCast(v),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
.none => {
|
||||||
|
return .{
|
||||||
|
.comptime_int = .{
|
||||||
|
.value = ct_int.value,
|
||||||
|
.signedness = switch (ct_int.signedness) {
|
||||||
|
.unsigned => .signed,
|
||||||
|
.signed => .unsigned,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12299,6 +12376,7 @@ pub const Builder = struct {
|
|||||||
.negation => block: {
|
.negation => block: {
|
||||||
assert(node.left != .null);
|
assert(node.left != .null);
|
||||||
assert(node.right == .null);
|
assert(node.right == .null);
|
||||||
|
|
||||||
const value = try builder.resolveRuntimeValue(unit, context, type_expect, node.left, .right);
|
const value = try builder.resolveRuntimeValue(unit, context, type_expect, node.left, .right);
|
||||||
|
|
||||||
switch (value.value) {
|
switch (value.value) {
|
||||||
@ -18095,6 +18173,51 @@ pub const InlineAssembly = struct {
|
|||||||
rdi,
|
rdi,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const aarch64 = struct {
|
||||||
|
pub const Instruction = enum {
|
||||||
|
b,
|
||||||
|
mov,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Register = enum {
|
||||||
|
fp,
|
||||||
|
lr,
|
||||||
|
sp,
|
||||||
|
x0,
|
||||||
|
x1,
|
||||||
|
x2,
|
||||||
|
x3,
|
||||||
|
x4,
|
||||||
|
x5,
|
||||||
|
x6,
|
||||||
|
x7,
|
||||||
|
x8,
|
||||||
|
x9,
|
||||||
|
x10,
|
||||||
|
x11,
|
||||||
|
x12,
|
||||||
|
x13,
|
||||||
|
x14,
|
||||||
|
x15,
|
||||||
|
x16,
|
||||||
|
x17,
|
||||||
|
x18,
|
||||||
|
x19,
|
||||||
|
x20,
|
||||||
|
x21,
|
||||||
|
x22,
|
||||||
|
x23,
|
||||||
|
x24,
|
||||||
|
x25,
|
||||||
|
x26,
|
||||||
|
x27,
|
||||||
|
x28,
|
||||||
|
x29,
|
||||||
|
x30,
|
||||||
|
x31,
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const LogKind = enum {
|
const LogKind = enum {
|
||||||
|
@ -2674,12 +2674,72 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
_ = assembly_statements.pop();
|
_ = assembly_statements.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
assembly_statements.appendSliceAssumeCapacity("\n\t");
|
assembly_statements.appendSliceAssumeCapacity("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = assembly_statements.pop();
|
||||||
|
|
||||||
// try constraints.append_slice(context.allocator, ",~{dirflag},~{fpsr},~{flags}");
|
// try constraints.append_slice(context.allocator, ",~{dirflag},~{fpsr},~{flags}");
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
.aarch64 => {
|
||||||
|
for (assembly_block.instructions) |assembly_instruction_index| {
|
||||||
|
const instruction = unit.assembly_instructions.get(assembly_instruction_index);
|
||||||
|
const instruction_id: Compilation.InlineAssembly.aarch64.Instruction = @enumFromInt(instruction.id);
|
||||||
|
assembly_statements.appendSliceAssumeCapacity(@tagName(instruction_id));
|
||||||
|
assembly_statements.appendAssumeCapacity(' ');
|
||||||
|
|
||||||
|
if (instruction.operands.len > 0) {
|
||||||
|
for (instruction.operands) |operand| {
|
||||||
|
switch (operand) {
|
||||||
|
.register => |register_value| {
|
||||||
|
const register: Compilation.InlineAssembly.aarch64.Register = @enumFromInt(register_value);
|
||||||
|
assembly_statements.appendSliceAssumeCapacity(@tagName(register));
|
||||||
|
},
|
||||||
|
.number_literal => |literal| {
|
||||||
|
var buffer: [65]u8 = undefined;
|
||||||
|
const number_literal = format_int(&buffer, literal, 10, false);
|
||||||
|
const slice_ptr = number_literal.ptr - 1;
|
||||||
|
const literal_slice = slice_ptr[0 .. number_literal.len + 1];
|
||||||
|
literal_slice[0] = '#';
|
||||||
|
assembly_statements.appendSliceAssumeCapacity(try context.arena.duplicate_bytes(literal_slice));
|
||||||
|
},
|
||||||
|
.value => |sema_value| {
|
||||||
|
if (llvm.llvm_value_map.get(sema_value)) |v| {
|
||||||
|
_ = v; // autofix
|
||||||
|
unreachable;
|
||||||
|
} else {
|
||||||
|
const value = try llvm.emitLeftValue(unit, context, sema_value);
|
||||||
|
var buffer: [65]u8 = undefined;
|
||||||
|
const operand_number = format_int(&buffer, operand_values.len, 16, false);
|
||||||
|
const slice_ptr = operand_number.ptr - 2;
|
||||||
|
const operand_slice = slice_ptr[0 .. operand_number.len + 2];
|
||||||
|
operand_slice[0] = '$';
|
||||||
|
operand_slice[1] = '{';
|
||||||
|
var new_buffer: [65]u8 = undefined;
|
||||||
|
@memcpy(new_buffer[0..operand_slice.len], operand_slice);
|
||||||
|
new_buffer[operand_slice.len] = '}';
|
||||||
|
const new_slice = try context.arena.duplicate_bytes(new_buffer[0 .. operand_slice.len + 1]);
|
||||||
|
assembly_statements.appendSliceAssumeCapacity(new_slice);
|
||||||
|
operand_values.appendAssumeCapacity(value);
|
||||||
|
const value_type = value.getType();
|
||||||
|
operand_types.appendAssumeCapacity(value_type);
|
||||||
|
constraints.appendAssumeCapacity('X');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assembly_statements.appendSliceAssumeCapacity(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = assembly_statements.pop();
|
||||||
|
_ = assembly_statements.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
assembly_statements.appendSliceAssumeCapacity("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = assembly_statements.pop();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const is_var_args = false;
|
const is_var_args = false;
|
||||||
@ -2908,31 +2968,41 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
const function_type = LLVM.Context.getFunctionType(return_type, syscall_argument_types.ptr, syscall_argument_types.len, is_var_args) orelse unreachable;
|
const function_type = LLVM.Context.getFunctionType(return_type, syscall_argument_types.ptr, syscall_argument_types.len, is_var_args) orelse unreachable;
|
||||||
var constraints = BoundedArray(u8, 4096){};
|
var constraints = BoundedArray(u8, 4096){};
|
||||||
|
|
||||||
const inline_asm = switch (unit.descriptor.arch) {
|
const syscall_registers: [7][]const u8 = switch (unit.descriptor.arch) {
|
||||||
.x86_64 => blk: {
|
.x86_64 => .{ "rax", "rdi", "rsi", "rdx", "r10", "r8", "r9" },
|
||||||
constraints.appendSliceAssumeCapacity("={rax}");
|
.aarch64 => .{ "x8", "x0", "x1", "x2", "x3", "x4", "x5" },
|
||||||
|
};
|
||||||
const syscall_registers = [7][]const u8{ "rax", "rdi", "rsi", "rdx", "r10", "r8", "r9" };
|
const syscall_instruction: []const u8 = switch (unit.descriptor.arch) {
|
||||||
for (syscall_registers[0..syscall_argument_count]) |syscall_register| {
|
.x86_64 => "syscall",
|
||||||
constraints.appendAssumeCapacity(',');
|
.aarch64 => "svc #0",
|
||||||
constraints.appendAssumeCapacity('{');
|
};
|
||||||
constraints.appendSliceAssumeCapacity(syscall_register);
|
const return_constraints: []const u8 = switch (unit.descriptor.arch) {
|
||||||
constraints.appendAssumeCapacity('}');
|
.x86_64 => "={rax}",
|
||||||
}
|
.aarch64 => "={x0}",
|
||||||
|
|
||||||
constraints.appendSliceAssumeCapacity(",~{rcx},~{r11},~{memory}");
|
|
||||||
|
|
||||||
const assembly = "syscall";
|
|
||||||
const has_side_effects = true;
|
|
||||||
const is_align_stack = true;
|
|
||||||
const can_throw = false;
|
|
||||||
const inline_assembly = LLVM.Value.InlineAssembly.get(function_type, assembly, assembly.len, &constraints.buffer, constraints.len, has_side_effects, is_align_stack, LLVM.Value.InlineAssembly.Dialect.@"at&t", can_throw) orelse return LLVM.Value.Error.inline_assembly;
|
|
||||||
break :blk inline_assembly;
|
|
||||||
},
|
|
||||||
else => |t| @panic(@tagName(t)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const call_to_asm = llvm.builder.createCall(function_type, inline_asm.toValue(), syscall_arguments.ptr, syscall_arguments.len, "syscall", "syscall".len, null) orelse return LLVM.Value.Instruction.Error.call;
|
const clobber_constraints: []const u8 = switch (unit.descriptor.arch) {
|
||||||
|
.x86_64 => ",~{rcx},~{r11},~{memory}",
|
||||||
|
.aarch64 => ",~{memory},~{cc}",
|
||||||
|
};
|
||||||
|
|
||||||
|
constraints.appendSliceAssumeCapacity(return_constraints);
|
||||||
|
|
||||||
|
for (syscall_registers[0..syscall_argument_count]) |syscall_register| {
|
||||||
|
constraints.appendAssumeCapacity(',');
|
||||||
|
constraints.appendAssumeCapacity('{');
|
||||||
|
constraints.appendSliceAssumeCapacity(syscall_register);
|
||||||
|
constraints.appendAssumeCapacity('}');
|
||||||
|
}
|
||||||
|
constraints.appendSliceAssumeCapacity(clobber_constraints);
|
||||||
|
|
||||||
|
const has_side_effects = true;
|
||||||
|
const is_align_stack = true;
|
||||||
|
const can_throw = false;
|
||||||
|
const inline_assembly = LLVM.Value.InlineAssembly.get(function_type, syscall_instruction.ptr, syscall_instruction.len, &constraints.buffer, constraints.len, has_side_effects, is_align_stack, LLVM.Value.InlineAssembly.Dialect.@"at&t", can_throw) orelse return LLVM.Value.Error.inline_assembly;
|
||||||
|
|
||||||
|
const call_to_asm = llvm.builder.createCall(function_type, inline_assembly.toValue(), syscall_arguments.ptr, syscall_arguments.len, "syscall", "syscall".len, null) orelse return LLVM.Value.Instruction.Error.call;
|
||||||
|
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(instruction_index, call_to_asm.toValue());
|
try llvm.llvm_instruction_map.put_no_clobber(instruction_index, call_to_asm.toValue());
|
||||||
},
|
},
|
||||||
.@"unreachable" => {
|
.@"unreachable" => {
|
||||||
@ -3298,7 +3368,10 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
|
|
||||||
// TODO: proper target selection
|
// TODO: proper target selection
|
||||||
const target_triple = switch (unit.descriptor.os) {
|
const target_triple = switch (unit.descriptor.os) {
|
||||||
.linux => "x86_64-linux-none",
|
.linux => switch (unit.descriptor.arch) {
|
||||||
|
.aarch64 => "aarch64-linux-none",
|
||||||
|
.x86_64 => "x86_64-linux-none",
|
||||||
|
},
|
||||||
.macos => "aarch64-apple-macosx-none",
|
.macos => "aarch64-apple-macosx-none",
|
||||||
.windows => "x86_64-windows-gnu",
|
.windows => "x86_64-windows-gnu",
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,7 @@ const log = std.log;
|
|||||||
const library = @import("../library.zig");
|
const library = @import("../library.zig");
|
||||||
const byte_equal = library.byte_equal;
|
const byte_equal = library.byte_equal;
|
||||||
const enumFromString = library.enumFromString;
|
const enumFromString = library.enumFromString;
|
||||||
|
const exit_with_error = library.exit_with_error;
|
||||||
const MyAllocator = library.MyAllocator;
|
const MyAllocator = library.MyAllocator;
|
||||||
const PinnedArray = library.PinnedArray;
|
const PinnedArray = library.PinnedArray;
|
||||||
|
|
||||||
@ -505,7 +506,7 @@ pub fn analyze(text: []const u8, token_buffer: *Token.Buffer) !Result {
|
|||||||
'A'...'Z', 'a'...'z' => {
|
'A'...'Z', 'a'...'z' => {
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (text[index]) {
|
switch (text[index]) {
|
||||||
'A'...'Z', 'a'...'z' => index += 1,
|
'A'...'Z', 'a'...'z', '0'...'9' => index += 1,
|
||||||
else => break,
|
else => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -559,12 +560,13 @@ pub fn analyze(text: []const u8, token_buffer: *Token.Buffer) !Result {
|
|||||||
hex,
|
hex,
|
||||||
bin,
|
bin,
|
||||||
octal,
|
octal,
|
||||||
|
decimal,
|
||||||
};
|
};
|
||||||
const representation: Representation = switch (text[index]) {
|
const representation: Representation = switch (text[index]) {
|
||||||
'x' => .hex,
|
'x' => .hex,
|
||||||
else => unreachable,
|
else => .decimal,
|
||||||
};
|
};
|
||||||
index += 1;
|
index += @intFromBool(representation != .decimal);
|
||||||
switch (representation) {
|
switch (representation) {
|
||||||
.hex => {
|
.hex => {
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -574,6 +576,20 @@ pub fn analyze(text: []const u8, token_buffer: *Token.Buffer) !Result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = token_buffer.tokens.append(.{
|
||||||
|
.id = .number_literal,
|
||||||
|
.line = line_index,
|
||||||
|
.offset = start_i,
|
||||||
|
.length = index - start_i,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.decimal => {
|
||||||
|
switch (text[index]) {
|
||||||
|
'0'...'9' => unreachable,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_ = token_buffer.tokens.append(.{
|
_ = token_buffer.tokens.append(.{
|
||||||
.id = .number_literal,
|
.id = .number_literal,
|
||||||
.line = line_index,
|
.line = line_index,
|
||||||
@ -590,9 +606,16 @@ pub fn analyze(text: []const u8, token_buffer: *Token.Buffer) !Result {
|
|||||||
const ch_fmt = library.format_int(&ch_array, start_ch, 16, false);
|
const ch_fmt = library.format_int(&ch_array, start_ch, 16, false);
|
||||||
try Compilation.write(.panic, ch_fmt);
|
try Compilation.write(.panic, ch_fmt);
|
||||||
try Compilation.write(.panic, "\n");
|
try Compilation.write(.panic, "\n");
|
||||||
std.posix.exit(0);
|
exit_with_error();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const debug_asm_tokens = false;
|
||||||
|
if (debug_asm_tokens) {
|
||||||
|
try Compilation.write(.panic, "ASM token: '");
|
||||||
|
try Compilation.write(.panic, text[start_i..index]);
|
||||||
|
try Compilation.write(.panic, "'\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = token_buffer.tokens.append(.{
|
_ = token_buffer.tokens.append(.{
|
||||||
|
@ -239,7 +239,7 @@ pub fn PinnedArrayAdvanced(comptime T: type, comptime MaybeIndex: ?type) type {
|
|||||||
array.ensure_capacity(1);
|
array.ensure_capacity(1);
|
||||||
const src = array.slice()[index..];
|
const src = array.slice()[index..];
|
||||||
array.length += 1;
|
array.length += 1;
|
||||||
const dst = array.slice()[index + 1..];
|
const dst = array.slice()[index + 1 ..];
|
||||||
copy_backwards(T, dst, src);
|
copy_backwards(T, dst, src);
|
||||||
array.slice()[index] = item;
|
array.slice()[index] = item;
|
||||||
}
|
}
|
||||||
@ -707,3 +707,8 @@ pub fn align_forward(value: u64, alignment: u64) u64 {
|
|||||||
const mask = alignment - 1;
|
const mask = alignment - 1;
|
||||||
return (value + mask) & ~mask;
|
return (value + mask) & ~mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exit_with_error() noreturn {
|
||||||
|
@breakpoint();
|
||||||
|
std.posix.exit(1);
|
||||||
|
}
|
||||||
|
@ -20,6 +20,17 @@ pub fn link(context: *const Compilation.Context, options: linker.Options) !void
|
|||||||
_ = argv.append(driver_program);
|
_ = argv.append(driver_program);
|
||||||
_ = argv.append("--error-limit=0");
|
_ = argv.append("--error-limit=0");
|
||||||
|
|
||||||
|
switch (@import("builtin").cpu.arch) {
|
||||||
|
.aarch64 => switch (@import("builtin").os.tag) {
|
||||||
|
.linux => {
|
||||||
|
_ = argv.append("-znow");
|
||||||
|
_ = argv.append_slice(&.{ "-m", "aarch64linux"});
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
// const output_path = out_path orelse "a.out";
|
// const output_path = out_path orelse "a.out";
|
||||||
_ = argv.append("-o");
|
_ = argv.append("-o");
|
||||||
_ = argv.append(options.output_file_path);
|
_ = argv.append(options.output_file_path);
|
||||||
@ -78,14 +89,30 @@ pub fn link(context: *const Compilation.Context, options: linker.Options) !void
|
|||||||
} else {
|
} else {
|
||||||
if (options.link_libcpp) {
|
if (options.link_libcpp) {
|
||||||
assert(options.link_libc);
|
assert(options.link_libc);
|
||||||
_ = argv.append("/usr/lib/libstdc++.so");
|
switch (@import("builtin").cpu.arch) {
|
||||||
|
.x86_64 => _ = argv.append("/usr/lib/libstdc++.so"),
|
||||||
|
.aarch64 => _ = argv.append("/usr/lib64/libstdc++.so.6"),
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.link_libc) {
|
if (options.link_libc) {
|
||||||
_ = argv.append("/usr/lib/crt1.o");
|
switch (@import("builtin").cpu.arch) {
|
||||||
_ = argv.append("/usr/lib/crti.o");
|
.x86_64 => {
|
||||||
argv.append_slice(&.{ "-L", "/usr/lib" });
|
_ = argv.append("/usr/lib/crt1.o");
|
||||||
argv.append_slice(&.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
_ = argv.append("/usr/lib/crti.o");
|
||||||
|
argv.append_slice(&.{ "-L", "/usr/lib" });
|
||||||
|
argv.append_slice(&.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
||||||
|
},
|
||||||
|
.aarch64 => {
|
||||||
|
_ = argv.append("/usr/lib64/crt1.o");
|
||||||
|
_ = argv.append("/usr/lib64/crti.o");
|
||||||
|
argv.append_slice(&.{ "-L", "/usr/lib64" });
|
||||||
|
argv.append_slice(&.{ "-dynamic-linker", "/lib/ld-linux-aarch64.so.1" });
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
|
||||||
_ = argv.append("--as-needed");
|
_ = argv.append("--as-needed");
|
||||||
_ = argv.append("-lm");
|
_ = argv.append("-lm");
|
||||||
_ = argv.append("-lpthread");
|
_ = argv.append("-lpthread");
|
||||||
@ -93,7 +120,16 @@ pub fn link(context: *const Compilation.Context, options: linker.Options) !void
|
|||||||
_ = argv.append("-ldl");
|
_ = argv.append("-ldl");
|
||||||
_ = argv.append("-lrt");
|
_ = argv.append("-lrt");
|
||||||
_ = argv.append("-lutil");
|
_ = argv.append("-lutil");
|
||||||
_ = argv.append("/usr/lib/crtn.o");
|
|
||||||
|
switch (@import("builtin").cpu.arch) {
|
||||||
|
.x86_64 => {
|
||||||
|
_ = argv.append("/usr/lib/crtn.o");
|
||||||
|
},
|
||||||
|
.aarch64 => {
|
||||||
|
_ = argv.append("/usr/lib64/crtn.o");
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
24
build.zig
24
build.zig
@ -446,7 +446,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const result = try std.ChildProcess.run(.{
|
const result = try std.ChildProcess.run(.{
|
||||||
.allocator = b.allocator,
|
.allocator = b.allocator,
|
||||||
.argv = &.{
|
.argv = &.{
|
||||||
"cc", "--version",
|
"c++", "--version",
|
||||||
},
|
},
|
||||||
.max_output_bytes = 0xffffffffffffff,
|
.max_output_bytes = 0xffffffffffffff,
|
||||||
});
|
});
|
||||||
@ -470,11 +470,27 @@ pub fn build(b: *std.Build) !void {
|
|||||||
unreachable;
|
unreachable;
|
||||||
};
|
};
|
||||||
|
|
||||||
const cxx_include_base = try std.mem.concat(b.allocator, u8, &.{ "/usr/include/c++/", cxx_version });
|
const cxx_include_base = switch (@import("builtin").cpu.arch) {
|
||||||
compiler.addObjectFile(.{ .cwd_relative = "/usr/lib/libstdc++.so" });
|
.x86_64 => try std.mem.concat(b.allocator, u8, &.{ "/usr/include/c++/", cxx_version }),
|
||||||
|
.aarch64 => "/usr/include/c++/13",
|
||||||
|
else => @compileError("Arch not supported"),
|
||||||
|
};
|
||||||
|
compiler.addObjectFile(.{
|
||||||
|
.cwd_relative = switch (@import("builtin").cpu.arch) {
|
||||||
|
.aarch64 => "/lib64/libstdc++.so.6",
|
||||||
|
.x86_64 => "/usr/lib/libstdc++.so",
|
||||||
|
else => @compileError("Arch not supported"),
|
||||||
|
},
|
||||||
|
});
|
||||||
compiler.addIncludePath(.{ .cwd_relative = "/usr/include" });
|
compiler.addIncludePath(.{ .cwd_relative = "/usr/include" });
|
||||||
compiler.addIncludePath(.{ .cwd_relative = cxx_include_base });
|
compiler.addIncludePath(.{ .cwd_relative = cxx_include_base });
|
||||||
compiler.addIncludePath(.{ .cwd_relative = try std.mem.concat(b.allocator, u8, &.{ cxx_include_base, "/x86_64-pc-linux-gnu" }) });
|
compiler.addIncludePath(.{
|
||||||
|
.cwd_relative = try std.mem.concat(b.allocator, u8, &.{ cxx_include_base, switch (@import("builtin").cpu.arch) {
|
||||||
|
.x86_64 => "/x86_64-pc-linux-gnu",
|
||||||
|
.aarch64 => "/aarch64-redhat-linux",
|
||||||
|
else => @compileError("Arch not supported"),
|
||||||
|
} }),
|
||||||
|
});
|
||||||
compiler.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
|
compiler.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -131,7 +131,7 @@ fn runBuildTests(allocator: Allocator, args: struct {
|
|||||||
const test_dir_path = "test/build";
|
const test_dir_path = "test/build";
|
||||||
const test_names = try collectDirectoryDirEntries(allocator, test_dir_path);
|
const test_names = try collectDirectoryDirEntries(allocator, test_dir_path);
|
||||||
const test_dir_realpath = try std.fs.cwd().realpathAlloc(allocator, test_dir_path);
|
const test_dir_realpath = try std.fs.cwd().realpathAlloc(allocator, test_dir_path);
|
||||||
const compiler_realpath = try std.fs.cwd().realpathAlloc(allocator, args.compiler_path);
|
|
||||||
try std.posix.chdir(test_dir_realpath);
|
try std.posix.chdir(test_dir_realpath);
|
||||||
|
|
||||||
const total_compilation_count = test_names.len;
|
const total_compilation_count = test_names.len;
|
||||||
@ -142,16 +142,23 @@ fn runBuildTests(allocator: Allocator, args: struct {
|
|||||||
var failed_test_count: usize = 0;
|
var failed_test_count: usize = 0;
|
||||||
const total_test_count = test_names.len;
|
const total_test_count = test_names.len;
|
||||||
|
|
||||||
|
errdefer {
|
||||||
|
std.posix.chdir(previous_cwd) catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
for (test_names) |test_name| {
|
for (test_names) |test_name| {
|
||||||
std.debug.print("{s}... ", .{test_name});
|
std.debug.print("{s}... ", .{test_name});
|
||||||
try std.posix.chdir(test_name);
|
try std.posix.chdir(test_name);
|
||||||
|
|
||||||
const compile_run = try std.ChildProcess.run(.{
|
const compile_run = std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
// TODO: delete -main_source_file?
|
.argv = &.{ args.compiler_path, "build" },
|
||||||
.argv = &.{ compiler_realpath, "build" },
|
|
||||||
.max_output_bytes = std.math.maxInt(u64),
|
.max_output_bytes = std.math.maxInt(u64),
|
||||||
});
|
}) catch |err| {
|
||||||
|
const compilation_success = false;
|
||||||
|
std.debug.print("[COMPILATION {s}] ", .{if (compilation_success) "\x1b[32mOK\x1b[0m" else "\x1b[31mFAILED\x1b[0m"});
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
|
||||||
ran_compilation_count += 1;
|
ran_compilation_count += 1;
|
||||||
|
|
||||||
@ -177,12 +184,20 @@ fn runBuildTests(allocator: Allocator, args: struct {
|
|||||||
|
|
||||||
if (compilation_success and !args.self_hosted) {
|
if (compilation_success and !args.self_hosted) {
|
||||||
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name });
|
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name });
|
||||||
const test_run = try std.ChildProcess.run(.{
|
const test_run = std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
// TODO: delete -main_source_file?
|
// TODO: delete -main_source_file?
|
||||||
.argv = &.{test_path},
|
.argv = &.{test_path},
|
||||||
.max_output_bytes = std.math.maxInt(u64),
|
.max_output_bytes = std.math.maxInt(u64),
|
||||||
});
|
}) catch |err| {
|
||||||
|
const test_success = false;
|
||||||
|
std.debug.print("[TEST {s}]\n", .{if (test_success) "\x1b[32mOK\x1b[0m" else "\x1b[31mFAILED\x1b[0m"});
|
||||||
|
std.debug.print("{}\n", .{err});
|
||||||
|
if (@errorReturnTrace()) |error_trace| {
|
||||||
|
std.debug.dumpStackTrace(error_trace.*);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
};
|
||||||
ran_test_count += 1;
|
ran_test_count += 1;
|
||||||
const test_result: TestError!bool = switch (test_run.term) {
|
const test_result: TestError!bool = switch (test_run.term) {
|
||||||
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
|
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
|
||||||
@ -213,6 +228,9 @@ fn runBuildTests(allocator: Allocator, args: struct {
|
|||||||
std.debug.print("TOTAL TESTS: {}. RAN: {}. FAILED: {}\n", .{ total_test_count, ran_test_count, failed_test_count });
|
std.debug.print("TOTAL TESTS: {}. RAN: {}. FAILED: {}\n", .{ total_test_count, ran_test_count, failed_test_count });
|
||||||
|
|
||||||
try std.posix.chdir(previous_cwd);
|
try std.posix.chdir(previous_cwd);
|
||||||
|
const current_cwd = try std.fs.cwd().realpathAlloc(allocator, ".");
|
||||||
|
std.debug.assert(std.mem.eql(u8, current_cwd, previous_cwd));
|
||||||
|
std.debug.print("Hello \n", .{});
|
||||||
|
|
||||||
if (failed_compilation_count > 0 or failed_test_count > 0) {
|
if (failed_compilation_count > 0 or failed_test_count > 0) {
|
||||||
return error.fail;
|
return error.fail;
|
||||||
@ -226,11 +244,21 @@ fn runStdTests(allocator: Allocator, args: struct {
|
|||||||
var errors = false;
|
var errors = false;
|
||||||
std.debug.print("std... ", .{});
|
std.debug.print("std... ", .{});
|
||||||
|
|
||||||
const result = try std.ChildProcess.run(.{
|
std.debug.print("CWD: {s}\n", .{std.fs.cwd().realpathAlloc(allocator, ".") catch unreachable});
|
||||||
|
|
||||||
|
const argv = &.{ args.compiler_path, "test", "-main_source_file", "lib/std/std.nat", "-name", "std" };
|
||||||
|
|
||||||
|
const result = std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.argv = &.{ args.compiler_path, "test", "-main_source_file", "lib/std/std.nat", "-name", "std" },
|
.argv = argv,
|
||||||
.max_output_bytes = std.math.maxInt(u64),
|
.max_output_bytes = std.math.maxInt(u64),
|
||||||
});
|
}) catch |err| {
|
||||||
|
std.debug.print("Error: {}", .{err});
|
||||||
|
if (@errorReturnTrace()) |error_trace| {
|
||||||
|
std.debug.dumpStackTrace(error_trace.*);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
};
|
||||||
const compilation_result: TestError!bool = switch (result.term) {
|
const compilation_result: TestError!bool = switch (result.term) {
|
||||||
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
|
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
|
||||||
.Signal => error.signaled,
|
.Signal => error.signaled,
|
||||||
@ -290,7 +318,6 @@ fn runCmakeTests(allocator: Allocator, args: struct {
|
|||||||
const cc_dir = try std.fs.cwd().openDir(args.dir_path, .{
|
const cc_dir = try std.fs.cwd().openDir(args.dir_path, .{
|
||||||
.iterate = true,
|
.iterate = true,
|
||||||
});
|
});
|
||||||
const compiler_realpath = try std.fs.cwd().realpathAlloc(allocator, args.compiler_path);
|
|
||||||
|
|
||||||
const cc_dir_path = try cc_dir.realpathAlloc(allocator, ".");
|
const cc_dir_path = try cc_dir.realpathAlloc(allocator, ".");
|
||||||
try std.posix.chdir(cc_dir_path);
|
try std.posix.chdir(cc_dir_path);
|
||||||
@ -316,9 +343,9 @@ fn runCmakeTests(allocator: Allocator, args: struct {
|
|||||||
"-G",
|
"-G",
|
||||||
"Ninja",
|
"Ninja",
|
||||||
// "-DCMAKE_VERBOSE_MAKEFILE=On",
|
// "-DCMAKE_VERBOSE_MAKEFILE=On",
|
||||||
try std.mem.concat(allocator, u8, &.{ "-DCMAKE_C_COMPILER=", compiler_realpath, ";cc" }),
|
try std.mem.concat(allocator, u8, &.{ "-DCMAKE_C_COMPILER=", args.compiler_path, ";cc" }),
|
||||||
try std.mem.concat(allocator, u8, &.{ "-DCMAKE_CXX_COMPILER=", compiler_realpath, ";c++" }),
|
try std.mem.concat(allocator, u8, &.{ "-DCMAKE_CXX_COMPILER=", args.compiler_path, ";c++" }),
|
||||||
try std.mem.concat(allocator, u8, &.{ "-DCMAKE_ASM_COMPILER=", compiler_realpath, ";cc" }),
|
try std.mem.concat(allocator, u8, &.{ "-DCMAKE_ASM_COMPILER=", args.compiler_path, ";cc" }),
|
||||||
},
|
},
|
||||||
.max_output_bytes = std.math.maxInt(u64),
|
.max_output_bytes = std.math.maxInt(u64),
|
||||||
});
|
});
|
||||||
@ -474,19 +501,21 @@ fn run_test_suite(allocator: Allocator, args: struct {
|
|||||||
std.debug.print("TESTING {s} COMPILER: {s}...\n=================\n", .{ if (self_hosted) "SELF-HOSTED" else "BOOTSTRAP", args.compiler_path });
|
std.debug.print("TESTING {s} COMPILER: {s}...\n=================\n", .{ if (self_hosted) "SELF-HOSTED" else "BOOTSTRAP", args.compiler_path });
|
||||||
var errors = false;
|
var errors = false;
|
||||||
|
|
||||||
|
const compiler_path = std.fs.cwd().realpathAlloc(allocator, args.compiler_path) catch unreachable;
|
||||||
|
|
||||||
runStandalone(allocator, .{
|
runStandalone(allocator, .{
|
||||||
.directory_path = "test/standalone",
|
.directory_path = "test/standalone",
|
||||||
.group_name = "STANDALONE",
|
.group_name = "STANDALONE",
|
||||||
.is_test = false,
|
.is_test = false,
|
||||||
.self_hosted = self_hosted,
|
.self_hosted = self_hosted,
|
||||||
.compiler_path = args.compiler_path,
|
.compiler_path = compiler_path,
|
||||||
}) catch {
|
}) catch {
|
||||||
errors = true;
|
errors = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
runBuildTests(allocator, .{
|
runBuildTests(allocator, .{
|
||||||
.self_hosted = self_hosted,
|
.self_hosted = self_hosted,
|
||||||
.compiler_path = args.compiler_path,
|
.compiler_path = compiler_path,
|
||||||
}) catch {
|
}) catch {
|
||||||
errors = true;
|
errors = true;
|
||||||
};
|
};
|
||||||
@ -496,14 +525,14 @@ fn run_test_suite(allocator: Allocator, args: struct {
|
|||||||
.group_name = "TEST EXECUTABLE",
|
.group_name = "TEST EXECUTABLE",
|
||||||
.is_test = true,
|
.is_test = true,
|
||||||
.self_hosted = self_hosted,
|
.self_hosted = self_hosted,
|
||||||
.compiler_path = args.compiler_path,
|
.compiler_path = compiler_path,
|
||||||
}) catch {
|
}) catch {
|
||||||
errors = true;
|
errors = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
runStdTests(allocator, .{
|
runStdTests(allocator, .{
|
||||||
.self_hosted = self_hosted,
|
.self_hosted = self_hosted,
|
||||||
.compiler_path = args.compiler_path,
|
.compiler_path = compiler_path,
|
||||||
}) catch {
|
}) catch {
|
||||||
errors = true;
|
errors = true;
|
||||||
};
|
};
|
||||||
@ -511,37 +540,41 @@ fn run_test_suite(allocator: Allocator, args: struct {
|
|||||||
if (!self_hosted) {
|
if (!self_hosted) {
|
||||||
runCmakeTests(allocator, .{
|
runCmakeTests(allocator, .{
|
||||||
.dir_path = "test/cc",
|
.dir_path = "test/cc",
|
||||||
.compiler_path = args.compiler_path,
|
.compiler_path = compiler_path,
|
||||||
}) catch {
|
}) catch {
|
||||||
errors = true;
|
errors = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
runCmakeTests(allocator, .{
|
runCmakeTests(allocator, .{
|
||||||
.dir_path = "test/c++",
|
.dir_path = "test/c++",
|
||||||
.compiler_path = args.compiler_path,
|
.compiler_path = compiler_path,
|
||||||
}) catch {
|
}) catch {
|
||||||
errors = true;
|
errors = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (@import("builtin").os.tag) {
|
switch (@import("builtin").cpu.arch) {
|
||||||
.macos => runCmakeTests(allocator, .{
|
.aarch64 => switch (@import("builtin").os.tag) {
|
||||||
.dir_path = "test/cc_macos",
|
.linux => runCmakeTests(allocator, .{
|
||||||
.compiler_path = args.compiler_path,
|
.dir_path = "test/cc_aarch64_linux",
|
||||||
}) catch {
|
.compiler_path = compiler_path,
|
||||||
errors = true;
|
|
||||||
},
|
|
||||||
.windows => {},
|
|
||||||
.linux => switch (@import("builtin").abi) {
|
|
||||||
.gnu => runCmakeTests(allocator, .{
|
|
||||||
.dir_path = "test/cc_linux",
|
|
||||||
.compiler_path = args.compiler_path,
|
|
||||||
}) catch {
|
}) catch {
|
||||||
errors = true;
|
errors = true;
|
||||||
},
|
},
|
||||||
.musl => {},
|
.macos => runCmakeTests(allocator, .{
|
||||||
else => @compileError("ABI not supported"),
|
.dir_path = "test/cc_aarch64_macos",
|
||||||
|
.compiler_path = compiler_path,
|
||||||
|
}) catch {
|
||||||
|
errors = true;
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
},
|
},
|
||||||
else => @compileError("OS not supported"),
|
.x86_64 => runCmakeTests(allocator, .{
|
||||||
|
.dir_path = "test/cc_x86_64",
|
||||||
|
.compiler_path = compiler_path,
|
||||||
|
}) catch {
|
||||||
|
errors = true;
|
||||||
|
},
|
||||||
|
else => @compileError("Arch not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +24,7 @@ const unwrap_syscall = system.unwrap_syscall;
|
|||||||
|
|
||||||
const exit = fn(exit_code: s32) noreturn {
|
const exit = fn(exit_code: s32) noreturn {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux => _ = #syscall(#cast(linux.Syscall.exit_group), #cast(exit_code)),
|
.linux, .macos => system.exit(exit_code),
|
||||||
.macos => system.exit(exit_code),
|
|
||||||
.windows => windows.ExitProcess(#cast(exit_code)),
|
.windows => windows.ExitProcess(#cast(exit_code)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -323,6 +322,7 @@ const duplicate_process = fn () DuplicateProcessError!Process.Id {
|
|||||||
const ExecveError = error{
|
const ExecveError = error{
|
||||||
execve_failed,
|
execve_failed,
|
||||||
};
|
};
|
||||||
|
|
||||||
const execute = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) ExecveError!noreturn {
|
const execute = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) ExecveError!noreturn {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux, .macos => {
|
.linux, .macos => {
|
||||||
|
@ -3,14 +3,333 @@ const std = #import("std");
|
|||||||
const stdin: FileDescriptor = 0;
|
const stdin: FileDescriptor = 0;
|
||||||
const stdout: FileDescriptor = 1;
|
const stdout: FileDescriptor = 1;
|
||||||
const stderr: FileDescriptor = 2;
|
const stderr: FileDescriptor = 2;
|
||||||
|
const cpu = #import("builtin").cpu;
|
||||||
|
|
||||||
const Syscall = switch (#import("builtin").cpu) {
|
const Syscall = switch (cpu) {
|
||||||
.x86_64 => Syscall_x86_64,
|
.x86_64 => Syscall_x86_64,
|
||||||
|
.aarch64 => Syscall_aarch64,
|
||||||
else => #error("Architecture not supported"),
|
else => #error("Architecture not supported"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const current_working_directory_file_descriptor: ssize = -100;
|
||||||
|
|
||||||
const ProcessId = s32;
|
const ProcessId = s32;
|
||||||
|
|
||||||
|
const Syscall_aarch64 = enum(usize) {
|
||||||
|
io_setup = 0,
|
||||||
|
io_destroy = 1,
|
||||||
|
io_submit = 2,
|
||||||
|
io_cancel = 3,
|
||||||
|
io_getevents = 4,
|
||||||
|
setxattr = 5,
|
||||||
|
lsetxattr = 6,
|
||||||
|
fsetxattr = 7,
|
||||||
|
getxattr = 8,
|
||||||
|
lgetxattr = 9,
|
||||||
|
fgetxattr = 10,
|
||||||
|
listxattr = 11,
|
||||||
|
llistxattr = 12,
|
||||||
|
flistxattr = 13,
|
||||||
|
removexattr = 14,
|
||||||
|
lremovexattr = 15,
|
||||||
|
fremovexattr = 16,
|
||||||
|
getcwd = 17,
|
||||||
|
lookup_dcookie = 18,
|
||||||
|
eventfd2 = 19,
|
||||||
|
epoll_create1 = 20,
|
||||||
|
epoll_ctl = 21,
|
||||||
|
epoll_pwait = 22,
|
||||||
|
dup = 23,
|
||||||
|
dup3 = 24,
|
||||||
|
fcntl = 25,
|
||||||
|
inotify_init1 = 26,
|
||||||
|
inotify_add_watch = 27,
|
||||||
|
inotify_rm_watch = 28,
|
||||||
|
ioctl = 29,
|
||||||
|
ioprio_set = 30,
|
||||||
|
ioprio_get = 31,
|
||||||
|
flock = 32,
|
||||||
|
mknodat = 33,
|
||||||
|
mkdirat = 34,
|
||||||
|
unlinkat = 35,
|
||||||
|
symlinkat = 36,
|
||||||
|
linkat = 37,
|
||||||
|
renameat = 38,
|
||||||
|
umount2 = 39,
|
||||||
|
mount = 40,
|
||||||
|
pivot_root = 41,
|
||||||
|
nfsservctl = 42,
|
||||||
|
statfs = 43,
|
||||||
|
fstatfs = 44,
|
||||||
|
truncate = 45,
|
||||||
|
ftruncate = 46,
|
||||||
|
fallocate = 47,
|
||||||
|
faccessat = 48,
|
||||||
|
chdir = 49,
|
||||||
|
fchdir = 50,
|
||||||
|
chroot = 51,
|
||||||
|
fchmod = 52,
|
||||||
|
fchmodat = 53,
|
||||||
|
fchownat = 54,
|
||||||
|
fchown = 55,
|
||||||
|
openat = 56,
|
||||||
|
close = 57,
|
||||||
|
vhangup = 58,
|
||||||
|
pipe2 = 59,
|
||||||
|
quotactl = 60,
|
||||||
|
getdents64 = 61,
|
||||||
|
lseek = 62,
|
||||||
|
read = 63,
|
||||||
|
write = 64,
|
||||||
|
readv = 65,
|
||||||
|
writev = 66,
|
||||||
|
pread64 = 67,
|
||||||
|
pwrite64 = 68,
|
||||||
|
preadv = 69,
|
||||||
|
pwritev = 70,
|
||||||
|
sendfile = 71,
|
||||||
|
pselect6 = 72,
|
||||||
|
ppoll = 73,
|
||||||
|
signalfd4 = 74,
|
||||||
|
vmsplice = 75,
|
||||||
|
splice = 76,
|
||||||
|
tee = 77,
|
||||||
|
readlinkat = 78,
|
||||||
|
fstatat = 79,
|
||||||
|
fstat = 80,
|
||||||
|
sync = 81,
|
||||||
|
fsync = 82,
|
||||||
|
fdatasync = 83,
|
||||||
|
sync_file_range = 84,
|
||||||
|
timerfd_create = 85,
|
||||||
|
timerfd_settime = 86,
|
||||||
|
timerfd_gettime = 87,
|
||||||
|
utimensat = 88,
|
||||||
|
acct = 89,
|
||||||
|
capget = 90,
|
||||||
|
capset = 91,
|
||||||
|
personality = 92,
|
||||||
|
exit = 93,
|
||||||
|
exit_group = 94,
|
||||||
|
waitid = 95,
|
||||||
|
set_tid_address = 96,
|
||||||
|
unshare = 97,
|
||||||
|
futex = 98,
|
||||||
|
set_robust_list = 99,
|
||||||
|
get_robust_list = 100,
|
||||||
|
nanosleep = 101,
|
||||||
|
getitimer = 102,
|
||||||
|
setitimer = 103,
|
||||||
|
kexec_load = 104,
|
||||||
|
init_module = 105,
|
||||||
|
delete_module = 106,
|
||||||
|
timer_create = 107,
|
||||||
|
timer_gettime = 108,
|
||||||
|
timer_getoverrun = 109,
|
||||||
|
timer_settime = 110,
|
||||||
|
timer_delete = 111,
|
||||||
|
clock_settime = 112,
|
||||||
|
clock_gettime = 113,
|
||||||
|
clock_getres = 114,
|
||||||
|
clock_nanosleep = 115,
|
||||||
|
syslog = 116,
|
||||||
|
ptrace = 117,
|
||||||
|
sched_setparam = 118,
|
||||||
|
sched_setscheduler = 119,
|
||||||
|
sched_getscheduler = 120,
|
||||||
|
sched_getparam = 121,
|
||||||
|
sched_setaffinity = 122,
|
||||||
|
sched_getaffinity = 123,
|
||||||
|
sched_yield = 124,
|
||||||
|
sched_get_priority_max = 125,
|
||||||
|
sched_get_priority_min = 126,
|
||||||
|
sched_rr_get_interval = 127,
|
||||||
|
restart_syscall = 128,
|
||||||
|
kill = 129,
|
||||||
|
tkill = 130,
|
||||||
|
tgkill = 131,
|
||||||
|
sigaltstack = 132,
|
||||||
|
rt_sigsuspend = 133,
|
||||||
|
rt_sigaction = 134,
|
||||||
|
rt_sigprocmask = 135,
|
||||||
|
rt_sigpending = 136,
|
||||||
|
rt_sigtimedwait = 137,
|
||||||
|
rt_sigqueueinfo = 138,
|
||||||
|
rt_sigreturn = 139,
|
||||||
|
setpriority = 140,
|
||||||
|
getpriority = 141,
|
||||||
|
reboot = 142,
|
||||||
|
setregid = 143,
|
||||||
|
setgid = 144,
|
||||||
|
setreuid = 145,
|
||||||
|
setuid = 146,
|
||||||
|
setresuid = 147,
|
||||||
|
getresuid = 148,
|
||||||
|
setresgid = 149,
|
||||||
|
getresgid = 150,
|
||||||
|
setfsuid = 151,
|
||||||
|
setfsgid = 152,
|
||||||
|
times = 153,
|
||||||
|
setpgid = 154,
|
||||||
|
getpgid = 155,
|
||||||
|
getsid = 156,
|
||||||
|
setsid = 157,
|
||||||
|
getgroups = 158,
|
||||||
|
setgroups = 159,
|
||||||
|
uname = 160,
|
||||||
|
sethostname = 161,
|
||||||
|
setdomainname = 162,
|
||||||
|
getrlimit = 163,
|
||||||
|
setrlimit = 164,
|
||||||
|
getrusage = 165,
|
||||||
|
umask = 166,
|
||||||
|
prctl = 167,
|
||||||
|
getcpu = 168,
|
||||||
|
gettimeofday = 169,
|
||||||
|
settimeofday = 170,
|
||||||
|
adjtimex = 171,
|
||||||
|
getpid = 172,
|
||||||
|
getppid = 173,
|
||||||
|
getuid = 174,
|
||||||
|
geteuid = 175,
|
||||||
|
getgid = 176,
|
||||||
|
getegid = 177,
|
||||||
|
gettid = 178,
|
||||||
|
sysinfo = 179,
|
||||||
|
mq_open = 180,
|
||||||
|
mq_unlink = 181,
|
||||||
|
mq_timedsend = 182,
|
||||||
|
mq_timedreceive = 183,
|
||||||
|
mq_notify = 184,
|
||||||
|
mq_getsetattr = 185,
|
||||||
|
msgget = 186,
|
||||||
|
msgctl = 187,
|
||||||
|
msgrcv = 188,
|
||||||
|
msgsnd = 189,
|
||||||
|
semget = 190,
|
||||||
|
semctl = 191,
|
||||||
|
semtimedop = 192,
|
||||||
|
semop = 193,
|
||||||
|
shmget = 194,
|
||||||
|
shmctl = 195,
|
||||||
|
shmat = 196,
|
||||||
|
shmdt = 197,
|
||||||
|
socket = 198,
|
||||||
|
socketpair = 199,
|
||||||
|
bind = 200,
|
||||||
|
listen = 201,
|
||||||
|
accept = 202,
|
||||||
|
connect = 203,
|
||||||
|
getsockname = 204,
|
||||||
|
getpeername = 205,
|
||||||
|
sendto = 206,
|
||||||
|
recvfrom = 207,
|
||||||
|
setsockopt = 208,
|
||||||
|
getsockopt = 209,
|
||||||
|
shutdown = 210,
|
||||||
|
sendmsg = 211,
|
||||||
|
recvmsg = 212,
|
||||||
|
readahead = 213,
|
||||||
|
brk = 214,
|
||||||
|
munmap = 215,
|
||||||
|
mremap = 216,
|
||||||
|
add_key = 217,
|
||||||
|
request_key = 218,
|
||||||
|
keyctl = 219,
|
||||||
|
clone = 220,
|
||||||
|
execve = 221,
|
||||||
|
mmap = 222,
|
||||||
|
fadvise64 = 223,
|
||||||
|
swapon = 224,
|
||||||
|
swapoff = 225,
|
||||||
|
mprotect = 226,
|
||||||
|
msync = 227,
|
||||||
|
mlock = 228,
|
||||||
|
munlock = 229,
|
||||||
|
mlockall = 230,
|
||||||
|
munlockall = 231,
|
||||||
|
mincore = 232,
|
||||||
|
madvise = 233,
|
||||||
|
remap_file_pages = 234,
|
||||||
|
mbind = 235,
|
||||||
|
get_mempolicy = 236,
|
||||||
|
set_mempolicy = 237,
|
||||||
|
migrate_pages = 238,
|
||||||
|
move_pages = 239,
|
||||||
|
rt_tgsigqueueinfo = 240,
|
||||||
|
perf_event_open = 241,
|
||||||
|
accept4 = 242,
|
||||||
|
recvmmsg = 243,
|
||||||
|
wait4 = 260,
|
||||||
|
prlimit64 = 261,
|
||||||
|
fanotify_init = 262,
|
||||||
|
fanotify_mark = 263,
|
||||||
|
name_to_handle_at = 264,
|
||||||
|
open_by_handle_at = 265,
|
||||||
|
clock_adjtime = 266,
|
||||||
|
syncfs = 267,
|
||||||
|
setns = 268,
|
||||||
|
sendmmsg = 269,
|
||||||
|
process_vm_readv = 270,
|
||||||
|
process_vm_writev = 271,
|
||||||
|
kcmp = 272,
|
||||||
|
finit_module = 273,
|
||||||
|
sched_setattr = 274,
|
||||||
|
sched_getattr = 275,
|
||||||
|
renameat2 = 276,
|
||||||
|
seccomp = 277,
|
||||||
|
getrandom = 278,
|
||||||
|
memfd_create = 279,
|
||||||
|
bpf = 280,
|
||||||
|
execveat = 281,
|
||||||
|
userfaultfd = 282,
|
||||||
|
membarrier = 283,
|
||||||
|
mlock2 = 284,
|
||||||
|
copy_file_range = 285,
|
||||||
|
preadv2 = 286,
|
||||||
|
pwritev2 = 287,
|
||||||
|
pkey_mprotect = 288,
|
||||||
|
pkey_alloc = 289,
|
||||||
|
pkey_free = 290,
|
||||||
|
statx = 291,
|
||||||
|
io_pgetevents = 292,
|
||||||
|
rseq = 293,
|
||||||
|
kexec_file_load = 294,
|
||||||
|
pidfd_send_signal = 424,
|
||||||
|
io_uring_setup = 425,
|
||||||
|
io_uring_enter = 426,
|
||||||
|
io_uring_register = 427,
|
||||||
|
open_tree = 428,
|
||||||
|
move_mount = 429,
|
||||||
|
fsopen = 430,
|
||||||
|
fsconfig = 431,
|
||||||
|
fsmount = 432,
|
||||||
|
fspick = 433,
|
||||||
|
pidfd_open = 434,
|
||||||
|
clone3 = 435,
|
||||||
|
close_range = 436,
|
||||||
|
openat2 = 437,
|
||||||
|
pidfd_getfd = 438,
|
||||||
|
faccessat2 = 439,
|
||||||
|
process_madvise = 440,
|
||||||
|
epoll_pwait2 = 441,
|
||||||
|
mount_setattr = 442,
|
||||||
|
quotactl_fd = 443,
|
||||||
|
landlock_create_ruleset = 444,
|
||||||
|
landlock_add_rule = 445,
|
||||||
|
landlock_restrict_self = 446,
|
||||||
|
memfd_secret = 447,
|
||||||
|
process_mrelease = 448,
|
||||||
|
futex_waitv = 449,
|
||||||
|
set_mempolicy_home_node = 450,
|
||||||
|
cachestat = 451,
|
||||||
|
fchmodat2 = 452,
|
||||||
|
map_shadow_stack = 453,
|
||||||
|
futex_wake = 454,
|
||||||
|
futex_wait = 455,
|
||||||
|
futex_requeue = 456,
|
||||||
|
};
|
||||||
|
|
||||||
const Syscall_x86_64 = enum(usize) {
|
const Syscall_x86_64 = enum(usize) {
|
||||||
read = 0,
|
read = 0,
|
||||||
write = 1,
|
write = 1,
|
||||||
@ -865,6 +1184,11 @@ const get_map_flags = fn(flags: std.os.MapFlags) MapFlags{
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const exit = fn (exit_code: s32) noreturn {
|
||||||
|
_ = #syscall(#cast(Syscall.exit), #cast(exit_code));
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
const mmap = fn(address: ?[&]u8, length: usize, protection_flags: ProtectionFlags, map_flags: MapFlags, fd: FileDescriptor, offset: u64) usize {
|
const mmap = fn(address: ?[&]u8, length: usize, protection_flags: ProtectionFlags, map_flags: MapFlags, fd: FileDescriptor, offset: u64) usize {
|
||||||
const flat_protection_flags: u32 = #cast(protection_flags);
|
const flat_protection_flags: u32 = #cast(protection_flags);
|
||||||
const flat_map_flags: u32 = #cast(map_flags);
|
const flat_map_flags: u32 = #cast(map_flags);
|
||||||
@ -884,13 +1208,70 @@ const munmap = fn(bytes: []const u8) usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const readlink = fn(file_path: [&:0]const u8, bytes: []u8) usize {
|
const readlink = fn(file_path: [&:0]const u8, bytes: []u8) usize {
|
||||||
const result = #syscall(#cast(Syscall.readlink), #cast(file_path), #cast(bytes.pointer), bytes.length);
|
switch (cpu) {
|
||||||
return result;
|
.x86_64 => {
|
||||||
|
const result = #syscall(#cast(Syscall.readlink), #cast(file_path), #cast(bytes.pointer), bytes.length);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
.aarch64 => {
|
||||||
|
const result = #syscall(#cast(Syscall.readlinkat), #cast(current_working_directory_file_descriptor), #cast(file_path), #cast(bytes.pointer), bytes.length);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SIG = struct {
|
||||||
|
const BLOCK = 0;
|
||||||
|
const UNBLOCK = 1;
|
||||||
|
const SETMASK = 2;
|
||||||
|
|
||||||
|
const HUP = 1;
|
||||||
|
const INT = 2;
|
||||||
|
const QUIT = 3;
|
||||||
|
const ILL = 4;
|
||||||
|
const TRAP = 5;
|
||||||
|
const ABRT = 6;
|
||||||
|
const IOT = ABRT;
|
||||||
|
const BUS = 7;
|
||||||
|
const FPE = 8;
|
||||||
|
const KILL = 9;
|
||||||
|
const USR1 = 10;
|
||||||
|
const SEGV = 11;
|
||||||
|
const USR2 = 12;
|
||||||
|
const PIPE = 13;
|
||||||
|
const ALRM = 14;
|
||||||
|
const TERM = 15;
|
||||||
|
const STKFLT = 16;
|
||||||
|
const CHLD = 17;
|
||||||
|
const CONT = 18;
|
||||||
|
const STOP = 19;
|
||||||
|
const TSTP = 20;
|
||||||
|
const TTIN = 21;
|
||||||
|
const TTOU = 22;
|
||||||
|
const URG = 23;
|
||||||
|
const XCPU = 24;
|
||||||
|
const XFSZ = 25;
|
||||||
|
const VTALRM = 26;
|
||||||
|
const PROF = 27;
|
||||||
|
const WINCH = 28;
|
||||||
|
const IO = 29;
|
||||||
|
const POLL = 29;
|
||||||
|
const PWR = 30;
|
||||||
|
const SYS = 31;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const fork = fn() usize {
|
const fork = fn() usize {
|
||||||
const result = #syscall(#cast(Syscall.fork));
|
switch (cpu) {
|
||||||
return result;
|
.x86_64 => {
|
||||||
|
const result = #syscall(#cast(Syscall.fork));
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
.aarch64 => {
|
||||||
|
const result = #syscall(#cast(Syscall.clone), SIG.CHLD, 0);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const execve = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) usize {
|
const execve = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) usize {
|
||||||
@ -910,8 +1291,16 @@ const dup2 = fn(old: FileDescriptor, new: FileDescriptor) usize {
|
|||||||
|
|
||||||
const open = fn(path: [&:0]const u8, flags: OpenFlags, permissions: u32) usize {
|
const open = fn(path: [&:0]const u8, flags: OpenFlags, permissions: u32) usize {
|
||||||
const flattened_flags: u32 = #cast(flags);
|
const flattened_flags: u32 = #cast(flags);
|
||||||
const result = #syscall(#cast(Syscall.open), #cast(path), flattened_flags, permissions);
|
switch (cpu) {
|
||||||
return result;
|
.x86_64 => {
|
||||||
|
const result = #syscall(#cast(Syscall.open), #cast(path), flattened_flags, permissions);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
.aarch64 => {
|
||||||
|
const result = #syscall(#cast(Syscall.openat), #cast(current_working_directory_file_descriptor), #cast(path), flattened_flags, permissions);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const openat = fn(directory_file_descriptor: FileDescriptor, path: [&:0]const u8, flags: u32, permissions: u32) usize {
|
const openat = fn(directory_file_descriptor: FileDescriptor, path: [&:0]const u8, flags: u32, permissions: u32) usize {
|
||||||
|
@ -9,12 +9,21 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const _start = fn naked cc(.c) () noreturn {
|
const _start = fn naked cc(.c) () noreturn {
|
||||||
#asm(`
|
switch (builtin.cpu) {
|
||||||
xor ebp, ebp;
|
.x86_64 => #asm(`
|
||||||
mov rdi, rsp;
|
xor ebp, ebp;
|
||||||
and rsp, 0xfffffffffffffff0;
|
mov rdi, rsp;
|
||||||
call {start};
|
and rsp, 0xfffffffffffffff0;
|
||||||
`);
|
call {start};
|
||||||
|
`),
|
||||||
|
.aarch64 => #asm(`
|
||||||
|
mov fp, 0;
|
||||||
|
mov lr, 0;
|
||||||
|
mov x0, sp;
|
||||||
|
b {start};
|
||||||
|
`),
|
||||||
|
else => #error("Architecture not supported"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var argument_count: usize = 0;
|
var argument_count: usize = 0;
|
||||||
|
4
test/cc_aarch64_linux/c_asm/assembly.S
Normal file
4
test/cc_aarch64_linux/c_asm/assembly.S
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.global foo
|
||||||
|
foo:
|
||||||
|
mov w0, #42
|
||||||
|
ret
|
2
test/cc_x86_64/c_asm/.gitignore
vendored
Normal file
2
test/cc_x86_64/c_asm/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.o
|
||||||
|
build/
|
3
test/cc_x86_64/c_asm/CMakeLists.txt
Normal file
3
test/cc_x86_64/c_asm/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
project(c_asm C ASM)
|
||||||
|
add_executable(c_asm main.c assembly.S)
|
7
test/cc_x86_64/c_asm/main.c
Normal file
7
test/cc_x86_64/c_asm/main.c
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
extern int foo();
|
||||||
|
#include <assert.h>
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
assert(foo() == 42);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user