Pass all tests on Apple M1
This commit is contained in:
parent
863603c03c
commit
1ecf7fa908
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -12,7 +12,7 @@
|
|||||||
"args": [
|
"args": [
|
||||||
"exe",
|
"exe",
|
||||||
"-main_source_file",
|
"-main_source_file",
|
||||||
"test/standalone/first/main.nat"
|
"test/standalone/hello_world/main.nat"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
},
|
},
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -32,6 +32,7 @@ pub const LLVM = struct {
|
|||||||
debug_type_map: AutoHashMap(Compilation.Type.Index, *LLVM.DebugInfo.Type) = .{},
|
debug_type_map: AutoHashMap(Compilation.Type.Index, *LLVM.DebugInfo.Type) = .{},
|
||||||
type_name_map: AutoHashMap(Compilation.Type.Index, []const u8) = .{},
|
type_name_map: AutoHashMap(Compilation.Type.Index, []const u8) = .{},
|
||||||
type_map: AutoHashMap(Compilation.Type.Index, *LLVM.Type) = .{},
|
type_map: AutoHashMap(Compilation.Type.Index, *LLVM.Type) = .{},
|
||||||
|
function_declaration_map: AutoArrayHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{},
|
||||||
function_definition_map: AutoArrayHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{},
|
function_definition_map: AutoArrayHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{},
|
||||||
llvm_instruction_map: AutoHashMap(Compilation.Instruction.Index, *LLVM.Value) = .{},
|
llvm_instruction_map: AutoHashMap(Compilation.Instruction.Index, *LLVM.Value) = .{},
|
||||||
llvm_value_map: AutoArrayHashMap(Compilation.V, *LLVM.Value) = .{},
|
llvm_value_map: AutoArrayHashMap(Compilation.V, *LLVM.Value) = .{},
|
||||||
@ -47,7 +48,7 @@ pub const LLVM = struct {
|
|||||||
return_phi_node: ?*LLVM.Value.Instruction.PhiNode = null,
|
return_phi_node: ?*LLVM.Value.Instruction.PhiNode = null,
|
||||||
scope: *LLVM.DebugInfo.Scope = undefined,
|
scope: *LLVM.DebugInfo.Scope = undefined,
|
||||||
file: *LLVM.DebugInfo.File = undefined,
|
file: *LLVM.DebugInfo.File = undefined,
|
||||||
subprogram: *LLVM.DebugInfo.Subprogram = undefined,
|
// subprogram: *LLVM.DebugInfo.Subprogram = undefined,
|
||||||
arg_index: u32 = 0,
|
arg_index: u32 = 0,
|
||||||
tag_count: c_uint = 0,
|
tag_count: c_uint = 0,
|
||||||
inside_branch: bool = false,
|
inside_branch: bool = false,
|
||||||
@ -1281,13 +1282,13 @@ pub const LLVM = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn renderTypeName(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, sema_type_index: Compilation.Type.Index) ![]const u8 {
|
fn renderTypeName(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, sema_type_index: Compilation.Type.Index) ![]const u8 {
|
||||||
const gop = try llvm.type_name_map.getOrPut(context.allocator, sema_type_index);
|
if (llvm.type_name_map.get(sema_type_index)) |result| {
|
||||||
if (gop.found_existing) {
|
return result;
|
||||||
return gop.value_ptr.*;
|
|
||||||
} else {
|
} else {
|
||||||
if (unit.type_declarations.get(sema_type_index)) |global_declaration| {
|
if (unit.type_declarations.get(sema_type_index)) |global_declaration| {
|
||||||
gop.value_ptr.* = unit.getIdentifier(global_declaration.declaration.name);
|
const result = unit.getIdentifier(global_declaration.declaration.name);
|
||||||
return gop.value_ptr.*;
|
try llvm.type_name_map.putNoClobber(context.allocator, sema_type_index, result);
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
const sema_type = unit.types.get(sema_type_index);
|
const sema_type = unit.types.get(sema_type_index);
|
||||||
const result: []const u8 = switch (sema_type.*) {
|
const result: []const u8 = switch (sema_type.*) {
|
||||||
@ -2241,6 +2242,114 @@ pub const LLVM = struct {
|
|||||||
const call = llvm.builder.createCall(intrinsic_type, intrinsic_function.toValue(), intrinsic_arguments.ptr, intrinsic_arguments.len, name.ptr, name.len, null) orelse return LLVM.Value.Instruction.Error.call;
|
const call = llvm.builder.createCall(intrinsic_type, intrinsic_function.toValue(), intrinsic_arguments.ptr, intrinsic_arguments.len, name.ptr, name.len, null) orelse return LLVM.Value.Instruction.Error.call;
|
||||||
return call.toValue();
|
return call.toValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emitFunctionDeclaration(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, declaration: *Compilation.Debug.Declaration.Global) !void {
|
||||||
|
const function_type = try llvm.getType(unit, context, declaration.declaration.type);
|
||||||
|
const is_export = declaration.attributes.contains(.@"export");
|
||||||
|
const is_extern = declaration.attributes.contains(.@"extern");
|
||||||
|
const export_or_extern = is_export or is_extern;
|
||||||
|
|
||||||
|
const linkage: LLVM.Linkage = switch (export_or_extern) {
|
||||||
|
true => .@"extern",
|
||||||
|
false => .internal,
|
||||||
|
};
|
||||||
|
// TODO: Check name collision
|
||||||
|
const mangle_name = !export_or_extern;
|
||||||
|
_ = mangle_name; // autofix
|
||||||
|
const name = unit.getIdentifier(declaration.declaration.name);
|
||||||
|
const function = llvm.module.createFunction(function_type.toFunction() orelse unreachable, linkage, address_space, name.ptr, name.len) orelse return Error.function;
|
||||||
|
|
||||||
|
const function_prototype = unit.function_prototypes.get(unit.types.get(declaration.declaration.type).function);
|
||||||
|
switch (unit.types.get(function_prototype.return_type).*) {
|
||||||
|
.noreturn => {
|
||||||
|
function.addAttributeKey(.NoReturn);
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function_prototype.attributes.naked) {
|
||||||
|
function.addAttributeKey(.Naked);
|
||||||
|
}
|
||||||
|
|
||||||
|
const calling_convention = getCallingConvention(function_prototype.calling_convention);
|
||||||
|
function.setCallingConvention(calling_convention);
|
||||||
|
|
||||||
|
switch (declaration.initial_value) {
|
||||||
|
.function_declaration => try llvm.function_declaration_map.putNoClobber(context.allocator, declaration, function),
|
||||||
|
.function_definition => try llvm.function_definition_map.putNoClobber(context.allocator, declaration, function),
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unit.descriptor.generate_debug_information) {
|
||||||
|
const debug_file = try llvm.getDebugInfoFile(unit, context, declaration.declaration.scope.file);
|
||||||
|
var parameter_types = try ArrayList(*LLVM.DebugInfo.Type).initCapacity(context.allocator, function_prototype.argument_types.len);
|
||||||
|
for (function_prototype.argument_types) |argument_type_index| {
|
||||||
|
const argument_type = try llvm.getDebugType(unit, context, argument_type_index);
|
||||||
|
parameter_types.appendAssumeCapacity(argument_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
const subroutine_type_flags = LLVM.DebugInfo.Node.Flags{
|
||||||
|
.visibility = .none,
|
||||||
|
.forward_declaration = is_extern,
|
||||||
|
.apple_block = false,
|
||||||
|
.block_by_ref_struct = false,
|
||||||
|
.virtual = false,
|
||||||
|
.artificial = false,
|
||||||
|
.explicit = false,
|
||||||
|
.prototyped = false,
|
||||||
|
.objective_c_class_complete = false,
|
||||||
|
.object_pointer = false,
|
||||||
|
.vector = false,
|
||||||
|
.static_member = false,
|
||||||
|
.lvalue_reference = false,
|
||||||
|
.rvalue_reference = false,
|
||||||
|
.reserved = false,
|
||||||
|
.inheritance = .none,
|
||||||
|
.introduced_virtual = false,
|
||||||
|
.bit_field = false,
|
||||||
|
.no_return = false,
|
||||||
|
.type_pass_by_value = false,
|
||||||
|
.type_pass_by_reference = false,
|
||||||
|
.enum_class = false,
|
||||||
|
.thunk = false,
|
||||||
|
.non_trivial = false,
|
||||||
|
.big_endian = false,
|
||||||
|
.little_endian = false,
|
||||||
|
.all_calls_described = false,
|
||||||
|
};
|
||||||
|
const subroutine_type_calling_convention = LLVM.DebugInfo.CallingConvention.none;
|
||||||
|
const subroutine_type = llvm.debug_info_builder.createSubroutineType(parameter_types.items.ptr, parameter_types.items.len, subroutine_type_flags, subroutine_type_calling_convention) orelse unreachable;
|
||||||
|
const scope_line = 0;
|
||||||
|
const subprogram_flags = LLVM.DebugInfo.Subprogram.Flags{
|
||||||
|
.virtuality = .none,
|
||||||
|
.local_to_unit = !export_or_extern,
|
||||||
|
.definition = !is_extern,
|
||||||
|
.optimized = false,
|
||||||
|
.pure = false,
|
||||||
|
.elemental = false,
|
||||||
|
.recursive = false,
|
||||||
|
.main_subprogram = false,
|
||||||
|
.deleted = false,
|
||||||
|
.object_c_direct = false,
|
||||||
|
};
|
||||||
|
const subprogram_declaration = null;
|
||||||
|
const function_name = unit.getIdentifier(declaration.declaration.name);
|
||||||
|
const subprogram = llvm.debug_info_builder.createFunction(debug_file.toScope(), function_name.ptr, function_name.len, function_name.ptr, function_name.len, debug_file, declaration.declaration.line + 1, subroutine_type, scope_line, subroutine_type_flags, subprogram_flags, subprogram_declaration) orelse unreachable;
|
||||||
|
function.setSubprogram(subprogram);
|
||||||
|
|
||||||
|
switch (declaration.initial_value) {
|
||||||
|
.function_declaration => {},
|
||||||
|
.function_definition => |function_definition_index| {
|
||||||
|
const function_definition = unit.function_definitions.get(function_definition_index);
|
||||||
|
const scope = subprogram.toLocalScope().toScope();
|
||||||
|
|
||||||
|
try llvm.scope_map.putNoClobber(context.allocator, &function_definition.scope.scope, scope);
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getCallingConvention(calling_convention: Compilation.Function.CallingConvention) LLVM.Value.Constant.Function.CallingConvention {
|
fn getCallingConvention(calling_convention: Compilation.Function.CallingConvention) LLVM.Value.Constant.Function.CallingConvention {
|
||||||
@ -2305,49 +2414,26 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
try llvm.scope_map.putNoClobber(context.allocator, &unit.scope.scope, llvm.scope);
|
try llvm.scope_map.putNoClobber(context.allocator, &unit.scope.scope, llvm.scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unit.external_functions.values()) |external_function_declaration| {
|
||||||
|
try llvm.emitFunctionDeclaration(unit, context, external_function_declaration);
|
||||||
|
}
|
||||||
|
|
||||||
const functions = unit.code_to_emit.values();
|
const functions = unit.code_to_emit.values();
|
||||||
|
|
||||||
{
|
{
|
||||||
var function_i: usize = functions.len;
|
var function_i: usize = functions.len;
|
||||||
|
// Emit it in reverse order so the code goes the right order, from entry point to leaves
|
||||||
while (function_i > 0) {
|
while (function_i > 0) {
|
||||||
function_i -= 1;
|
function_i -= 1;
|
||||||
const function_declaration = functions[function_i];
|
const function_declaration = functions[function_i];
|
||||||
const function_definition_index = function_declaration.getFunctionDefinitionIndex();
|
try llvm.emitFunctionDeclaration(unit, context, function_declaration);
|
||||||
const function_definition = unit.function_definitions.get(function_definition_index);
|
|
||||||
const function_type = try llvm.getType(unit, context, function_definition.type);
|
|
||||||
const is_export = function_declaration.attributes.contains(.@"export");
|
|
||||||
const linkage: LLVM.Linkage = switch (is_export) {
|
|
||||||
true => .@"extern",
|
|
||||||
false => .internal,
|
|
||||||
};
|
|
||||||
// TODO: Check name collision
|
|
||||||
const mangle_name = !is_export;
|
|
||||||
_ = mangle_name; // autofix
|
|
||||||
const name = unit.getIdentifier(function_declaration.declaration.name);
|
|
||||||
const function = llvm.module.createFunction(function_type.toFunction() orelse unreachable, linkage, address_space, name.ptr, name.len) orelse return Error.function;
|
|
||||||
|
|
||||||
const function_prototype = unit.function_prototypes.get(unit.types.get(function_definition.type).function);
|
|
||||||
switch (unit.types.get(function_prototype.return_type).*) {
|
|
||||||
.noreturn => {
|
|
||||||
function.addAttributeKey(.NoReturn);
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
if (function_prototype.attributes.naked) {
|
|
||||||
function.addAttributeKey(.Naked);
|
|
||||||
}
|
|
||||||
|
|
||||||
const calling_convention = getCallingConvention(function_prototype.calling_convention);
|
|
||||||
function.setCallingConvention(calling_convention);
|
|
||||||
|
|
||||||
try llvm.function_definition_map.putNoClobber(context.allocator, function_declaration, function);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, cache all the global variables
|
// First, cache all the global variables
|
||||||
for (unit.data_to_emit.items) |global_declaration| {
|
for (unit.data_to_emit.items) |global_declaration| {
|
||||||
const name = unit.getIdentifier(global_declaration.declaration.name);
|
const name = unit.getIdentifier(global_declaration.declaration.name);
|
||||||
|
|
||||||
switch (global_declaration.initial_value) {
|
switch (global_declaration.initial_value) {
|
||||||
.string_literal => |hash| {
|
.string_literal => |hash| {
|
||||||
const string_literal = unit.string_literal_values.get(hash).?;
|
const string_literal = unit.string_literal_values.get(hash).?;
|
||||||
@ -2402,68 +2488,11 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
llvm.function = function;
|
llvm.function = function;
|
||||||
llvm.sema_function = function_declaration;
|
llvm.sema_function = function_declaration;
|
||||||
llvm.inside_branch = false;
|
llvm.inside_branch = false;
|
||||||
const function_prototype = unit.function_prototypes.get(unit.types.get(function_definition.type).function);
|
|
||||||
const function_name = unit.getIdentifier(function_declaration.declaration.name);
|
|
||||||
|
|
||||||
if (unit.descriptor.generate_debug_information) {
|
if (unit.descriptor.generate_debug_information) {
|
||||||
const debug_file = try llvm.getDebugInfoFile(unit, context, function_declaration.declaration.scope.file);
|
const subprogram = llvm.function.getSubprogram() orelse unreachable;
|
||||||
var parameter_types = try ArrayList(*LLVM.DebugInfo.Type).initCapacity(context.allocator, function_prototype.argument_types.len);
|
|
||||||
for (function_prototype.argument_types) |argument_type_index| {
|
|
||||||
const argument_type = try llvm.getDebugType(unit, context, argument_type_index);
|
|
||||||
parameter_types.appendAssumeCapacity(argument_type);
|
|
||||||
}
|
|
||||||
const subroutine_type_flags = LLVM.DebugInfo.Node.Flags{
|
|
||||||
.visibility = .none,
|
|
||||||
.forward_declaration = false,
|
|
||||||
.apple_block = false,
|
|
||||||
.block_by_ref_struct = false,
|
|
||||||
.virtual = false,
|
|
||||||
.artificial = false,
|
|
||||||
.explicit = false,
|
|
||||||
.prototyped = false,
|
|
||||||
.objective_c_class_complete = false,
|
|
||||||
.object_pointer = false,
|
|
||||||
.vector = false,
|
|
||||||
.static_member = false,
|
|
||||||
.lvalue_reference = false,
|
|
||||||
.rvalue_reference = false,
|
|
||||||
.reserved = false,
|
|
||||||
.inheritance = .none,
|
|
||||||
.introduced_virtual = false,
|
|
||||||
.bit_field = false,
|
|
||||||
.no_return = false,
|
|
||||||
.type_pass_by_value = false,
|
|
||||||
.type_pass_by_reference = false,
|
|
||||||
.enum_class = false,
|
|
||||||
.thunk = false,
|
|
||||||
.non_trivial = false,
|
|
||||||
.big_endian = false,
|
|
||||||
.little_endian = false,
|
|
||||||
.all_calls_described = false,
|
|
||||||
};
|
|
||||||
const subroutine_type_calling_convention = LLVM.DebugInfo.CallingConvention.none;
|
|
||||||
const subroutine_type = llvm.debug_info_builder.createSubroutineType(parameter_types.items.ptr, parameter_types.items.len, subroutine_type_flags, subroutine_type_calling_convention) orelse unreachable;
|
|
||||||
const scope_line = 0;
|
|
||||||
const subprogram_flags = LLVM.DebugInfo.Subprogram.Flags{
|
|
||||||
.virtuality = .none,
|
|
||||||
.local_to_unit = true,
|
|
||||||
.definition = true,
|
|
||||||
.optimized = false,
|
|
||||||
.pure = false,
|
|
||||||
.elemental = false,
|
|
||||||
.recursive = false,
|
|
||||||
.main_subprogram = false,
|
|
||||||
.deleted = false,
|
|
||||||
.object_c_direct = false,
|
|
||||||
};
|
|
||||||
const subprogram_declaration = null;
|
|
||||||
const subprogram = llvm.debug_info_builder.createFunction(debug_file.toScope(), function_name.ptr, function_name.len, function_name.ptr, function_name.len, debug_file, function_declaration.declaration.line + 1, subroutine_type, scope_line, subroutine_type_flags, subprogram_flags, subprogram_declaration) orelse unreachable;
|
|
||||||
llvm.function.setSubprogram(subprogram);
|
|
||||||
llvm.file = subprogram.getFile() orelse unreachable;
|
llvm.file = subprogram.getFile() orelse unreachable;
|
||||||
llvm.subprogram = subprogram;
|
|
||||||
llvm.scope = subprogram.toLocalScope().toScope();
|
llvm.scope = subprogram.toLocalScope().toScope();
|
||||||
|
|
||||||
try llvm.scope_map.putNoClobber(context.allocator, &function_definition.scope.scope, llvm.scope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm.arg_index = 0;
|
llvm.arg_index = 0;
|
||||||
@ -2496,7 +2525,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
.pop_scope => |pop_scope| {
|
.pop_scope => |pop_scope| {
|
||||||
const new = try llvm.getScope(unit, context, pop_scope.new);
|
const new = try llvm.getScope(unit, context, pop_scope.new);
|
||||||
if (pop_scope.new.kind == .function) {
|
if (pop_scope.new.kind == .function) {
|
||||||
assert(new.toSubprogram() orelse unreachable == llvm.subprogram);
|
assert(new.toSubprogram() orelse unreachable == llvm.function.getSubprogram() orelse unreachable);
|
||||||
}
|
}
|
||||||
llvm.scope = new;
|
llvm.scope = new;
|
||||||
var scope = pop_scope.old;
|
var scope = pop_scope.old;
|
||||||
@ -2504,7 +2533,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
scope = scope.parent.?;
|
scope = scope.parent.?;
|
||||||
}
|
}
|
||||||
const subprogram_scope = try llvm.getScope(unit, context, scope);
|
const subprogram_scope = try llvm.getScope(unit, context, scope);
|
||||||
assert(llvm.subprogram == subprogram_scope.toSubprogram() orelse unreachable);
|
assert(llvm.function.getSubprogram() orelse unreachable == subprogram_scope.toSubprogram() orelse unreachable);
|
||||||
},
|
},
|
||||||
.debug_checkpoint => |debug_checkpoint| {
|
.debug_checkpoint => |debug_checkpoint| {
|
||||||
const scope = try llvm.getScope(unit, context, debug_checkpoint.scope);
|
const scope = try llvm.getScope(unit, context, debug_checkpoint.scope);
|
||||||
@ -2600,6 +2629,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
.slice => {},
|
.slice => {},
|
||||||
.array => {},
|
.array => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
const declaration_type = try llvm.getType(unit, context, stack_slot.type);
|
const declaration_type = try llvm.getType(unit, context, stack_slot.type);
|
||||||
const alloca_array_size = null;
|
const alloca_array_size = null;
|
||||||
const declaration_alloca = llvm.builder.createAlloca(declaration_type, address_space, alloca_array_size, "", "".len) orelse return LLVM.Value.Instruction.Error.alloca;
|
const declaration_alloca = llvm.builder.createAlloca(declaration_type, address_space, alloca_array_size, "", "".len) orelse return LLVM.Value.Instruction.Error.alloca;
|
||||||
@ -2630,6 +2660,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
.enum_to_int,
|
.enum_to_int,
|
||||||
.slice_to_nullable,
|
.slice_to_nullable,
|
||||||
.slice_to_not_null,
|
.slice_to_not_null,
|
||||||
|
.slice_coerce_to_zero_termination,
|
||||||
.pointer_to_nullable,
|
.pointer_to_nullable,
|
||||||
.pointer_const_to_var,
|
.pointer_const_to_var,
|
||||||
.pointer_to_array_to_pointer_to_many,
|
.pointer_to_array_to_pointer_to_many,
|
||||||
@ -2676,7 +2707,6 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
};
|
};
|
||||||
|
|
||||||
const value_type = try llvm.getType(unit, context, load.type);
|
const value_type = try llvm.getType(unit, context, load.type);
|
||||||
// const value_type = try llvm.getType(unit, context, load.value.type);
|
|
||||||
const is_volatile = false;
|
const is_volatile = false;
|
||||||
const load_i = llvm.builder.createLoad(value_type, value, is_volatile, "", "".len) orelse return LLVM.Value.Instruction.Error.load;
|
const load_i = llvm.builder.createLoad(value_type, value, is_volatile, "", "".len) orelse return LLVM.Value.Instruction.Error.load;
|
||||||
try llvm.llvm_instruction_map.putNoClobber(context.allocator, instruction_index, load_i.toValue());
|
try llvm.llvm_instruction_map.putNoClobber(context.allocator, instruction_index, load_i.toValue());
|
||||||
@ -2722,11 +2752,18 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
switch (call.callable.value) {
|
switch (call.callable.value) {
|
||||||
.@"comptime" => |ct| switch (ct) {
|
.@"comptime" => |ct| switch (ct) {
|
||||||
.global => |call_function_declaration| {
|
.global => |call_function_declaration| {
|
||||||
const call_function_definition_index = call_function_declaration.getFunctionDefinitionIndex();
|
const call_function_type = call_function_declaration.declaration.type;
|
||||||
const callee = llvm.function_definition_map.get(call_function_declaration).?;
|
// const call_function_definition_index = call_function_declaration.getFunctionDefinitionIndex();
|
||||||
const call_function_definition = unit.function_definitions.get(call_function_definition_index);
|
// const callee = llvm.function_definition_map.get(call_function_declaration).?;
|
||||||
const call_function_prototype = unit.function_prototypes.get(unit.types.get(call_function_definition.type).function);
|
const call_function_prototype = unit.function_prototypes.get(unit.types.get(call_function_type).function);
|
||||||
assert(call_function_definition.type == call.function_type);
|
assert(call_function_type == call.function_type);
|
||||||
|
|
||||||
|
const callee = switch (call_function_declaration.initial_value) {
|
||||||
|
.function_definition => llvm.function_definition_map.get(call_function_declaration).?,
|
||||||
|
.function_declaration => llvm.function_declaration_map.get(call_function_declaration).?,
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
for (call.arguments, arguments) |argument_value, *argument| {
|
for (call.arguments, arguments) |argument_value, *argument| {
|
||||||
argument.* = try llvm.emitRightValue(unit, context, argument_value);
|
argument.* = try llvm.emitRightValue(unit, context, argument_value);
|
||||||
@ -3062,7 +3099,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unit.descriptor.generate_debug_information) {
|
if (unit.descriptor.generate_debug_information) {
|
||||||
llvm.debug_info_builder.finalizeSubprogram(llvm.subprogram, llvm.function);
|
llvm.debug_info_builder.finalizeSubprogram(llvm.function.getSubprogram() orelse unreachable, llvm.function);
|
||||||
}
|
}
|
||||||
|
|
||||||
const verify_function = true;
|
const verify_function = true;
|
||||||
|
@ -304,7 +304,7 @@ const Analyzer = struct {
|
|||||||
if (equal(u8, identifier_name, enum_field.name)) {
|
if (equal(u8, identifier_name, enum_field.name)) {
|
||||||
const attribute = @field(Compilation.Debug.Declaration.Global.Attribute, enum_field.name);
|
const attribute = @field(Compilation.Debug.Declaration.Global.Attribute, enum_field.name);
|
||||||
const attribute_node = switch (attribute) {
|
const attribute_node = switch (attribute) {
|
||||||
.@"export" => try analyzer.addNode(.{
|
.@"export", .@"extern", => try analyzer.addNode(.{
|
||||||
.id = @field(Node.Id, "symbol_attribute_" ++ @tagName(attribute)),
|
.id = @field(Node.Id, "symbol_attribute_" ++ @tagName(attribute)),
|
||||||
.token = identifier,
|
.token = identifier,
|
||||||
.left = .null,
|
.left = .null,
|
||||||
@ -313,7 +313,7 @@ const Analyzer = struct {
|
|||||||
};
|
};
|
||||||
break attribute_node;
|
break attribute_node;
|
||||||
}
|
}
|
||||||
} else @panic("Not known attribute");
|
} else panic("Unknown symbol attribute: {s}", .{identifier_name});
|
||||||
try list.append(analyzer.allocator, attribute_node);
|
try list.append(analyzer.allocator, attribute_node);
|
||||||
|
|
||||||
switch (analyzer.peekToken()) {
|
switch (analyzer.peekToken()) {
|
||||||
@ -400,7 +400,7 @@ const Analyzer = struct {
|
|||||||
};
|
};
|
||||||
break attribute_node;
|
break attribute_node;
|
||||||
}
|
}
|
||||||
} else @panic("Not known attribute");
|
} else panic("Unknown function attribute: {s}", .{identifier_name});
|
||||||
|
|
||||||
try attribute_and_return_type_node_list.append(analyzer.allocator, attribute_node);
|
try attribute_and_return_type_node_list.append(analyzer.allocator, attribute_node);
|
||||||
|
|
||||||
@ -1128,7 +1128,8 @@ const Analyzer = struct {
|
|||||||
fn primaryExpression(analyzer: *Analyzer) !Node.Index {
|
fn primaryExpression(analyzer: *Analyzer) !Node.Index {
|
||||||
const result = switch (analyzer.peekToken()) {
|
const result = switch (analyzer.peekToken()) {
|
||||||
.identifier => switch (analyzer.peekTokenAhead(1)) {
|
.identifier => switch (analyzer.peekTokenAhead(1)) {
|
||||||
.operator_colon => unreachable,
|
// TODO: tags
|
||||||
|
// .operator_colon => unreachable,
|
||||||
else => try analyzer.curlySuffixExpression(),
|
else => try analyzer.curlySuffixExpression(),
|
||||||
},
|
},
|
||||||
.string_literal,
|
.string_literal,
|
||||||
@ -1349,6 +1350,7 @@ const Analyzer = struct {
|
|||||||
.operator_right_parenthesis,
|
.operator_right_parenthesis,
|
||||||
.operator_left_brace,
|
.operator_left_brace,
|
||||||
.operator_assign,
|
.operator_assign,
|
||||||
|
.operator_semicolon,
|
||||||
=> return node_index,
|
=> return node_index,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
|
56
build.zig
56
build.zig
@ -5,7 +5,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const self_hosted_ci = b.option(bool, "self_hosted_ci", "This option enables the self-hosted CI behavior") orelse false;
|
const self_hosted_ci = b.option(bool, "self_hosted_ci", "This option enables the self-hosted CI behavior") orelse false;
|
||||||
const third_party_ci = b.option(bool, "third_party_ci", "This option enables the third-party CI behavior") orelse false;
|
const third_party_ci = b.option(bool, "third_party_ci", "This option enables the third-party CI behavior") orelse false;
|
||||||
const is_ci = self_hosted_ci or third_party_ci;
|
const is_ci = self_hosted_ci or third_party_ci;
|
||||||
const print_stack_trace = b.option(bool, "print_stack_trace", "This option enables printing stack traces inside the compiler") orelse is_ci;
|
const print_stack_trace = b.option(bool, "print_stack_trace", "This option enables printing stack traces inside the compiler") orelse is_ci or @import("builtin").os.tag == .macos;
|
||||||
const native_target = b.resolveTargetQuery(.{});
|
const native_target = b.resolveTargetQuery(.{});
|
||||||
const optimization = b.standardOptimizeOption(.{});
|
const optimization = b.standardOptimizeOption(.{});
|
||||||
var target_query = b.standardTargetOptionsQueryOnly(.{});
|
var target_query = b.standardTargetOptionsQueryOnly(.{});
|
||||||
@ -14,6 +14,32 @@ pub fn build(b: *std.Build) !void {
|
|||||||
target_query.abi = .musl;
|
target_query.abi = .musl;
|
||||||
}
|
}
|
||||||
const target = b.resolveTargetQuery(target_query);
|
const target = b.resolveTargetQuery(target_query);
|
||||||
|
const compiler_options = b.addOptions();
|
||||||
|
compiler_options.addOption(bool, "print_stack_trace", print_stack_trace);
|
||||||
|
|
||||||
|
const compiler = b.addExecutable(.{
|
||||||
|
.name = "nat",
|
||||||
|
.root_source_file = .{ .path = "bootstrap/main.zig" },
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimization,
|
||||||
|
});
|
||||||
|
compiler.root_module.addOptions("configuration", compiler_options);
|
||||||
|
compiler.formatted_panics = print_stack_trace;
|
||||||
|
compiler.root_module.unwind_tables = print_stack_trace;
|
||||||
|
compiler.root_module.omit_frame_pointer = false;
|
||||||
|
compiler.want_lto = false;
|
||||||
|
|
||||||
|
compiler.linkLibC();
|
||||||
|
compiler.linkSystemLibrary("c++");
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// if (target.result.os.tag == .windows) {
|
||||||
|
// compiler.linkSystemLibrary("ole32");
|
||||||
|
// compiler.linkSystemLibrary("version");
|
||||||
|
// compiler.linkSystemLibrary("uuid");
|
||||||
|
// compiler.linkSystemLibrary("msvcrt-os");
|
||||||
|
// }
|
||||||
|
|
||||||
const llvm_version = "17.0.6";
|
const llvm_version = "17.0.6";
|
||||||
var fetcher_run: ?*std.Build.Step.Run = null;
|
var fetcher_run: ?*std.Build.Step.Run = null;
|
||||||
const llvm_path = b.option([]const u8, "llvm_path", "LLVM prefix path") orelse blk: {
|
const llvm_path = b.option([]const u8, "llvm_path", "LLVM prefix path") orelse blk: {
|
||||||
@ -69,30 +95,6 @@ pub fn build(b: *std.Build) !void {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const compiler_options = b.addOptions();
|
|
||||||
compiler_options.addOption(bool, "print_stack_trace", print_stack_trace);
|
|
||||||
|
|
||||||
const compiler = b.addExecutable(.{
|
|
||||||
.name = "nat",
|
|
||||||
.root_source_file = .{ .path = "bootstrap/main.zig" },
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimization,
|
|
||||||
});
|
|
||||||
compiler.root_module.addOptions("configuration", compiler_options);
|
|
||||||
compiler.formatted_panics = print_stack_trace;
|
|
||||||
compiler.root_module.unwind_tables = print_stack_trace;
|
|
||||||
compiler.root_module.omit_frame_pointer = false;
|
|
||||||
compiler.want_lto = false;
|
|
||||||
|
|
||||||
compiler.linkLibC();
|
|
||||||
compiler.linkSystemLibrary("c++");
|
|
||||||
|
|
||||||
if (target.result.os.tag == .windows) {
|
|
||||||
compiler.linkSystemLibrary("ole32");
|
|
||||||
compiler.linkSystemLibrary("version");
|
|
||||||
compiler.linkSystemLibrary("uuid");
|
|
||||||
compiler.linkSystemLibrary("msvcrt-os");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fetcher_run) |fr| {
|
if (fetcher_run) |fr| {
|
||||||
compiler.step.dependOn(&fr.step);
|
compiler.step.dependOn(&fr.step);
|
||||||
@ -408,13 +410,9 @@ pub fn build(b: *std.Build) !void {
|
|||||||
test_command.step.dependOn(b.getInstallStep());
|
test_command.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
if (b.args) |args| {
|
if (b.args) |args| {
|
||||||
std.debug.print("Args: {s}", .{args});
|
|
||||||
run_command.addArgs(args);
|
run_command.addArgs(args);
|
||||||
debug_command.addArgs(args);
|
debug_command.addArgs(args);
|
||||||
test_command.addArgs(args);
|
test_command.addArgs(args);
|
||||||
for (debug_command.argv.items, 0..) |arg, i| {
|
|
||||||
std.debug.print("Arg #{}: {s}\n", .{i, arg.bytes});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const run_step = b.step("run", "Test the Nativity compiler");
|
const run_step = b.step("run", "Test the Nativity compiler");
|
||||||
|
@ -7,6 +7,7 @@ const Os = enum{
|
|||||||
|
|
||||||
const Cpu = enum{
|
const Cpu = enum{
|
||||||
x86_64,
|
x86_64,
|
||||||
|
aarch64,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Abi = enum{
|
const Abi = enum{
|
||||||
|
@ -11,17 +11,20 @@ const exit = fn(exit_code: s32) noreturn {
|
|||||||
switch (current) {
|
switch (current) {
|
||||||
.linux => _ = #syscall(#cast(linux.Syscall.exit_group), #cast(exit_code)),
|
.linux => _ = #syscall(#cast(linux.Syscall.exit_group), #cast(exit_code)),
|
||||||
.macos => macos.exit(exit_code),
|
.macos => macos.exit(exit_code),
|
||||||
.windows => windows.ExitProcess(exit_code),
|
.windows => windows.ExitProcess(#cast(exit_code)),
|
||||||
}
|
}
|
||||||
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const max_file_operation_byte_count = switch (current) {
|
const max_file_operation_byte_count = switch (current) {
|
||||||
.linux => 0x7ffff000,
|
.linux => 0x7ffff000,
|
||||||
|
.macos => 0x7fffffff,
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unwrap_syscall_signed = fn(syscall_result: ssize) bool {
|
||||||
|
return syscall_result >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
const FileDescriptor = struct{
|
const FileDescriptor = struct{
|
||||||
handle: system.FileDescriptor,
|
handle: system.FileDescriptor,
|
||||||
|
|
||||||
@ -54,6 +57,15 @@ const FileDescriptor = struct{
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.macos => {
|
||||||
|
const raw_result = macos.write(file_descriptor.handle, bytes.ptr, bytes.len);
|
||||||
|
if (unwrap_syscall_signed(raw_result)) {
|
||||||
|
const bytes_written: usize = #cast(raw_result);
|
||||||
|
return bytes_written;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,16 +102,27 @@ const MapFlags = struct(u32){
|
|||||||
const allocate_virtual_memory = fn(address: ?[&]u8, length: usize, general_protection_flags: ProtectionFlags, general_map_flags: MapFlags) ?[&]u8 {
|
const allocate_virtual_memory = fn(address: ?[&]u8, length: usize, general_protection_flags: ProtectionFlags, general_map_flags: MapFlags) ?[&]u8 {
|
||||||
const protection_flags = system.get_protection_flags(flags = general_protection_flags);
|
const protection_flags = system.get_protection_flags(flags = general_protection_flags);
|
||||||
const map_flags = system.get_map_flags(flags = general_map_flags);
|
const map_flags = system.get_map_flags(flags = general_map_flags);
|
||||||
|
const fd = -1;
|
||||||
|
const offset = 0;
|
||||||
|
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux => {
|
.linux => {
|
||||||
if (linux.unwrap_syscall(syscall_result = linux.mmap(address, length, protection_flags, map_flags, fd = -1, offset = 0))) |result_address| {
|
if (linux.unwrap_syscall(syscall_result = linux.mmap(address, length, protection_flags, map_flags, fd, offset))) |result_address| {
|
||||||
const pointer: [&]u8 = #cast(result_address);
|
const pointer: [&]u8 = #cast(result_address);
|
||||||
return pointer;
|
return pointer;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.macos => {
|
||||||
|
const result = macos.mmap(address, length, protection_flags, map_flags, fd, offset);
|
||||||
|
if (result != macos.MAP_FAILED) {
|
||||||
|
const result_address: [&]u8 = #cast(result);
|
||||||
|
return result_address;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +137,11 @@ const free_virtual_memory = fn(bytes_ptr: [&]const u8, bytes_len: usize) bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.macos => {
|
||||||
|
const raw_result = macos.munmap(bytes_ptr, bytes_len);
|
||||||
|
const result = unwrap_syscall_signed(raw_result);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,10 +164,11 @@ const readlink = fn(file_path: [&:0]const u8, buffer: []u8) ?[]u8 {
|
|||||||
|
|
||||||
const max_path_byte_count = switch (current) {
|
const max_path_byte_count = switch (current) {
|
||||||
.linux => 0x1000,
|
.linux => 0x1000,
|
||||||
|
.macos => 1024,
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const current_executable_path = fn(buffer: []u8) ?[]u8 {
|
const current_executable_path = fn(buffer: [:0]u8) ?[]u8 {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux => {
|
.linux => {
|
||||||
if (readlink(file_path = "/proc/self/exe", buffer)) |bytes| {
|
if (readlink(file_path = "/proc/self/exe", buffer)) |bytes| {
|
||||||
@ -148,6 +177,31 @@ const current_executable_path = fn(buffer: []u8) ?[]u8 {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.macos => {
|
||||||
|
var symlink_path_buffer: [max_path_byte_count:0]u8 = undefined;
|
||||||
|
var symlink_path_len: u32 = symlink_path_buffer.len + 1;
|
||||||
|
const ns_result = macos._NSGetExecutablePath(symlink_path_buffer.&, symlink_path_len.&);
|
||||||
|
if (ns_result == 0) {
|
||||||
|
const symlink_path = symlink_path_buffer[0..symlink_path_len];
|
||||||
|
const result = macos.realpath(symlink_path.ptr, buffer.ptr);
|
||||||
|
if (result != null) {
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < buffer.len) {
|
||||||
|
if (result[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
#assert(i < buffer.len);
|
||||||
|
|
||||||
|
return result[0..i];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,14 +221,25 @@ const duplicate_process = fn () ?Process.Id {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.macos => {
|
||||||
|
const fork_result = macos.fork();
|
||||||
|
if (unwrap_syscall_signed(fork_result)) {
|
||||||
|
return fork_result;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const execute = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) usize {
|
const execute = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) void {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux => {
|
.linux => {
|
||||||
return linux.execve(path, argv, env);
|
_ = linux.execve(path, argv, env);
|
||||||
|
},
|
||||||
|
.macos => {
|
||||||
|
_ = macos.execve(path, argv, env);
|
||||||
},
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
|
@ -494,7 +494,7 @@ const memfd_create = fn(name: [&:0]const u8, flags: u32) usize {
|
|||||||
|
|
||||||
const unwrap_syscall = fn(syscall_result: usize) ?usize {
|
const unwrap_syscall = fn(syscall_result: usize) ?usize {
|
||||||
const signed_syscall_result: ssize = #cast(syscall_result);
|
const signed_syscall_result: ssize = #cast(syscall_result);
|
||||||
if (signed_syscall_result >= 0) {
|
if (std.os.unwrap_syscall_signed(signed_syscall_result)) {
|
||||||
return syscall_result;
|
return syscall_result;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,3 +1,56 @@
|
|||||||
|
const std = #import("std");
|
||||||
|
|
||||||
const FileDescriptor = s32;
|
const FileDescriptor = s32;
|
||||||
const write = fn (file_descriptor: FileDescriptor, bytes_ptr: [&]const u8, bytes_len: usize) ssize extern;
|
const ProcessId = s32;
|
||||||
const exit = fn (exit_code: u32) noreturn extern;
|
const MAP_FAILED = 0xffffffffffffffff;
|
||||||
|
|
||||||
|
const MapFlags = struct(u32){
|
||||||
|
shared: bool,
|
||||||
|
private: bool,
|
||||||
|
reserved: u2 = 0,
|
||||||
|
fixed: bool,
|
||||||
|
reserved0: bool = 0,
|
||||||
|
noreserve: bool,
|
||||||
|
reserved1: u2 = 0,
|
||||||
|
has_semaphore: bool,
|
||||||
|
no_cache: bool,
|
||||||
|
reserved2: u1 = 0,
|
||||||
|
anonymous: bool,
|
||||||
|
reserved3: u19 = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProtectionFlags = struct(u32) {
|
||||||
|
read: bool,
|
||||||
|
write: bool,
|
||||||
|
execute: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
const get_protection_flags = fn(flags: std.os.ProtectionFlags) ProtectionFlags {
|
||||||
|
return ProtectionFlags{
|
||||||
|
.read = flags.read,
|
||||||
|
.write = flags.write,
|
||||||
|
.execute = flags.execute,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const get_map_flags = fn(flags: std.os.MapFlags) MapFlags{
|
||||||
|
return MapFlags{
|
||||||
|
.shared = false,
|
||||||
|
.private = true,
|
||||||
|
.fixed = false,
|
||||||
|
.noreserve = false,
|
||||||
|
.has_semaphore = false,
|
||||||
|
.no_cache = false,
|
||||||
|
.anonymous = true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const write :: extern = fn (file_descriptor: FileDescriptor, bytes_ptr: [&]const u8, bytes_len: usize) ssize;
|
||||||
|
const exit :: extern = fn (exit_code: s32) noreturn;
|
||||||
|
const fork :: extern = fn () ProcessId;
|
||||||
|
const mmap :: extern = fn (address: ?[&]const u8, length: usize, protection_flags: ProtectionFlags, map_flags: MapFlags, file_descriptor: FileDescriptor, offset: u64) usize;
|
||||||
|
const munmap :: extern = fn (address: [&]const u8, length: usize) s32;
|
||||||
|
const execve :: extern = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) s32;
|
||||||
|
const realpath :: extern = fn(path: [&:0]const u8, resolved_path: [&:0]u8) [&:0]u8;
|
||||||
|
|
||||||
|
const _NSGetExecutablePath :: extern = fn (buffer: [&:0]u8, buffer_size: &u32) s32;
|
||||||
|
@ -2,7 +2,7 @@ const std = #import("std");
|
|||||||
const print = std.print;
|
const print = std.print;
|
||||||
|
|
||||||
const main = fn() s32 {
|
const main = fn() s32 {
|
||||||
var buffer: [std.os.max_path_byte_count + 1]u8 = undefined;
|
var buffer: [std.os.max_path_byte_count:0]u8 = undefined;
|
||||||
if (std.os.current_executable_path(buffer = buffer.&)) |bytes| {
|
if (std.os.current_executable_path(buffer = buffer.&)) |bytes| {
|
||||||
print(bytes);
|
print(bytes);
|
||||||
print(bytes = "\n");
|
print(bytes = "\n");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user