From 50a29f7c213d4a906839dfd625b6280663348781 Mon Sep 17 00:00:00 2001
From: Robin Voetter
Date: Mon, 26 Jul 2021 02:37:11 +0200
Subject: [PATCH 01/96] Add @select
@select(
comptime T: type,
pred: std.meta.Vector(len, bool),
a: std.meta.Vector(len, T),
b: std.meta.Vector(len, T)
) std.meta.Vector(len, T)
Constructs a vector from a & b, based on the values in the predicate vector. For indices where the predicate value is true, the corresponding
element from the a vector is selected, and otherwise from b.
---
doc/langref.html.in | 10 ++++
src/AstGen.zig | 10 ++++
src/BuiltinFn.zig | 8 +++
src/Sema.zig | 7 +++
src/Zir.zig | 13 ++++
src/stage1/all_types.hpp | 20 +++++++
src/stage1/astgen.cpp | 51 ++++++++++++++++
src/stage1/codegen.cpp | 10 ++++
src/stage1/ir.cpp | 124 ++++++++++++++++++++++++++++++++++++++-
src/stage1/ir_print.cpp | 32 ++++++++++
test/behavior.zig | 1 +
test/behavior/select.zig | 25 ++++++++
12 files changed, 309 insertions(+), 2 deletions(-)
create mode 100644 test/behavior/select.zig
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 9e98bb0114..a805f9a2ac 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -7125,6 +7125,7 @@ fn func(y: *i32) void {
an integer or an enum.
{#header_close#}
+
{#header_open|@bitCast#}
{#syntax#}@bitCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}
@@ -8177,6 +8178,15 @@ test "@wasmMemoryGrow" {
a calling function, the returned address will apply to the calling function.
{#header_close#}
+
+ {#header_open|@select#}
+ {#syntax#}@select(comptime T: type, pred: std.meta.Vector(len, bool), a: std.meta.Vector(len, T), b: std.meta.Vector(len, T)) std.meta.Vector(len, T){#endsyntax#}
+
+ Selects values element-wise from {#syntax#}a{#endsyntax#} or {#syntax#}b{#endsyntax#} based on {#syntax#}pred{#endsyntax#}. If {#syntax#}pred[i]{#endsyntax#} is {#syntax#}true{#endsyntax#}, the corresponding element in the result will be {#syntax#}a[i]{#endsyntax#} and otherwise {#syntax#}b[i]{#endsyntax#}.
+
+ {#see_also|SIMD|Vectors#}
+ {#header_close#}
+
{#header_open|@setAlignStack#}
{#syntax#}@setAlignStack(comptime alignment: u29){#endsyntax#}
diff --git a/src/AstGen.zig b/src/AstGen.zig
index a00b43288b..656b960c2f 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -2090,6 +2090,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
.splat,
.reduce,
.shuffle,
+ .select,
.atomic_load,
.atomic_rmw,
.atomic_store,
@@ -7375,6 +7376,15 @@ fn builtinCall(
});
return rvalue(gz, rl, result, node);
},
+ .select => {
+ const result = try gz.addPlNode(.select, node, Zir.Inst.Select{
+ .elem_type = try typeExpr(gz, scope, params[0]),
+ .pred = try expr(gz, scope, .none, params[1]),
+ .a = try expr(gz, scope, .none, params[2]),
+ .b = try expr(gz, scope, .none, params[3]),
+ });
+ return rvalue(gz, rl, result, node);
+ },
.async_call => {
const result = try gz.addPlNode(.builtin_async_call, node, Zir.Inst.AsyncCall{
.frame_buffer = try expr(gz, scope, .none, params[0]),
diff --git a/src/BuiltinFn.zig b/src/BuiltinFn.zig
index 3964512838..07371b3192 100644
--- a/src/BuiltinFn.zig
+++ b/src/BuiltinFn.zig
@@ -69,6 +69,7 @@ pub const Tag = enum {
ptr_to_int,
rem,
return_address,
+ select,
set_align_stack,
set_cold,
set_eval_branch_quota,
@@ -601,6 +602,13 @@ pub const list = list: {
.param_count = 0,
},
},
+ .{
+ "@select",
+ .{
+ .tag = .select,
+ .param_count = 4,
+ },
+ },
.{
"@setAlignStack",
.{
diff --git a/src/Sema.zig b/src/Sema.zig
index 3df512596f..6f8975d086 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -338,6 +338,7 @@ pub fn analyzeBody(
.splat => try sema.zirSplat(block, inst),
.reduce => try sema.zirReduce(block, inst),
.shuffle => try sema.zirShuffle(block, inst),
+ .select => try sema.zirSelect(block, inst),
.atomic_load => try sema.zirAtomicLoad(block, inst),
.atomic_rmw => try sema.zirAtomicRmw(block, inst),
.atomic_store => try sema.zirAtomicStore(block, inst),
@@ -6099,6 +6100,12 @@ fn zirShuffle(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
return sema.mod.fail(&block.base, src, "TODO: Sema.zirShuffle", .{});
}
+fn zirSelect(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+ const src = inst_data.src();
+ return sema.mod.fail(&block.base, src, "TODO: Sema.zirSelect", .{});
+}
+
fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
diff --git a/src/Zir.zig b/src/Zir.zig
index 00f66ef507..003b43d9e0 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -890,6 +890,9 @@ pub const Inst = struct {
/// Implements the `@shuffle` builtin.
/// Uses the `pl_node` union field with payload `Shuffle`.
shuffle,
+ /// Implements the `@select` builtin.
+ /// Uses the `pl_node` union field with payload `Select`.
+ select,
/// Implements the `@atomicLoad` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
atomic_load,
@@ -1181,6 +1184,7 @@ pub const Inst = struct {
.splat,
.reduce,
.shuffle,
+ .select,
.atomic_load,
.atomic_rmw,
.atomic_store,
@@ -1451,6 +1455,7 @@ pub const Inst = struct {
.splat = .pl_node,
.reduce = .pl_node,
.shuffle = .pl_node,
+ .select = .pl_node,
.atomic_load = .pl_node,
.atomic_rmw = .pl_node,
.atomic_store = .pl_node,
@@ -2725,6 +2730,13 @@ pub const Inst = struct {
mask: Ref,
};
+ pub const Select = struct {
+ elem_type: Ref,
+ pred: Ref,
+ a: Ref,
+ b: Ref,
+ };
+
pub const AsyncCall = struct {
frame_buffer: Ref,
result_ptr: Ref,
@@ -2935,6 +2947,7 @@ const Writer = struct {
.cmpxchg_strong,
.cmpxchg_weak,
.shuffle,
+ .select,
.atomic_rmw,
.atomic_store,
.mul_add,
diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp
index ee06c15cf0..b4b2740dec 100644
--- a/src/stage1/all_types.hpp
+++ b/src/stage1/all_types.hpp
@@ -1755,6 +1755,7 @@ enum BuiltinFnId {
BuiltinFnIdIntToEnum,
BuiltinFnIdVectorType,
BuiltinFnIdShuffle,
+ BuiltinFnIdSelect,
BuiltinFnIdSplat,
BuiltinFnIdSetCold,
BuiltinFnIdSetRuntimeSafety,
@@ -2544,6 +2545,7 @@ enum Stage1ZirInstId : uint8_t {
Stage1ZirInstIdBoolToInt,
Stage1ZirInstIdVectorType,
Stage1ZirInstIdShuffleVector,
+ Stage1ZirInstIdSelect,
Stage1ZirInstIdSplat,
Stage1ZirInstIdBoolNot,
Stage1ZirInstIdMemset,
@@ -2664,6 +2666,7 @@ enum Stage1AirInstId : uint8_t {
Stage1AirInstIdReduce,
Stage1AirInstIdTruncate,
Stage1AirInstIdShuffleVector,
+ Stage1AirInstIdSelect,
Stage1AirInstIdSplat,
Stage1AirInstIdBoolNot,
Stage1AirInstIdMemset,
@@ -4295,6 +4298,23 @@ struct Stage1AirInstShuffleVector {
Stage1AirInst *mask; // This is in zig-format, not llvm format
};
+struct Stage1ZirInstSelect {
+ Stage1ZirInst base;
+
+ Stage1ZirInst *scalar_type;
+ Stage1ZirInst *pred; // This is in zig-format, not llvm format
+ Stage1ZirInst *a;
+ Stage1ZirInst *b;
+};
+
+struct Stage1AirInstSelect {
+ Stage1AirInst base;
+
+ Stage1AirInst *pred; // This is in zig-format, not llvm format
+ Stage1AirInst *a;
+ Stage1AirInst *b;
+};
+
struct Stage1ZirInstSplat {
Stage1ZirInst base;
diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp
index cc8ccefad7..e8f68c82bb 100644
--- a/src/stage1/astgen.cpp
+++ b/src/stage1/astgen.cpp
@@ -196,6 +196,8 @@ void destroy_instruction_src(Stage1ZirInst *inst) {
return heap::c_allocator.destroy(reinterpret_cast(inst));
case Stage1ZirInstIdShuffleVector:
return heap::c_allocator.destroy(reinterpret_cast(inst));
+ case Stage1ZirInstIdSelect:
+ return heap::c_allocator.destroy(reinterpret_cast(inst));
case Stage1ZirInstIdSplat:
return heap::c_allocator.destroy(reinterpret_cast(inst));
case Stage1ZirInstIdBoolNot:
@@ -651,6 +653,10 @@ static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstShuffleVector *) {
return Stage1ZirInstIdShuffleVector;
}
+static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSelect *) {
+ return Stage1ZirInstIdSelect;
+}
+
static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSplat *) {
return Stage1ZirInstIdSplat;
}
@@ -2037,6 +2043,22 @@ static Stage1ZirInst *ir_build_shuffle_vector(Stage1AstGen *ag, Scope *scope, As
return &instruction->base;
}
+static Stage1ZirInst *ir_build_select(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
+ Stage1ZirInst *scalar_type, Stage1ZirInst *pred, Stage1ZirInst *a, Stage1ZirInst *b)
+{
+ Stage1ZirInstSelect *instruction = ir_build_instruction(ag, scope, source_node);
+ instruction->scalar_type = scalar_type;
+ instruction->pred = pred;
+ instruction->a = a;
+ instruction->b = b;
+
+ ir_ref_instruction(pred, ag->current_basic_block);
+ ir_ref_instruction(a, ag->current_basic_block);
+ ir_ref_instruction(b, ag->current_basic_block);
+
+ return &instruction->base;
+}
+
static Stage1ZirInst *ir_build_splat_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
Stage1ZirInst *len, Stage1ZirInst *scalar)
{
@@ -4619,6 +4641,35 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast
arg0_value, arg1_value, arg2_value, arg3_value);
return ir_lval_wrap(ag, scope, shuffle_vector, lval, result_loc);
}
+ case BuiltinFnIdSelect:
+ {
+ // Used for the type expr
+ Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope);
+
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
+ Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, comptime_scope);
+ if (arg0_value == ag->codegen->invalid_inst_src)
+ return arg0_value;
+
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
+ Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
+ if (arg0_value == ag->codegen->invalid_inst_src)
+ return arg1_value;
+
+ AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
+ Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
+ if (arg1_value == ag->codegen->invalid_inst_src)
+ return arg2_value;
+
+ AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
+ Stage1ZirInst *arg3_value = astgen_node(ag, arg3_node, scope);
+ if (arg2_value == ag->codegen->invalid_inst_src)
+ return arg3_value;
+
+ Stage1ZirInst *select = ir_build_select(ag, scope, node,
+ arg0_value, arg1_value, arg2_value, arg3_value);
+ return ir_lval_wrap(ag, scope, select, lval, result_loc);
+ }
case BuiltinFnIdSplat:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp
index 562327d500..fc2651c8f7 100644
--- a/src/stage1/codegen.cpp
+++ b/src/stage1/codegen.cpp
@@ -5162,6 +5162,13 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, Stage1Air *executable,
llvm_mask_value, "");
}
+static LLVMValueRef ir_render_select(CodeGen *g, Stage1Air *executable, Stage1AirInstSelect *instruction) {
+ LLVMValueRef pred = ir_llvm_value(g, instruction->pred);
+ LLVMValueRef a = ir_llvm_value(g, instruction->a);
+ LLVMValueRef b = ir_llvm_value(g, instruction->b);
+ return LLVMBuildSelect(g->builder, pred, a, b, "");
+}
+
static LLVMValueRef ir_render_splat(CodeGen *g, Stage1Air *executable, Stage1AirInstSplat *instruction) {
ZigType *result_type = instruction->base.value->type;
ir_assert(result_type->id == ZigTypeIdVector, &instruction->base);
@@ -7015,6 +7022,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, Stage1Air *executable, Sta
return ir_render_spill_end(g, executable, (Stage1AirInstSpillEnd *)instruction);
case Stage1AirInstIdShuffleVector:
return ir_render_shuffle_vector(g, executable, (Stage1AirInstShuffleVector *) instruction);
+ case Stage1AirInstIdSelect:
+ return ir_render_select(g, executable, (Stage1AirInstSelect *) instruction);
case Stage1AirInstIdSplat:
return ir_render_splat(g, executable, (Stage1AirInstSplat *) instruction);
case Stage1AirInstIdVectorExtractElem:
@@ -8920,6 +8929,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
+ create_builtin_fn(g, BuiltinFnIdSelect, "select", 4);
create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp
index a6d1ff3007..9a2e50fef7 100644
--- a/src/stage1/ir.cpp
+++ b/src/stage1/ir.cpp
@@ -355,6 +355,8 @@ void destroy_instruction_gen(Stage1AirInst *inst) {
return heap::c_allocator.destroy(reinterpret_cast(inst));
case Stage1AirInstIdShuffleVector:
return heap::c_allocator.destroy(reinterpret_cast(inst));
+ case Stage1AirInstIdSelect:
+ return heap::c_allocator.destroy(reinterpret_cast(inst));
case Stage1AirInstIdSplat:
return heap::c_allocator.destroy(reinterpret_cast(inst));
case Stage1AirInstIdBoolNot:
@@ -901,6 +903,10 @@ static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstShuffleVector *) {
return Stage1AirInstIdShuffleVector;
}
+static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSelect *) {
+ return Stage1AirInstIdSelect;
+}
+
static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSplat *) {
return Stage1AirInstIdSplat;
}
@@ -1756,6 +1762,22 @@ static Stage1AirInst *ir_build_shuffle_vector_gen(IrAnalyze *ira, Scope *scope,
return &inst->base;
}
+static Stage1AirInst *ir_build_select_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
+ ZigType *result_type, Stage1AirInst *pred, Stage1AirInst *a, Stage1AirInst *b)
+{
+ Stage1AirInstSelect *inst = ir_build_inst_gen(&ira->new_irb, scope, source_node);
+ inst->base.value->type = result_type;
+ inst->pred = pred;
+ inst->a = a;
+ inst->b = b;
+
+ ir_ref_inst_gen(pred);
+ ir_ref_inst_gen(a);
+ ir_ref_inst_gen(b);
+
+ return &inst->base;
+}
+
static Stage1AirInst *ir_build_splat_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_type,
Stage1AirInst *scalar)
{
@@ -20318,6 +20340,100 @@ static Stage1AirInst *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, Stag
return ir_analyze_shuffle_vector(ira, instruction->base.scope, instruction->base.source_node, scalar_type, a, b, mask);
}
+static Stage1AirInst *ir_analyze_instruction_select(IrAnalyze *ira, Stage1ZirInstSelect *instruction) {
+ Error err;
+
+ ZigType *scalar_type = ir_resolve_vector_elem_type(ira, instruction->scalar_type->child);
+ if (type_is_invalid(scalar_type))
+ return ira->codegen->invalid_inst_gen;
+
+ if ((err = ir_validate_vector_elem_type(ira, instruction->base.source_node, scalar_type)))
+ return ira->codegen->invalid_inst_gen;
+
+ Stage1AirInst *pred = instruction->pred->child;
+ if (type_is_invalid(pred->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ Stage1AirInst *a = instruction->a->child;
+ if (type_is_invalid(a->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ Stage1AirInst *b = instruction->b->child;
+ if (type_is_invalid(b->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ if (pred->value->type->id != ZigTypeIdVector) {
+ ir_add_error(ira, pred,
+ buf_sprintf("expected vector type, found '%s'",
+ buf_ptr(&pred->value->type->name)));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ uint32_t pred_len = pred->value->type->data.vector.len;
+ pred = ir_implicit_cast(ira, pred, get_vector_type(ira->codegen, pred_len,
+ ira->codegen->builtin_types.entry_bool));
+ if (type_is_invalid(pred->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ if (a->value->type->id != ZigTypeIdVector) {
+ ir_add_error(ira, a,
+ buf_sprintf("expected vector type, found '%s'",
+ buf_ptr(&a->value->type->name)));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ if (b->value->type->id != ZigTypeIdVector) {
+ ir_add_error(ira, b,
+ buf_sprintf("expected vector type, found '%s'",
+ buf_ptr(&b->value->type->name)));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigType *result_type = get_vector_type(ira->codegen, pred_len, scalar_type);
+
+ a = ir_implicit_cast(ira, a, result_type);
+ if (type_is_invalid(a->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ b = ir_implicit_cast(ira, b, result_type);
+ if (type_is_invalid(a->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ if (instr_is_comptime(pred) && instr_is_comptime(a) && instr_is_comptime(b)) {
+ ZigValue *pred_val = ir_resolve_const(ira, pred, UndefBad);
+ if (pred_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ ZigValue *a_val = ir_resolve_const(ira, a, UndefBad);
+ if (a_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ ZigValue *b_val = ir_resolve_const(ira, b, UndefBad);
+ if (b_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ expand_undef_array(ira->codegen, a_val);
+ expand_undef_array(ira->codegen, b_val);
+
+ Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, result_type);
+ result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(pred_len);
+
+ for (uint64_t i = 0; i < pred_len; i += 1) {
+ ZigValue *dst_elem_val = &result->value->data.x_array.data.s_none.elements[i];
+ ZigValue *pred_elem_val = &pred_val->data.x_array.data.s_none.elements[i];
+ ZigValue *a_elem_val = &a_val->data.x_array.data.s_none.elements[i];
+ ZigValue *b_elem_val = &b_val->data.x_array.data.s_none.elements[i];
+ ZigValue *result_elem_val = pred_elem_val->data.x_bool ? a_elem_val : b_elem_val;
+ copy_const_val(ira->codegen, dst_elem_val, result_elem_val);
+ }
+
+ result->value->special = ConstValSpecialStatic;
+ return result;
+ }
+
+ return ir_build_select_gen(ira, instruction->base.scope, instruction->base.source_node, result_type, pred, a, b);
+}
+
static Stage1AirInst *ir_analyze_instruction_splat(IrAnalyze *ira, Stage1ZirInstSplat *instruction) {
Error err;
@@ -24595,7 +24711,9 @@ static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst
return ir_analyze_instruction_vector_type(ira, (Stage1ZirInstVectorType *)instruction);
case Stage1ZirInstIdShuffleVector:
return ir_analyze_instruction_shuffle_vector(ira, (Stage1ZirInstShuffleVector *)instruction);
- case Stage1ZirInstIdSplat:
+ case Stage1ZirInstIdSelect:
+ return ir_analyze_instruction_select(ira, (Stage1ZirInstSelect *)instruction);
+ case Stage1ZirInstIdSplat:
return ir_analyze_instruction_splat(ira, (Stage1ZirInstSplat *)instruction);
case Stage1ZirInstIdBoolNot:
return ir_analyze_instruction_bool_not(ira, (Stage1ZirInstBoolNot *)instruction);
@@ -24931,6 +25049,7 @@ bool ir_inst_gen_has_side_effects(Stage1AirInst *instruction) {
case Stage1AirInstIdUnionTag:
case Stage1AirInstIdTruncate:
case Stage1AirInstIdShuffleVector:
+ case Stage1AirInstIdSelect:
case Stage1AirInstIdSplat:
case Stage1AirInstIdBoolNot:
case Stage1AirInstIdReturnAddress:
@@ -25084,6 +25203,7 @@ bool ir_inst_src_has_side_effects(Stage1ZirInst *instruction) {
case Stage1ZirInstIdTruncate:
case Stage1ZirInstIdVectorType:
case Stage1ZirInstIdShuffleVector:
+ case Stage1ZirInstIdSelect:
case Stage1ZirInstIdSplat:
case Stage1ZirInstIdBoolNot:
case Stage1ZirInstIdSlice:
@@ -25751,7 +25871,7 @@ static Error ir_resolve_lazy_recurse_array(AstNode *source_node, ZigValue *val,
static Error ir_resolve_lazy_recurse(AstNode *source_node, ZigValue *val) {
Error err;
- if ((err = ir_resolve_lazy_raw(source_node, val)))
+ if ((err = ir_resolve_lazy_raw(source_node, val)))
return err;
assert(val->special != ConstValSpecialRuntime);
assert(val->special != ConstValSpecialLazy);
diff --git a/src/stage1/ir_print.cpp b/src/stage1/ir_print.cpp
index bec9521bc2..e83da8565c 100644
--- a/src/stage1/ir_print.cpp
+++ b/src/stage1/ir_print.cpp
@@ -93,6 +93,8 @@ const char* ir_inst_src_type_str(Stage1ZirInstId id) {
return "SrcInvalid";
case Stage1ZirInstIdShuffleVector:
return "SrcShuffle";
+ case Stage1ZirInstIdSelect:
+ return "SrcSelect";
case Stage1ZirInstIdSplat:
return "SrcSplat";
case Stage1ZirInstIdDeclVar:
@@ -379,6 +381,8 @@ const char* ir_inst_gen_type_str(Stage1AirInstId id) {
return "GenInvalid";
case Stage1AirInstIdShuffleVector:
return "GenShuffle";
+ case Stage1AirInstIdSelect:
+ return "GenSelect";
case Stage1AirInstIdSplat:
return "GenSplat";
case Stage1AirInstIdDeclVar:
@@ -1722,6 +1726,28 @@ static void ir_print_shuffle_vector(IrPrintGen *irp, Stage1AirInstShuffleVector
fprintf(irp->f, ")");
}
+static void ir_print_select(IrPrintSrc *irp, Stage1ZirInstSelect *instruction) {
+ fprintf(irp->f, "@select(");
+ ir_print_other_inst_src(irp, instruction->scalar_type);
+ fprintf(irp->f, ", ");
+ ir_print_other_inst_src(irp, instruction->pred);
+ fprintf(irp->f, ", ");
+ ir_print_other_inst_src(irp, instruction->a);
+ fprintf(irp->f, ", ");
+ ir_print_other_inst_src(irp, instruction->b);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_select(IrPrintGen *irp, Stage1AirInstSelect *instruction) {
+ fprintf(irp->f, "@select(");
+ ir_print_other_inst_gen(irp, instruction->pred);
+ fprintf(irp->f, ", ");
+ ir_print_other_inst_gen(irp, instruction->a);
+ fprintf(irp->f, ", ");
+ ir_print_other_inst_gen(irp, instruction->b);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_splat_src(IrPrintSrc *irp, Stage1ZirInstSplat *instruction) {
fprintf(irp->f, "@splat(");
ir_print_other_inst_src(irp, instruction->len);
@@ -2836,6 +2862,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, Stage1ZirInst *instruction, bool
case Stage1ZirInstIdShuffleVector:
ir_print_shuffle_vector(irp, (Stage1ZirInstShuffleVector *)instruction);
break;
+ case Stage1ZirInstIdSelect:
+ ir_print_select(irp, (Stage1ZirInstSelect *)instruction);
+ break;
case Stage1ZirInstIdSplat:
ir_print_splat_src(irp, (Stage1ZirInstSplat *)instruction);
break;
@@ -3178,6 +3207,9 @@ static void ir_print_inst_gen(IrPrintGen *irp, Stage1AirInst *instruction, bool
case Stage1AirInstIdShuffleVector:
ir_print_shuffle_vector(irp, (Stage1AirInstShuffleVector *)instruction);
break;
+ case Stage1AirInstIdSelect:
+ ir_print_select(irp, (Stage1AirInstSelect *)instruction);
+ break;
case Stage1AirInstIdSplat:
ir_print_splat_gen(irp, (Stage1AirInstSplat *)instruction);
break;
diff --git a/test/behavior.zig b/test/behavior.zig
index 0055638335..8459e499d7 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -118,6 +118,7 @@ test {
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("behavior/reflection.zig");
_ = @import("behavior/shuffle.zig");
+ _ = @import("behavior/select.zig");
_ = @import("behavior/sizeof_and_typeof.zig");
_ = @import("behavior/slice.zig");
_ = @import("behavior/slice_sentinel_comptime.zig");
diff --git a/test/behavior/select.zig b/test/behavior/select.zig
new file mode 100644
index 0000000000..5c69094413
--- /dev/null
+++ b/test/behavior/select.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const mem = std.mem;
+const expect = std.testing.expect;
+const Vector = std.meta.Vector;
+
+test "@select" {
+ const S = struct {
+ fn doTheTest() !void {
+ var a: Vector(4, bool) = [4]bool{ true, false, true, false };
+ var b: Vector(4, i32) = [4]i32{ -1, 4, 999, -31 };
+ var c: Vector(4, i32) = [4]i32{ -5, 1, 0, 1234 };
+ var abc = @select(i32, a, b, c);
+ try expect(mem.eql(i32, &@as([4]i32, abc), &[4]i32{ -1, 1, 999, 1234 }));
+
+ var x: Vector(4, bool) = [4]bool{ false, false, false, true };
+ var y: Vector(4, f32) = [4]f32{ 0.001, 33.4, 836, -3381.233 };
+ var z: Vector(4, f32) = [4]f32{ 0.0, 312.1, -145.9, 9993.55 };
+ var xyz = @select(f32, x, y, z);
+ try expect(mem.eql(f32, &@as([4]f32, xyz), &[4]f32{ 0.0, 312.1, -145.9, -3381.233 }));
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
From cdeea3b0943b070d49d8d8d0855f9a38843e3ecc Mon Sep 17 00:00:00 2001
From: Robin Voetter
Date: Sun, 25 Jul 2021 05:34:11 +0200
Subject: [PATCH 02/96] minimum/maximum builtins
---
doc/langref.html.in | 22 ++++++
src/AstGen.zig | 21 ++++++
src/BuiltinFn.zig | 16 ++++
src/Sema.zig | 14 ++++
src/Zir.zig | 12 +++
src/stage1/all_types.hpp | 4 +
src/stage1/astgen.cpp | 30 ++++++++
src/stage1/bigfloat.cpp | 24 ++++++
src/stage1/bigfloat.hpp | 3 +
src/stage1/bigint.cpp | 20 +++++
src/stage1/bigint.hpp | 2 +
src/stage1/codegen.cpp | 26 +++++++
src/stage1/ir.cpp | 120 ++++++++++++++++++++++++++++++
src/stage1/ir_print.cpp | 4 +
src/zig_llvm.cpp | 30 ++++++++
src/zig_llvm.h | 9 +++
test/behavior.zig | 1 +
test/behavior/maximum_minimum.zig | 58 +++++++++++++++
18 files changed, 416 insertions(+)
create mode 100644 test/behavior/maximum_minimum.zig
diff --git a/doc/langref.html.in b/doc/langref.html.in
index a805f9a2ac..38b91468e2 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -7988,6 +7988,17 @@ test "@hasDecl" {
{#header_close#}
+ {#header_open|@maximum#}
+ {#syntax#}@maximum(a: T, b: T) T{#endsyntax#}
+
+ Returns the maximum value of {#syntax#}a{#endsyntax#} and {#syntax#}b{#endsyntax#}. This builtin accepts integers, floats, and vectors of either. In the latter case, the operation is performed element wise.
+
+
+ NaNs are handled as follows: if one of the operands of a (pairwise) operation is NaN, the other operand is returned. If both operands are NaN, NaN is returned.
+
+ {#see_also|@minimum|SIMD|Vectors#}
+ {#header_close#}
+
{#header_open|@memcpy#}
{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}
@@ -8025,6 +8036,17 @@ mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}
mem.set(u8, dest, c);{#endsyntax#}
{#header_close#}
+ {#header_open|@minimum#}
+
{#syntax#}@minimum(a: T, b: T) T{#endsyntax#}
+
+ Returns the minimum value of {#syntax#}a{#endsyntax#} and {#syntax#}b{#endsyntax#}. This builtin accepts integers, floats, and vectors of either. In the latter case, the operation is performed element wise.
+
+
+ NaNs are handled as follows: if one of the operands of a (pairwise) operation is NaN, the other operand is returned. If both operands are NaN, NaN is returned.
+
+ {#see_also|@maximum|SIMD|Vectors#}
+ {#header_close#}
+
{#header_open|@wasmMemorySize#}
{#syntax#}@wasmMemorySize(index: u32) u32{#endsyntax#}
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 656b960c2f..34f906fab1 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -2098,8 +2098,10 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
.builtin_call,
.field_ptr_type,
.field_parent_ptr,
+ .maximum,
.memcpy,
.memset,
+ .minimum,
.builtin_async_call,
.c_import,
.@"resume",
@@ -7227,6 +7229,25 @@ fn builtinCall(
return rvalue(gz, rl, result, node);
},
+ .maximum => {
+ const a = try expr(gz, scope, .none, params[0]);
+ const b = try expr(gz, scope, .none, params[1]);
+ const result = try gz.addPlNode(.maximum, node, Zir.Inst.Bin{
+ .lhs = a,
+ .rhs = b,
+ });
+ return rvalue(gz, rl, result, node);
+ },
+ .minimum => {
+ const a = try expr(gz, scope, .none, params[0]);
+ const b = try expr(gz, scope, .none, params[1]);
+ const result = try gz.addPlNode(.minimum, node, Zir.Inst.Bin{
+ .lhs = a,
+ .rhs = b,
+ });
+ return rvalue(gz, rl, result, node);
+ },
+
.add_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .add_with_overflow),
.sub_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .sub_with_overflow),
.mul_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .mul_with_overflow),
diff --git a/src/BuiltinFn.zig b/src/BuiltinFn.zig
index 07371b3192..8f23ec86d7 100644
--- a/src/BuiltinFn.zig
+++ b/src/BuiltinFn.zig
@@ -57,8 +57,10 @@ pub const Tag = enum {
int_to_error,
int_to_float,
int_to_ptr,
+ maximum,
memcpy,
memset,
+ minimum,
wasm_memory_size,
wasm_memory_grow,
mod,
@@ -518,6 +520,13 @@ pub const list = list: {
.param_count = 2,
},
},
+ .{
+ "@maximum",
+ .{
+ .tag = .maximum,
+ .param_count = 2,
+ },
+ },
.{
"@memcpy",
.{
@@ -532,6 +541,13 @@ pub const list = list: {
.param_count = 3,
},
},
+ .{
+ "@minimum",
+ .{
+ .tag = .minimum,
+ .param_count = 2,
+ },
+ },
.{
"@wasmMemorySize",
.{
diff --git a/src/Sema.zig b/src/Sema.zig
index 6f8975d086..67cfc09b53 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -346,8 +346,10 @@ pub fn analyzeBody(
.builtin_call => try sema.zirBuiltinCall(block, inst),
.field_ptr_type => try sema.zirFieldPtrType(block, inst),
.field_parent_ptr => try sema.zirFieldParentPtr(block, inst),
+ .maximum => try sema.zirMaximum(block, inst),
.memcpy => try sema.zirMemcpy(block, inst),
.memset => try sema.zirMemset(block, inst),
+ .minimum => try sema.zirMinimum(block, inst),
.builtin_async_call => try sema.zirBuiltinAsyncCall(block, inst),
.@"resume" => try sema.zirResume(block, inst),
.@"await" => try sema.zirAwait(block, inst, false),
@@ -6148,6 +6150,12 @@ fn zirFieldParentPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Com
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldParentPtr", .{});
}
+fn zirMaximum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+ const src = inst_data.src();
+ return sema.mod.fail(&block.base, src, "TODO: Sema.zirMaximum", .{});
+}
+
fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
@@ -6160,6 +6168,12 @@ fn zirMemset(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro
return sema.mod.fail(&block.base, src, "TODO: Sema.zirMemset", .{});
}
+fn zirMinimum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+ const src = inst_data.src();
+ return sema.mod.fail(&block.base, src, "TODO: Sema.zirMinimum", .{});
+}
+
fn zirBuiltinAsyncCall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
diff --git a/src/Zir.zig b/src/Zir.zig
index 003b43d9e0..2b88a3415d 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -915,12 +915,18 @@ pub const Inst = struct {
/// Implements the `@fieldParentPtr` builtin.
/// Uses the `pl_node` union field with payload `FieldParentPtr`.
field_parent_ptr,
+ /// Implements the `@maximum` builtin.
+ /// Uses the `pl_node` union field with payload `Bin`
+ maximum,
/// Implements the `@memcpy` builtin.
/// Uses the `pl_node` union field with payload `Memcpy`.
memcpy,
/// Implements the `@memset` builtin.
/// Uses the `pl_node` union field with payload `Memset`.
memset,
+ /// Implements the `@minimum` builtin.
+ /// Uses the `pl_node` union field with payload `Bin`
+ minimum,
/// Implements the `@asyncCall` builtin.
/// Uses the `pl_node` union field with payload `AsyncCall`.
builtin_async_call,
@@ -1192,8 +1198,10 @@ pub const Inst = struct {
.builtin_call,
.field_ptr_type,
.field_parent_ptr,
+ .maximum,
.memcpy,
.memset,
+ .minimum,
.builtin_async_call,
.c_import,
.@"resume",
@@ -1463,8 +1471,10 @@ pub const Inst = struct {
.builtin_call = .pl_node,
.field_ptr_type = .bin,
.field_parent_ptr = .pl_node,
+ .maximum = .pl_node,
.memcpy = .pl_node,
.memset = .pl_node,
+ .minimum = .pl_node,
.builtin_async_call = .pl_node,
.c_import = .pl_node,
@@ -3020,6 +3030,8 @@ const Writer = struct {
.bitcast,
.bitcast_result_ptr,
.vector_type,
+ .maximum,
+ .minimum,
=> try self.writePlNodeBin(stream, inst),
.@"export" => try self.writePlNodeExport(stream, inst),
diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp
index b4b2740dec..a72faa15ce 100644
--- a/src/stage1/all_types.hpp
+++ b/src/stage1/all_types.hpp
@@ -1796,6 +1796,8 @@ enum BuiltinFnId {
BuiltinFnIdWasmMemoryGrow,
BuiltinFnIdSrc,
BuiltinFnIdReduce,
+ BuiltinFnIdMaximum,
+ BuiltinFnIdMinimum,
};
struct BuiltinFnEntry {
@@ -2938,6 +2940,8 @@ enum IrBinOp {
IrBinOpRemMod,
IrBinOpArrayCat,
IrBinOpArrayMult,
+ IrBinOpMaximum,
+ IrBinOpMinimum,
};
struct Stage1ZirInstBinOp {
diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp
index e8f68c82bb..a5afe32d8b 100644
--- a/src/stage1/astgen.cpp
+++ b/src/stage1/astgen.cpp
@@ -4686,6 +4686,21 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast
arg0_value, arg1_value);
return ir_lval_wrap(ag, scope, splat, lval, result_loc);
}
+ case BuiltinFnIdMaximum:
+ {
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
+ Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
+ if (arg0_value == ag->codegen->invalid_inst_src)
+ return arg0_value;
+
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
+ Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
+ if (arg1_value == ag->codegen->invalid_inst_src)
+ return arg1_value;
+
+ Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpMaximum, arg0_value, arg1_value, true);
+ return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
+ }
case BuiltinFnIdMemcpy:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -4726,6 +4741,21 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast
Stage1ZirInst *ir_memset = ir_build_memset_src(ag, scope, node, arg0_value, arg1_value, arg2_value);
return ir_lval_wrap(ag, scope, ir_memset, lval, result_loc);
}
+ case BuiltinFnIdMinimum:
+ {
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
+ Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
+ if (arg0_value == ag->codegen->invalid_inst_src)
+ return arg0_value;
+
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
+ Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
+ if (arg1_value == ag->codegen->invalid_inst_src)
+ return arg1_value;
+
+ Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpMinimum, arg0_value, arg1_value, true);
+ return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
+ }
case BuiltinFnIdWasmMemorySize:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
diff --git a/src/stage1/bigfloat.cpp b/src/stage1/bigfloat.cpp
index 56bf2637e3..e5f21e34ea 100644
--- a/src/stage1/bigfloat.cpp
+++ b/src/stage1/bigfloat.cpp
@@ -191,6 +191,30 @@ void bigfloat_sqrt(BigFloat *dest, const BigFloat *op) {
f128M_sqrt(&op->value, &dest->value);
}
+void bigfloat_min(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
+ if (bigfloat_is_nan(op1)) {
+ bigfloat_init_bigfloat(dest, op2);
+ } else if (bigfloat_is_nan(op2)) {
+ bigfloat_init_bigfloat(dest, op1);
+ } else if (f128M_lt(&op1->value, &op2->value)) {
+ bigfloat_init_bigfloat(dest, op1);
+ } else {
+ bigfloat_init_bigfloat(dest, op2);
+ }
+}
+
+void bigfloat_max(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
+ if (bigfloat_is_nan(op1)) {
+ bigfloat_init_bigfloat(dest, op2);
+ } else if (bigfloat_is_nan(op2)) {
+ bigfloat_init_bigfloat(dest, op1);
+ } else if (f128M_lt(&op1->value, &op2->value)) {
+ bigfloat_init_bigfloat(dest, op2);
+ } else {
+ bigfloat_init_bigfloat(dest, op1);
+ }
+}
+
bool bigfloat_is_nan(const BigFloat *op) {
return f128M_isSignalingNaN(&op->value);
}
diff --git a/src/stage1/bigfloat.hpp b/src/stage1/bigfloat.hpp
index 52e92d20f4..ffaff320e9 100644
--- a/src/stage1/bigfloat.hpp
+++ b/src/stage1/bigfloat.hpp
@@ -45,9 +45,12 @@ void bigfloat_div_floor(BigFloat *dest, const BigFloat *op1, const BigFloat *op2
void bigfloat_rem(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
void bigfloat_sqrt(BigFloat *dest, const BigFloat *op);
+void bigfloat_min(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
+void bigfloat_max(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
void bigfloat_append_buf(Buf *buf, const BigFloat *op);
Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2);
+
bool bigfloat_is_nan(const BigFloat *op);
// convenience functions
diff --git a/src/stage1/bigint.cpp b/src/stage1/bigint.cpp
index 3ab6d08d79..5c8efad698 100644
--- a/src/stage1/bigint.cpp
+++ b/src/stage1/bigint.cpp
@@ -448,6 +448,26 @@ bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
}
#endif
+void bigint_max(BigInt* dest, const BigInt *op1, const BigInt *op2) {
+ switch (bigint_cmp(op1, op2)) {
+ case CmpEQ:
+ case CmpLT:
+ return bigint_init_bigint(dest, op2);
+ case CmpGT:
+ return bigint_init_bigint(dest, op1);
+ }
+}
+
+void bigint_min(BigInt* dest, const BigInt *op1, const BigInt *op2) {
+ switch (bigint_cmp(op1, op2)) {
+ case CmpEQ:
+ case CmpLT:
+ return bigint_init_bigint(dest, op1);
+ case CmpGT:
+ return bigint_init_bigint(dest, op2);
+ }
+}
+
void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) {
if (op1->digit_count == 0) {
return bigint_init_bigint(dest, op2);
diff --git a/src/stage1/bigint.hpp b/src/stage1/bigint.hpp
index 67f3ca1368..53e07f9284 100644
--- a/src/stage1/bigint.hpp
+++ b/src/stage1/bigint.hpp
@@ -56,6 +56,8 @@ bool bigint_fits_in_bits(const BigInt *bn, size_t bit_count, bool is_signed);
void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bit_count, bool is_big_endian);
void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_count, bool is_big_endian,
bool is_signed);
+void bigint_max(BigInt* dest, const BigInt *op1, const BigInt *op2);
+void bigint_min(BigInt* dest, const BigInt *op1, const BigInt *op2);
void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2);
void bigint_add_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
void bigint_sub(BigInt *dest, const BigInt *op1, const BigInt *op2);
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp
index fc2651c8f7..d1bea6990a 100644
--- a/src/stage1/codegen.cpp
+++ b/src/stage1/codegen.cpp
@@ -3248,6 +3248,30 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable,
case IrBinOpRemMod:
return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
op1_value, op2_value, operand_type, RemKindMod);
+ case IrBinOpMaximum:
+ if (scalar_type->id == ZigTypeIdFloat) {
+ return ZigLLVMBuildMaxNum(g->builder, op1_value, op2_value, "");
+ } else if (scalar_type->id == ZigTypeIdInt) {
+ if (scalar_type->data.integral.is_signed) {
+ return ZigLLVMBuildSMax(g->builder, op1_value, op2_value, "");
+ } else {
+ return ZigLLVMBuildUMax(g->builder, op1_value, op2_value, "");
+ }
+ } else {
+ zig_unreachable();
+ }
+ case IrBinOpMinimum:
+ if (scalar_type->id == ZigTypeIdFloat) {
+ return ZigLLVMBuildMinNum(g->builder, op1_value, op2_value, "");
+ } else if (scalar_type->id == ZigTypeIdInt) {
+ if (scalar_type->data.integral.is_signed) {
+ return ZigLLVMBuildSMin(g->builder, op1_value, op2_value, "");
+ } else {
+ return ZigLLVMBuildUMin(g->builder, op1_value, op2_value, "");
+ }
+ } else {
+ zig_unreachable();
+ }
}
zig_unreachable();
}
@@ -8990,6 +9014,8 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 2);
create_builtin_fn(g, BuiltinFnIdSrc, "src", 0);
create_builtin_fn(g, BuiltinFnIdReduce, "reduce", 2);
+ create_builtin_fn(g, BuiltinFnIdMaximum, "maximum", 2);
+ create_builtin_fn(g, BuiltinFnIdMinimum, "minimum", 2);
}
static const char *bool_to_str(bool b) {
diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp
index 9a2e50fef7..e9bb7b1d15 100644
--- a/src/stage1/ir.cpp
+++ b/src/stage1/ir.cpp
@@ -3311,6 +3311,108 @@ static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
}
}
+static void float_max(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
+ assert(op1->type == op2->type);
+ out_val->type = op1->type;
+ if (op1->type->id == ZigTypeIdComptimeFloat) {
+ bigfloat_max(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
+ } else if (op1->type->id == ZigTypeIdFloat) {
+ switch (op1->type->data.floating.bit_count) {
+ case 16:
+ if (zig_f16_isNaN(op1->data.x_f16)) {
+ out_val->data.x_f16 = op2->data.x_f16;
+ } else if (zig_f16_isNaN(op2->data.x_f16)) {
+ out_val->data.x_f16 = op1->data.x_f16;
+ } else {
+ out_val->data.x_f16 = f16_lt(op1->data.x_f16, op2->data.x_f16) ? op2->data.x_f16 : op1->data.x_f16;
+ }
+ return;
+ case 32:
+ if (op1->data.x_f32 != op1->data.x_f32) {
+ out_val->data.x_f32 = op2->data.x_f32;
+ } else if (op2->data.x_f32 != op2->data.x_f32) {
+ out_val->data.x_f32 = op1->data.x_f32;
+ } else {
+ out_val->data.x_f32 = op1->data.x_f32 > op2->data.x_f32 ? op1->data.x_f32 : op2->data.x_f32;
+ }
+ return;
+ case 64:
+ if (op1->data.x_f64 != op1->data.x_f64) {
+ out_val->data.x_f64 = op2->data.x_f64;
+ } else if (op2->data.x_f64 != op2->data.x_f64) {
+ out_val->data.x_f64 = op1->data.x_f64;
+ } else {
+ out_val->data.x_f64 = op1->data.x_f64 > op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;
+ }
+ return;
+ case 128:
+ if (zig_f128_isNaN(&op1->data.x_f128)) {
+ out_val->data.x_f128 = op2->data.x_f128;
+ } else if (zig_f128_isNaN(&op2->data.x_f128)) {
+ out_val->data.x_f128 = op1->data.x_f128;
+ } else {
+ out_val->data.x_f128 = f128M_lt(&op1->data.x_f128, &op2->data.x_f128) ? op2->data.x_f128 : op1->data.x_f128;
+ }
+ return;
+ default:
+ zig_unreachable();
+ }
+ } else {
+ zig_unreachable();
+ }
+}
+
+static void float_min(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
+ assert(op1->type == op2->type);
+ out_val->type = op1->type;
+ if (op1->type->id == ZigTypeIdComptimeFloat) {
+ bigfloat_min(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
+ } else if (op1->type->id == ZigTypeIdFloat) {
+ switch (op1->type->data.floating.bit_count) {
+ case 16:
+ if (zig_f16_isNaN(op1->data.x_f16)) {
+ out_val->data.x_f16 = op2->data.x_f16;
+ } else if (zig_f16_isNaN(op2->data.x_f16)) {
+ out_val->data.x_f16 = op1->data.x_f16;
+ } else {
+ out_val->data.x_f16 = f16_lt(op1->data.x_f16, op2->data.x_f16) ? op1->data.x_f16 : op2->data.x_f16;
+ }
+ return;
+ case 32:
+ if (op1->data.x_f32 != op1->data.x_f32) {
+ out_val->data.x_f32 = op2->data.x_f32;
+ } else if (op2->data.x_f32 != op2->data.x_f32) {
+ out_val->data.x_f32 = op1->data.x_f32;
+ } else {
+ out_val->data.x_f32 = op1->data.x_f32 < op2->data.x_f32 ? op1->data.x_f32 : op2->data.x_f32;
+ }
+ return;
+ case 64:
+ if (op1->data.x_f64 != op1->data.x_f64) {
+ out_val->data.x_f64 = op2->data.x_f64;
+ } else if (op2->data.x_f64 != op2->data.x_f64) {
+ out_val->data.x_f64 = op1->data.x_f64;
+ } else {
+ out_val->data.x_f64 = op1->data.x_f32 < op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;
+ }
+ return;
+ case 128:
+ if (zig_f128_isNaN(&op1->data.x_f128)) {
+ out_val->data.x_f128 = op2->data.x_f128;
+ } else if (zig_f128_isNaN(&op2->data.x_f128)) {
+ out_val->data.x_f128 = op1->data.x_f128;
+ } else {
+ out_val->data.x_f128 = f128M_lt(&op1->data.x_f128, &op2->data.x_f128) ? op1->data.x_f128 : op2->data.x_f128;
+ }
+ return;
+ default:
+ zig_unreachable();
+ }
+ } else {
+ zig_unreachable();
+ }
+}
+
static void float_negate(ZigValue *out_val, ZigValue *op) {
out_val->type = op->type;
if (op->type->id == ZigTypeIdComptimeFloat) {
@@ -9704,6 +9806,20 @@ static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, Scope *scope, AstNode *s
float_mod(out_val, op1_val, op2_val);
}
break;
+ case IrBinOpMaximum:
+ if (is_int) {
+ bigint_max(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
+ } else {
+ float_max(out_val, op1_val, op2_val);
+ }
+ break;
+ case IrBinOpMinimum:
+ if (is_int) {
+ bigint_min(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
+ } else {
+ float_min(out_val, op1_val, op2_val);
+ }
+ break;
}
if (type_entry->id == ZigTypeIdInt) {
@@ -9904,6 +10020,8 @@ static bool ok_float_op(IrBinOp op) {
case IrBinOpRemRem:
case IrBinOpRemMod:
case IrBinOpRemUnspecified:
+ case IrBinOpMaximum:
+ case IrBinOpMinimum:
return true;
case IrBinOpBoolOr:
@@ -10894,6 +11012,8 @@ static Stage1AirInst *ir_analyze_instruction_bin_op(IrAnalyze *ira, Stage1ZirIns
case IrBinOpRemUnspecified:
case IrBinOpRemRem:
case IrBinOpRemMod:
+ case IrBinOpMaximum:
+ case IrBinOpMinimum:
return ir_analyze_bin_op_math(ira, bin_op_instruction);
case IrBinOpArrayCat:
return ir_analyze_array_cat(ira, bin_op_instruction);
diff --git a/src/stage1/ir_print.cpp b/src/stage1/ir_print.cpp
index e83da8565c..96e924b768 100644
--- a/src/stage1/ir_print.cpp
+++ b/src/stage1/ir_print.cpp
@@ -733,6 +733,10 @@ static const char *ir_bin_op_id_str(IrBinOp op_id) {
return "++";
case IrBinOpArrayMult:
return "**";
+ case IrBinOpMaximum:
+ return "@maximum";
+ case IrBinOpMinimum:
+ return "@minimum";
}
zig_unreachable();
}
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
index d5d6f9f670..d0bc24ed1b 100644
--- a/src/zig_llvm.cpp
+++ b/src/zig_llvm.cpp
@@ -458,6 +458,36 @@ LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef
return wrap(call_inst);
}
+LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
+ CallInst *call_inst = unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS), name);
+ return wrap(call_inst);
+}
+
+LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
+ CallInst *call_inst = unwrap(B)->CreateMinNum(unwrap(LHS), unwrap(RHS), name);
+ return wrap(call_inst);
+}
+
+LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
+ CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umax, unwrap(LHS), unwrap(RHS), nullptr, name);
+ return wrap(call_inst);
+}
+
+LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
+ CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umin, unwrap(LHS), unwrap(RHS), nullptr, name);
+ return wrap(call_inst);
+}
+
+LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
+ CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smax, unwrap(LHS), unwrap(RHS), nullptr, name);
+ return wrap(call_inst);
+}
+
+LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
+ CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smin, unwrap(LHS), unwrap(RHS), nullptr, name);
+ return wrap(call_inst);
+}
+
void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram) {
assert( isa(unwrap(fn)) );
Function *unwrapped_function = reinterpret_cast(unwrap(fn));
diff --git a/src/zig_llvm.h b/src/zig_llvm.h
index a771491138..f49c2662c6 100644
--- a/src/zig_llvm.h
+++ b/src/zig_llvm.h
@@ -129,6 +129,14 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst,
ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size,
unsigned Align, bool isVolatile);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
+
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
+
ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp,
LLVMValueRef new_val, LLVMAtomicOrdering success_ordering,
LLVMAtomicOrdering failure_ordering, bool is_weak);
@@ -142,6 +150,7 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLShrExact(LLVMBuilderRef builder, LLVMValu
ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
const char *name);
+
ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugPointerType(struct ZigLLVMDIBuilder *dibuilder,
struct ZigLLVMDIType *pointee_type, uint64_t size_in_bits, uint64_t align_in_bits, const char *name);
diff --git a/test/behavior.zig b/test/behavior.zig
index 8459e499d7..101ee2ce53 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -105,6 +105,7 @@ test {
_ = @import("behavior/inttoptr.zig");
_ = @import("behavior/ir_block_deps.zig");
_ = @import("behavior/math.zig");
+ _ = @import("behavior/maximum_minimum.zig");
_ = @import("behavior/merge_error_sets.zig");
_ = @import("behavior/misc.zig");
_ = @import("behavior/muladd.zig");
diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig
new file mode 100644
index 0000000000..5fef818f2b
--- /dev/null
+++ b/test/behavior/maximum_minimum.zig
@@ -0,0 +1,58 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const mem = std.mem;
+const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
+const Vector = std.meta.Vector;
+
+test "@maximum" {
+ const S = struct {
+ fn doTheTest() !void {
+ try expectEqual(@as(i32, 10), @maximum(@as(i32, -3), @as(i32, 10)));
+ try expectEqual(@as(f32, 3.2), @maximum(@as(f32, 3.2), @as(f32, 0.68)));
+
+ var a: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
+ var b: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
+ var x = @maximum(a, b);
+ try expect(mem.eql(i32, &@as([4]i32, x), &[4]i32{ 2147483647, 2147483647, 30, 40 }));
+
+ var c: Vector(4, f32) = [4]f32{ 0, 0.4, -2.4, 7.8 };
+ var d: Vector(4, f32) = [4]f32{ -0.23, 0.42, -0.64, 0.9 };
+ var y = @maximum(c, d);
+ try expect(mem.eql(f32, &@as([4]f32, y), &[4]f32{ 0, 0.42, -0.64, 7.8 }));
+
+ var e: Vector(2, f32) = [2]f32{ 0, std.math.qnan_f32 };
+ var f: Vector(2, f32) = [2]f32{ std.math.qnan_f32, 0 };
+ var z = @maximum(e, f);
+ try expect(mem.eql(f32, &@as([2]f32, z), &[2]f32{ 0, 0 }));
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "@minimum" {
+ const S = struct {
+ fn doTheTest() !void {
+ try expectEqual(@as(i32, -3), @minimum(@as(i32, -3), @as(i32, 10)));
+ try expectEqual(@as(f32, 0.68), @minimum(@as(f32, 3.2), @as(f32, 0.68)));
+
+ var a: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
+ var b: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
+ var x = @minimum(a, b);
+ try expect(mem.eql(i32, &@as([4]i32, x), &[4]i32{ 1, -2, 3, 4 }));
+
+ var c: Vector(4, f32) = [4]f32{ 0, 0.4, -2.4, 7.8 };
+ var d: Vector(4, f32) = [4]f32{ -0.23, 0.42, -0.64, 0.9 };
+ var y = @minimum(c, d);
+ try expect(mem.eql(f32, &@as([4]f32, y), &[4]f32{ -0.23, 0.4, -2.4, 0.9 }));
+
+ var e: Vector(2, f32) = [2]f32{ 0, std.math.qnan_f32 };
+ var f: Vector(2, f32) = [2]f32{ std.math.qnan_f32, 0 };
+ var z = @maximum(e, f);
+ try expect(mem.eql(f32, &@as([2]f32, z), &[2]f32{ 0, 0 }));
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
From 31a59c229cb39b9ffd1ee3397a1ce87c36b91477 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 26 Jul 2021 19:12:34 -0700
Subject: [PATCH 03/96] stage2: improvements towards `zig test`
* Add AIR instruction: struct_field_val
- This is part of an effort to eliminate the AIR instruction `ref`.
- It's implemented for C backend and LLVM backend so far.
* Rename `resolvePossiblyUndefinedValue` to `resolveMaybeUndefVal` just
to save some columns on long lines.
* Sema: add `fieldVal` alongside `fieldPtr` (renamed from
`namedFieldPtr`). This is part of an effort to eliminate the AIR
instruction `ref`. The idea is to avoid unnecessary loads, stores,
stack usage, and IR instructions, by paying a DRY cost.
LLVM backend improvements:
* internal linkage vs exported linkage is implemented, along with
aliases. There is an issue with incremental updates due to missing
LLVM API for deleting aliases; see the relevant comment in this commit.
- `updateDeclExports` is hooked up to the LLVM backend now.
* Fix usage of `Type.tag() == .noreturn` rather than calling `isNoReturn()`.
* Properly mark global variables as mutable/constant.
* Fix llvm type generation of function pointers
* Fix codegen for calls of function pointers
* Implement llvm type generation of error unions and error sets.
* Implement AIR instructions: addwrap, subwrap, mul, mulwrap, div,
bit_and, bool_and, bit_or, bool_or, xor, struct_field_ptr,
struct_field_val, unwrap_errunion_err, add for floats, sub for
floats.
After this commit, `zig test` on a file with `test "example" {}`
correctly generates and executes a test binary. However the
`test_functions` slice is undefined and just happens to be going into
the .bss section, causing the length to be 0. The next step towards
`zig test` will be replacing the `test_functions` Decl Value with the
set of test function pointers, before it is sent to linker/codegen.
---
src/Air.zig | 7 +-
src/Liveness.zig | 4 +-
src/Module.zig | 4 +-
src/Sema.zig | 386 ++++++++++++++++++++++++++++------
src/codegen.zig | 9 +
src/codegen/c.zig | 25 ++-
src/codegen/llvm.zig | 362 ++++++++++++++++++++++++-------
src/codegen/llvm/bindings.zig | 133 +++++++++++-
src/codegen/wasm.zig | 2 +-
src/link/Coff.zig | 14 +-
src/link/Elf.zig | 7 +-
src/link/MachO.zig | 6 +
src/link/Wasm.zig | 10 +-
src/print_air.zig | 7 +-
14 files changed, 808 insertions(+), 168 deletions(-)
diff --git a/src/Air.zig b/src/Air.zig
index 9451f8b763..8cb7b943e3 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -247,6 +247,9 @@ pub const Inst = struct {
/// Given a pointer to a struct and a field index, returns a pointer to the field.
/// Uses the `ty_pl` field, payload is `StructField`.
struct_field_ptr,
+ /// Given a byval struct and a field index, returns the field byval.
+ /// Uses the `ty_pl` field, payload is `StructField`.
+ struct_field_val,
/// Given a slice value, return the length.
/// Result type is always usize.
/// Uses the `ty_op` field.
@@ -376,7 +379,8 @@ pub const SwitchBr = struct {
};
pub const StructField = struct {
- struct_ptr: Inst.Ref,
+ /// Whether this is a pointer or byval is determined by the AIR tag.
+ struct_operand: Inst.Ref,
field_index: u32,
};
@@ -448,6 +452,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.constant,
.varptr,
.struct_field_ptr,
+ .struct_field_val,
=> return air.getRefType(datas[inst].ty_pl.ty),
.not,
diff --git a/src/Liveness.zig b/src/Liveness.zig
index c6617e9b29..a4c6d8c016 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -320,9 +320,9 @@ fn analyzeInst(
}
return extra_tombs.finish();
},
- .struct_field_ptr => {
+ .struct_field_ptr, .struct_field_val => {
const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data;
- return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_ptr, .none, .none });
+ return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_operand, .none, .none });
},
.br => {
const br = inst_datas[inst].br;
diff --git a/src/Module.zig b/src/Module.zig
index 8ebb1c203c..99f314c5cb 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -3702,8 +3702,8 @@ pub fn analyzeExport(
else => return mod.fail(scope, src, "unable to export type '{}'", .{exported_decl.ty}),
}
- try mod.decl_exports.ensureCapacity(mod.gpa, mod.decl_exports.count() + 1);
- try mod.export_owners.ensureCapacity(mod.gpa, mod.export_owners.count() + 1);
+ try mod.decl_exports.ensureUnusedCapacity(mod.gpa, 1);
+ try mod.export_owners.ensureUnusedCapacity(mod.gpa, 1);
const new_export = try mod.gpa.create(Export);
errdefer mod.gpa.destroy(new_export);
diff --git a/src/Sema.zig b/src/Sema.zig
index 67cfc09b53..46a41426c8 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -655,7 +655,7 @@ fn resolveDefinedValue(
src: LazySrcLoc,
air_ref: Air.Inst.Ref,
) CompileError!?Value {
- if (try sema.resolvePossiblyUndefinedValue(block, src, air_ref)) |val| {
+ if (try sema.resolveMaybeUndefVal(block, src, air_ref)) |val| {
if (val.isUndef()) {
return sema.failWithUseOfUndef(block, src);
}
@@ -664,7 +664,7 @@ fn resolveDefinedValue(
return null;
}
-fn resolvePossiblyUndefinedValue(
+fn resolveMaybeUndefVal(
sema: *Sema,
block: *Scope.Block,
src: LazySrcLoc,
@@ -1293,7 +1293,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
};
return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
}
- const result_ptr = try sema.namedFieldPtr(block, src, array_ptr, "len", src);
+ const result_ptr = try sema.fieldPtr(block, src, array_ptr, "len", src);
const result_ptr_src = array_ptr_src;
return sema.analyzeLoad(block, src, result_ptr, result_ptr_src);
}
@@ -1789,7 +1789,7 @@ fn zirCompileLog(
const arg = sema.resolveInst(arg_ref);
const arg_ty = sema.typeOf(arg);
- if (try sema.resolvePossiblyUndefinedValue(block, src, arg)) |val| {
+ if (try sema.resolveMaybeUndefVal(block, src, arg)) |val| {
try writer.print("@as({}, {})", .{ arg_ty, val });
} else {
try writer.print("@as({}, [runtime value])", .{arg_ty});
@@ -2579,7 +2579,7 @@ fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile
const op_coerced = try sema.coerce(block, Type.initTag(.anyerror), op, operand_src);
const result_ty = Type.initTag(.u16);
- if (try sema.resolvePossiblyUndefinedValue(block, src, op_coerced)) |val| {
+ if (try sema.resolveMaybeUndefVal(block, src, op_coerced)) |val| {
if (val.isUndef()) {
return sema.addConstUndef(result_ty);
}
@@ -2759,7 +2759,7 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE
return sema.addConstant(int_tag_ty, opv);
}
- if (try sema.resolvePossiblyUndefinedValue(block, operand_src, enum_tag)) |enum_tag_val| {
+ if (try sema.resolveMaybeUndefVal(block, operand_src, enum_tag)) |enum_tag_val| {
if (enum_tag_val.castTag(.enum_field_index)) |enum_field_payload| {
const field_index = enum_field_payload.data;
switch (enum_tag_ty.tag()) {
@@ -2806,7 +2806,7 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE
return mod.fail(&block.base, dest_ty_src, "expected enum, found {}", .{dest_ty});
}
- if (try sema.resolvePossiblyUndefinedValue(block, operand_src, operand)) |int_val| {
+ if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |int_val| {
if (dest_ty.isNonexhaustiveEnum()) {
return sema.addConstant(dest_ty, int_val);
}
@@ -3309,16 +3309,16 @@ fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
+ const lhs_src: LazySrcLoc = src; // TODO
const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
const field_name = sema.code.nullTerminatedString(extra.field_name_start);
const object = sema.resolveInst(extra.lhs);
- const object_ptr = if (sema.typeOf(object).zigTypeTag() == .Pointer)
- object
- else
- try sema.analyzeRef(block, src, object);
- const result_ptr = try sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
- const result_ptr_src = src;
- return sema.analyzeLoad(block, src, result_ptr, result_ptr_src);
+ if (sema.typeOf(object).isSinglePointer()) {
+ const result_ptr = try sema.fieldPtr(block, src, object, field_name, field_name_src);
+ return sema.analyzeLoad(block, src, result_ptr, lhs_src);
+ } else {
+ return sema.fieldVal(block, src, object, field_name, field_name_src);
+ }
}
fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -3331,7 +3331,7 @@ fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
const field_name = sema.code.nullTerminatedString(extra.field_name_start);
const object_ptr = sema.resolveInst(extra.lhs);
- return sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
+ return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src);
}
fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -3344,9 +3344,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp
const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
const object = sema.resolveInst(extra.lhs);
const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);
- const object_ptr = try sema.analyzeRef(block, src, object);
- const result_ptr = try sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
- return sema.analyzeLoad(block, src, result_ptr, src);
+ return sema.fieldVal(block, src, object, field_name, field_name_src);
}
fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -3359,7 +3357,7 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp
const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
const object_ptr = sema.resolveInst(extra.lhs);
const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);
- return sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
+ return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src);
}
fn zirIntCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -4691,8 +4689,8 @@ fn zirBitwise(
return sema.mod.fail(&block.base, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag()), @tagName(rhs_ty.zigTypeTag()) });
}
- if (try sema.resolvePossiblyUndefinedValue(block, lhs_src, casted_lhs)) |lhs_val| {
- if (try sema.resolvePossiblyUndefinedValue(block, rhs_src, casted_rhs)) |rhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
if (lhs_val.isUndef() or rhs_val.isUndef()) {
return sema.addConstUndef(resolved_type);
}
@@ -4823,8 +4821,8 @@ fn analyzeArithmetic(
return sema.mod.fail(&block.base, src, "invalid operands to binary expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag()), @tagName(rhs_ty.zigTypeTag()) });
}
- if (try sema.resolvePossiblyUndefinedValue(block, lhs_src, casted_lhs)) |lhs_val| {
- if (try sema.resolvePossiblyUndefinedValue(block, rhs_src, casted_rhs)) |rhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
if (lhs_val.isUndef() or rhs_val.isUndef()) {
return sema.addConstUndef(resolved_type);
}
@@ -5038,8 +5036,8 @@ fn zirCmp(
if (!is_equality_cmp) {
return mod.fail(&block.base, src, "{s} operator not allowed for errors", .{@tagName(op)});
}
- if (try sema.resolvePossiblyUndefinedValue(block, lhs_src, lhs)) |lval| {
- if (try sema.resolvePossiblyUndefinedValue(block, rhs_src, rhs)) |rval| {
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lval| {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rval| {
if (lval.isUndef() or rval.isUndef()) {
return sema.addConstUndef(Type.initTag(.bool));
}
@@ -5085,8 +5083,8 @@ fn zirCmp(
const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
- if (try sema.resolvePossiblyUndefinedValue(block, lhs_src, casted_lhs)) |lhs_val| {
- if (try sema.resolvePossiblyUndefinedValue(block, rhs_src, casted_rhs)) |rhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
if (lhs_val.isUndef() or rhs_val.isUndef()) {
return sema.addConstUndef(resolved_type);
}
@@ -5759,7 +5757,7 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref:
if (is_comptime) {
const values = try sema.arena.alloc(Value, field_inits.len);
for (field_inits) |field_init, i| {
- values[i] = (sema.resolvePossiblyUndefinedValue(block, src, field_init) catch unreachable).?;
+ values[i] = (sema.resolveMaybeUndefVal(block, src, field_init) catch unreachable).?;
}
return sema.addConstant(struct_ty, try Value.Tag.@"struct".create(sema.arena, values.ptr));
}
@@ -6234,7 +6232,7 @@ fn zirVarExtended(
const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const init_air_inst = sema.resolveInst(init_ref);
- break :blk (try sema.resolvePossiblyUndefinedValue(block, init_src, init_air_inst)) orelse
+ break :blk (try sema.resolveMaybeUndefVal(block, init_src, init_air_inst)) orelse
return sema.failWithNeededComptime(block, init_src);
} else Value.initTag(.unreachable_value);
@@ -6565,7 +6563,177 @@ fn emitBackwardBranch(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
}
}
-fn namedFieldPtr(
+fn fieldVal(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ object: Air.Inst.Ref,
+ field_name: []const u8,
+ field_name_src: LazySrcLoc,
+) CompileError!Air.Inst.Ref {
+ // When editing this function, note that there is corresponding logic to be edited
+ // in `fieldPtr`. This function takes a value and returns a value.
+
+ const mod = sema.mod;
+ const arena = sema.arena;
+ const object_src = src; // TODO better source location
+ const object_ty = sema.typeOf(object);
+
+ switch (object_ty.zigTypeTag()) {
+ .Array => {
+ if (mem.eql(u8, field_name, "len")) {
+ return sema.addConstant(
+ Type.initTag(.comptime_int),
+ try Value.Tag.int_u64.create(arena, object_ty.arrayLen()),
+ );
+ } else {
+ return mod.fail(
+ &block.base,
+ field_name_src,
+ "no member named '{s}' in '{}'",
+ .{ field_name, object_ty },
+ );
+ }
+ },
+ .Pointer => switch (object_ty.ptrSize()) {
+ .Slice => {
+ if (mem.eql(u8, field_name, "ptr")) {
+ const buf = try arena.create(Type.Payload.ElemType);
+ const result_ty = object_ty.slicePtrFieldType(buf);
+ if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| {
+ if (val.isUndef()) return sema.addConstUndef(result_ty);
+ return mod.fail(
+ &block.base,
+ field_name_src,
+ "TODO implement comptime slice ptr",
+ .{},
+ );
+ }
+ try sema.requireRuntimeBlock(block, src);
+ return block.addTyOp(.slice_ptr, result_ty, object);
+ } else if (mem.eql(u8, field_name, "len")) {
+ const result_ty = Type.initTag(.usize);
+ if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| {
+ if (val.isUndef()) return sema.addConstUndef(result_ty);
+ return sema.addConstant(
+ result_ty,
+ try Value.Tag.int_u64.create(arena, val.sliceLen()),
+ );
+ }
+ try sema.requireRuntimeBlock(block, src);
+ return block.addTyOp(.slice_len, result_ty, object);
+ } else {
+ return mod.fail(
+ &block.base,
+ field_name_src,
+ "no member named '{s}' in '{}'",
+ .{ field_name, object_ty },
+ );
+ }
+ },
+ .One => {
+ const elem_ty = object_ty.elemType();
+ if (elem_ty.zigTypeTag() == .Array) {
+ if (mem.eql(u8, field_name, "len")) {
+ return sema.addConstant(
+ Type.initTag(.comptime_int),
+ try Value.Tag.int_u64.create(arena, elem_ty.arrayLen()),
+ );
+ } else {
+ return mod.fail(
+ &block.base,
+ field_name_src,
+ "no member named '{s}' in '{}'",
+ .{ field_name, object_ty },
+ );
+ }
+ }
+ },
+ .Many, .C => {},
+ },
+ .Type => {
+ const val = (try sema.resolveDefinedValue(block, object_src, object)).?;
+ const child_type = try val.toType(arena);
+ switch (child_type.zigTypeTag()) {
+ .ErrorSet => {
+ // TODO resolve inferred error sets
+ const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: {
+ const error_set = payload.data;
+ // TODO this is O(N). I'm putting off solving this until we solve inferred
+ // error sets at the same time.
+ const names = error_set.names_ptr[0..error_set.names_len];
+ for (names) |name| {
+ if (mem.eql(u8, field_name, name)) {
+ break :blk name;
+ }
+ }
+ return mod.fail(&block.base, src, "no error named '{s}' in '{}'", .{
+ field_name, child_type,
+ });
+ } else (try mod.getErrorValue(field_name)).key;
+
+ return sema.addConstant(
+ child_type,
+ try Value.Tag.@"error".create(arena, .{ .name = name }),
+ );
+ },
+ .Struct, .Opaque, .Union => {
+ if (child_type.getNamespace()) |namespace| {
+ if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
+ return sema.analyzeLoad(block, src, inst, src);
+ }
+ }
+ // TODO add note: declared here
+ const kw_name = switch (child_type.zigTypeTag()) {
+ .Struct => "struct",
+ .Opaque => "opaque",
+ .Union => "union",
+ else => unreachable,
+ };
+ return mod.fail(&block.base, src, "{s} '{}' has no member named '{s}'", .{
+ kw_name, child_type, field_name,
+ });
+ },
+ .Enum => {
+ if (child_type.getNamespace()) |namespace| {
+ if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
+ return sema.analyzeLoad(block, src, inst, src);
+ }
+ }
+ const field_index = child_type.enumFieldIndex(field_name) orelse {
+ const msg = msg: {
+ const msg = try mod.errMsg(
+ &block.base,
+ src,
+ "enum '{}' has no member named '{s}'",
+ .{ child_type, field_name },
+ );
+ errdefer msg.destroy(sema.gpa);
+ try mod.errNoteNonLazy(
+ child_type.declSrcLoc(),
+ msg,
+ "enum declared here",
+ .{},
+ );
+ break :msg msg;
+ };
+ return mod.failWithOwnedErrorMsg(&block.base, msg);
+ };
+ const field_index_u32 = @intCast(u32, field_index);
+ const enum_val = try Value.Tag.enum_field_index.create(arena, field_index_u32);
+ return sema.addConstant(child_type, enum_val);
+ },
+ else => return mod.fail(&block.base, src, "type '{}' has no members", .{child_type}),
+ }
+ },
+ .Struct => return sema.structFieldVal(block, src, object, field_name, field_name_src, object_ty),
+ .Union => return sema.unionFieldVal(block, src, object, field_name, field_name_src, object_ty),
+ else => {},
+ }
+ return mod.fail(&block.base, src, "type '{}' does not support field access", .{object_ty});
+}
+
+fn fieldPtr(
sema: *Sema,
block: *Scope.Block,
src: LazySrcLoc,
@@ -6573,23 +6741,25 @@ fn namedFieldPtr(
field_name: []const u8,
field_name_src: LazySrcLoc,
) CompileError!Air.Inst.Ref {
+ // When editing this function, note that there is corresponding logic to be edited
+ // in `fieldVal`. This function takes a pointer and returns a pointer.
+
const mod = sema.mod;
const arena = sema.arena;
-
const object_ptr_src = src; // TODO better source location
const object_ptr_ty = sema.typeOf(object_ptr);
- const elem_ty = switch (object_ptr_ty.zigTypeTag()) {
+ const object_ty = switch (object_ptr_ty.zigTypeTag()) {
.Pointer => object_ptr_ty.elemType(),
else => return mod.fail(&block.base, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty}),
};
- switch (elem_ty.zigTypeTag()) {
+ switch (object_ty.zigTypeTag()) {
.Array => {
if (mem.eql(u8, field_name, "len")) {
return sema.addConstant(
Type.initTag(.single_const_pointer_to_comptime_int),
try Value.Tag.ref_val.create(
arena,
- try Value.Tag.int_u64.create(arena, elem_ty.arrayLen()),
+ try Value.Tag.int_u64.create(arena, object_ty.arrayLen()),
),
);
} else {
@@ -6597,33 +6767,33 @@ fn namedFieldPtr(
&block.base,
field_name_src,
"no member named '{s}' in '{}'",
- .{ field_name, elem_ty },
+ .{ field_name, object_ty },
);
}
},
.Pointer => {
- const ptr_child = elem_ty.elemType();
+ const ptr_child = object_ty.elemType();
if (ptr_child.isSlice()) {
if (mem.eql(u8, field_name, "ptr")) {
return mod.fail(
&block.base,
field_name_src,
"cannot obtain reference to pointer field of slice '{}'",
- .{elem_ty},
+ .{object_ty},
);
} else if (mem.eql(u8, field_name, "len")) {
return mod.fail(
&block.base,
field_name_src,
"cannot obtain reference to length field of slice '{}'",
- .{elem_ty},
+ .{object_ty},
);
} else {
return mod.fail(
&block.base,
field_name_src,
"no member named '{s}' in '{}'",
- .{ field_name, elem_ty },
+ .{ field_name, object_ty },
);
}
} else switch (ptr_child.zigTypeTag()) {
@@ -6641,7 +6811,7 @@ fn namedFieldPtr(
&block.base,
field_name_src,
"no member named '{s}' in '{}'",
- .{ field_name, elem_ty },
+ .{ field_name, object_ty },
);
}
},
@@ -6684,7 +6854,7 @@ fn namedFieldPtr(
},
.Struct, .Opaque, .Union => {
if (child_type.getNamespace()) |namespace| {
- if (try sema.analyzeNamespaceLookup(block, src, namespace, field_name)) |inst| {
+ if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
return inst;
}
}
@@ -6701,7 +6871,7 @@ fn namedFieldPtr(
},
.Enum => {
if (child_type.getNamespace()) |namespace| {
- if (try sema.analyzeNamespaceLookup(block, src, namespace, field_name)) |inst| {
+ if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
return inst;
}
}
@@ -6734,20 +6904,20 @@ fn namedFieldPtr(
else => return mod.fail(&block.base, src, "type '{}' has no members", .{child_type}),
}
},
- .Struct => return sema.analyzeStructFieldPtr(block, src, object_ptr, field_name, field_name_src, elem_ty),
- .Union => return sema.analyzeUnionFieldPtr(block, src, object_ptr, field_name, field_name_src, elem_ty),
+ .Struct => return sema.structFieldPtr(block, src, object_ptr, field_name, field_name_src, object_ty),
+ .Union => return sema.unionFieldPtr(block, src, object_ptr, field_name, field_name_src, object_ty),
else => {},
}
- return mod.fail(&block.base, src, "type '{}' does not support field access", .{elem_ty});
+ return mod.fail(&block.base, src, "type '{}' does not support field access", .{object_ty});
}
-fn analyzeNamespaceLookup(
+fn namespaceLookup(
sema: *Sema,
block: *Scope.Block,
src: LazySrcLoc,
namespace: *Scope.Namespace,
decl_name: []const u8,
-) CompileError!?Air.Inst.Ref {
+) CompileError!?*Decl {
const mod = sema.mod;
const gpa = sema.gpa;
if (try sema.lookupInNamespace(namespace, decl_name)) |decl| {
@@ -6762,12 +6932,23 @@ fn analyzeNamespaceLookup(
};
return mod.failWithOwnedErrorMsg(&block.base, msg);
}
- return try sema.analyzeDeclRef(block, src, decl);
+ return decl;
}
return null;
}
-fn analyzeStructFieldPtr(
+fn namespaceLookupRef(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ namespace: *Scope.Namespace,
+ decl_name: []const u8,
+) CompileError!?Air.Inst.Ref {
+ const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null;
+ return try sema.analyzeDeclRef(block, src, decl);
+}
+
+fn structFieldPtr(
sema: *Sema,
block: *Scope.Block,
src: LazySrcLoc,
@@ -6803,14 +6984,52 @@ fn analyzeStructFieldPtr(
.data = .{ .ty_pl = .{
.ty = try sema.addType(ptr_field_ty),
.payload = try sema.addExtra(Air.StructField{
- .struct_ptr = struct_ptr,
+ .struct_operand = struct_ptr,
.field_index = @intCast(u32, field_index),
}),
} },
});
}
-fn analyzeUnionFieldPtr(
+fn structFieldVal(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ struct_byval: Air.Inst.Ref,
+ field_name: []const u8,
+ field_name_src: LazySrcLoc,
+ unresolved_struct_ty: Type,
+) CompileError!Air.Inst.Ref {
+ assert(unresolved_struct_ty.zigTypeTag() == .Struct);
+
+ const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
+ const struct_obj = struct_ty.castTag(.@"struct").?.data;
+
+ const field_index = struct_obj.fields.getIndex(field_name) orelse
+ return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);
+ const field = struct_obj.fields.values()[field_index];
+
+ if (try sema.resolveMaybeUndefVal(block, src, struct_byval)) |struct_val| {
+ if (struct_val.isUndef()) return sema.addConstUndef(field.ty);
+
+ const field_values = struct_val.castTag(.@"struct").?.data;
+ return sema.addConstant(field.ty, field_values[field_index]);
+ }
+
+ try sema.requireRuntimeBlock(block, src);
+ return block.addInst(.{
+ .tag = .struct_field_val,
+ .data = .{ .ty_pl = .{
+ .ty = try sema.addType(field.ty),
+ .payload = try sema.addExtra(Air.StructField{
+ .struct_operand = struct_byval,
+ .field_index = @intCast(u32, field_index),
+ }),
+ } },
+ });
+}
+
+fn unionFieldPtr(
sema: *Sema,
block: *Scope.Block,
src: LazySrcLoc,
@@ -6847,6 +7066,37 @@ fn analyzeUnionFieldPtr(
return mod.fail(&block.base, src, "TODO implement runtime union field access", .{});
}
+fn unionFieldVal(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ union_byval: Air.Inst.Ref,
+ field_name: []const u8,
+ field_name_src: LazySrcLoc,
+ unresolved_union_ty: Type,
+) CompileError!Air.Inst.Ref {
+ assert(unresolved_union_ty.zigTypeTag() == .Union);
+
+ const union_ty = try sema.resolveTypeFields(block, src, unresolved_union_ty);
+ const union_obj = union_ty.cast(Type.Payload.Union).?.data;
+
+ const field_index = union_obj.fields.getIndex(field_name) orelse
+ return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name);
+
+ const field = union_obj.fields.values()[field_index];
+
+ if (try sema.resolveMaybeUndefVal(block, src, union_byval)) |union_val| {
+ if (union_val.isUndef()) return sema.addConstUndef(field.ty);
+
+ // TODO detect inactive union field and emit compile error
+ const active_val = union_val.castTag(.@"union").?.data.val;
+ return sema.addConstant(field.ty, active_val);
+ }
+
+ try sema.requireRuntimeBlock(block, src);
+ return sema.mod.fail(&block.base, src, "TODO implement runtime union field access", .{});
+}
+
fn elemPtr(
sema: *Sema,
block: *Scope.Block,
@@ -6973,7 +7223,7 @@ fn coerce(
const arena = sema.arena;
// undefined to anything
- if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| {
+ if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
if (val.isUndef() or inst_ty.zigTypeTag() == .Undefined) {
return sema.addConstant(dest_type, val);
}
@@ -7207,8 +7457,8 @@ fn storePtr(
if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null)
return;
- if (try sema.resolvePossiblyUndefinedValue(block, src, ptr)) |ptr_val| blk: {
- const const_val = (try sema.resolvePossiblyUndefinedValue(block, src, value)) orelse
+ if (try sema.resolveMaybeUndefVal(block, src, ptr)) |ptr_val| blk: {
+ const const_val = (try sema.resolveMaybeUndefVal(block, src, value)) orelse
return sema.mod.fail(&block.base, src, "cannot store runtime value in compile time variable", .{});
if (ptr_val.tag() == .int_u64)
@@ -7252,7 +7502,7 @@ fn bitcast(
inst: Air.Inst.Ref,
inst_src: LazySrcLoc,
) CompileError!Air.Inst.Ref {
- if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| {
+ if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
// Keep the comptime Value representation; take the new type.
return sema.addConstant(dest_type, val);
}
@@ -7358,7 +7608,7 @@ fn analyzeRef(
const operand_ty = sema.typeOf(operand);
const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One);
- if (try sema.resolvePossiblyUndefinedValue(block, src, operand)) |val| {
+ if (try sema.resolveMaybeUndefVal(block, src, operand)) |val| {
return sema.addConstant(ptr_type, try Value.Tag.ref_val.create(sema.arena, val));
}
@@ -7395,7 +7645,7 @@ fn analyzeSliceLen(
src: LazySrcLoc,
slice_inst: Air.Inst.Ref,
) CompileError!Air.Inst.Ref {
- if (try sema.resolvePossiblyUndefinedValue(block, src, slice_inst)) |slice_val| {
+ if (try sema.resolveMaybeUndefVal(block, src, slice_inst)) |slice_val| {
if (slice_val.isUndef()) {
return sema.addConstUndef(Type.initTag(.usize));
}
@@ -7413,7 +7663,7 @@ fn analyzeIsNull(
invert_logic: bool,
) CompileError!Air.Inst.Ref {
const result_ty = Type.initTag(.bool);
- if (try sema.resolvePossiblyUndefinedValue(block, src, operand)) |opt_val| {
+ if (try sema.resolveMaybeUndefVal(block, src, operand)) |opt_val| {
if (opt_val.isUndef()) {
return sema.addConstUndef(result_ty);
}
@@ -7442,7 +7692,7 @@ fn analyzeIsNonErr(
if (ot == .ErrorSet) return Air.Inst.Ref.bool_false;
assert(ot == .ErrorUnion);
const result_ty = Type.initTag(.bool);
- if (try sema.resolvePossiblyUndefinedValue(block, src, operand)) |err_union| {
+ if (try sema.resolveMaybeUndefVal(block, src, operand)) |err_union| {
if (err_union.isUndef()) {
return sema.addConstUndef(result_ty);
}
@@ -7567,8 +7817,8 @@ fn cmpNumeric(
});
}
- if (try sema.resolvePossiblyUndefinedValue(block, lhs_src, lhs)) |lhs_val| {
- if (try sema.resolvePossiblyUndefinedValue(block, rhs_src, rhs)) |rhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
if (lhs_val.isUndef() or rhs_val.isUndef()) {
return sema.addConstUndef(Type.initTag(.bool));
}
@@ -7635,7 +7885,7 @@ fn cmpNumeric(
var dest_float_type: ?Type = null;
var lhs_bits: usize = undefined;
- if (try sema.resolvePossiblyUndefinedValue(block, lhs_src, lhs)) |lhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
if (lhs_val.isUndef())
return sema.addConstUndef(Type.initTag(.bool));
const is_unsigned = if (lhs_is_float) x: {
@@ -7670,7 +7920,7 @@ fn cmpNumeric(
}
var rhs_bits: usize = undefined;
- if (try sema.resolvePossiblyUndefinedValue(block, rhs_src, rhs)) |rhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
if (rhs_val.isUndef())
return sema.addConstUndef(Type.initTag(.bool));
const is_unsigned = if (rhs_is_float) x: {
@@ -7725,7 +7975,7 @@ fn wrapOptional(
inst: Air.Inst.Ref,
inst_src: LazySrcLoc,
) !Air.Inst.Ref {
- if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| {
+ if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
return sema.addConstant(dest_type, val);
}
@@ -7743,7 +7993,7 @@ fn wrapErrorUnion(
const inst_ty = sema.typeOf(inst);
const dest_err_set_ty = dest_type.errorUnionSet();
const dest_payload_ty = dest_type.errorUnionPayload();
- if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| {
+ if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
if (inst_ty.zigTypeTag() != .ErrorSet) {
_ = try sema.coerce(block, dest_payload_ty, inst, inst_src);
} else switch (dest_err_set_ty.tag()) {
@@ -7956,7 +8206,7 @@ fn getBuiltin(
const mod = sema.mod;
const std_pkg = mod.main_pkg.table.get("std").?;
const std_file = (mod.importPkg(std_pkg) catch unreachable).file;
- const opt_builtin_inst = try sema.analyzeNamespaceLookup(
+ const opt_builtin_inst = try sema.namespaceLookupRef(
block,
src,
std_file.root_decl.?.namespace,
@@ -7964,7 +8214,7 @@ fn getBuiltin(
);
const builtin_inst = try sema.analyzeLoad(block, src, opt_builtin_inst.?, src);
const builtin_ty = try sema.analyzeAsType(block, src, builtin_inst);
- const opt_ty_inst = try sema.analyzeNamespaceLookup(
+ const opt_ty_inst = try sema.namespaceLookupRef(
block,
src,
builtin_ty.getNamespace().?,
@@ -8320,5 +8570,5 @@ fn isComptimeKnown(
src: LazySrcLoc,
inst: Air.Inst.Ref,
) !bool {
- return (try sema.resolvePossiblyUndefinedValue(block, src, inst)) != null;
+ return (try sema.resolveMaybeUndefVal(block, src, inst)) != null;
}
diff --git a/src/codegen.zig b/src/codegen.zig
index c2504f26a8..4924b68ca3 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -851,6 +851,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.ret => try self.airRet(inst),
.store => try self.airStore(inst),
.struct_field_ptr=> try self.airStructFieldPtr(inst),
+ .struct_field_val=> try self.airStructFieldVal(inst),
.switch_br => try self.airSwitch(inst),
.varptr => try self.airVarPtr(inst),
.slice_ptr => try self.airSlicePtr(inst),
@@ -1501,6 +1502,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
//return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });
}
+ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
+ const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
+ const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
+ _ = extra;
+ return self.fail("TODO implement codegen struct_field_val", .{});
+ //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });
+ }
+
fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool {
return switch (mcv) {
.none => unreachable,
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 705c5c2ad1..fa254af293 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -935,6 +935,7 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
.wrap_optional => try airWrapOptional(o, inst),
.ref => try airRef(o, inst),
.struct_field_ptr => try airStructFieldPtr(o, inst),
+ .struct_field_val => try airStructFieldVal(o, inst),
.varptr => try airVarPtr(o, inst),
.slice_ptr => try airSliceField(o, inst, ".ptr;\n"),
.slice_len => try airSliceField(o, inst, ".len;\n"),
@@ -1660,8 +1661,8 @@ fn airStructFieldPtr(o: *Object, inst: Air.Inst.Index) !CValue {
const ty_pl = o.air.instructions.items(.data)[inst].ty_pl;
const extra = o.air.extraData(Air.StructField, ty_pl.payload).data;
const writer = o.writer();
- const struct_ptr = try o.resolveInst(extra.struct_ptr);
- const struct_ptr_ty = o.air.typeOf(extra.struct_ptr);
+ const struct_ptr = try o.resolveInst(extra.struct_operand);
+ const struct_ptr_ty = o.air.typeOf(extra.struct_operand);
const struct_obj = struct_ptr_ty.elemType().castTag(.@"struct").?.data;
const field_name = struct_obj.fields.keys()[extra.field_index];
@@ -1680,6 +1681,26 @@ fn airStructFieldPtr(o: *Object, inst: Air.Inst.Index) !CValue {
return local;
}
+fn airStructFieldVal(o: *Object, inst: Air.Inst.Index) !CValue {
+ if (o.liveness.isUnused(inst))
+ return CValue.none;
+
+ const ty_pl = o.air.instructions.items(.data)[inst].ty_pl;
+ const extra = o.air.extraData(Air.StructField, ty_pl.payload).data;
+ const writer = o.writer();
+ const struct_byval = try o.resolveInst(extra.struct_operand);
+ const struct_ty = o.air.typeOf(extra.struct_operand);
+ const struct_obj = struct_ty.castTag(.@"struct").?.data;
+ const field_name = struct_obj.fields.keys()[extra.field_index];
+
+ const inst_ty = o.air.typeOfIndex(inst);
+ const local = try o.allocLocal(inst_ty, .Const);
+ try writer.writeAll(" = ");
+ try o.writeCValue(writer, struct_byval);
+ try writer.print(".{};\n", .{fmtIdent(field_name)});
+ return local;
+}
+
// *(E!T) -> E NOT *E
fn airUnwrapErrUnionErr(o: *Object, inst: Air.Inst.Index) !CValue {
if (o.liveness.isUnused(inst))
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 4224591b0b..1b3c36fc69 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -350,19 +350,21 @@ pub const Object = struct {
air: Air,
liveness: Liveness,
) !void {
+ const decl = func.owner_decl;
+
var dg: DeclGen = .{
.context = self.context,
.object = self,
.module = module,
- .decl = func.owner_decl,
+ .decl = decl,
.err_msg = null,
.gpa = module.gpa,
};
- const llvm_func = try dg.resolveLLVMFunction(func.owner_decl);
+ const llvm_func = try dg.resolveLlvmFunction(decl);
// This gets the LLVM values from the function and stores them in `dg.args`.
- const fn_param_len = func.owner_decl.ty.fnParamLen();
+ const fn_param_len = decl.ty.fnParamLen();
var args = try dg.gpa.alloc(*const llvm.Value, fn_param_len);
for (args) |*arg, i| {
@@ -400,13 +402,16 @@ pub const Object = struct {
fg.genBody(air.getMainBody()) catch |err| switch (err) {
error.CodegenFail => {
- func.owner_decl.analysis = .codegen_failure;
- try module.failed_decls.put(module.gpa, func.owner_decl, dg.err_msg.?);
+ decl.analysis = .codegen_failure;
+ try module.failed_decls.put(module.gpa, decl, dg.err_msg.?);
dg.err_msg = null;
return;
},
else => |e| return e,
};
+
+ const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{};
+ try self.updateDeclExports(module, decl, decl_exports);
}
pub fn updateDecl(self: *Object, module: *Module, decl: *Module.Decl) !void {
@@ -428,6 +433,38 @@ pub const Object = struct {
else => |e| return e,
};
}
+
+ pub fn updateDeclExports(
+ self: *Object,
+ module: *const Module,
+ decl: *const Module.Decl,
+ exports: []const *Module.Export,
+ ) !void {
+ const llvm_fn = self.llvm_module.getNamedFunction(decl.name).?;
+ const is_extern = decl.val.tag() == .extern_fn;
+ if (is_extern or exports.len != 0) {
+ llvm_fn.setLinkage(.External);
+ llvm_fn.setUnnamedAddr(.False);
+ } else {
+ llvm_fn.setLinkage(.Internal);
+ llvm_fn.setUnnamedAddr(.True);
+ }
+ // TODO LLVM C API does not support deleting aliases. We need to
+ // patch it to support this or figure out how to wrap the C++ API ourselves.
+ // Until then we iterate over existing aliases and make them point
+ // to the correct decl, or otherwise add a new alias. Old aliases are leaked.
+ for (exports) |exp| {
+ if (self.llvm_module.getNamedGlobalAlias(exp.options.name.ptr, exp.options.name.len)) |alias| {
+ alias.setAliasee(llvm_fn);
+ } else {
+ const exp_name_z = try module.gpa.dupeZ(u8, exp.options.name);
+ defer module.gpa.free(exp_name_z);
+
+ const alias = self.llvm_module.addAlias(llvm_fn.typeOf(), llvm_fn, exp_name_z);
+ _ = alias;
+ }
+ }
+ }
};
pub const DeclGen = struct {
@@ -461,21 +498,19 @@ pub const DeclGen = struct {
_ = func_payload;
@panic("TODO llvm backend genDecl function pointer");
} else if (decl.val.castTag(.extern_fn)) |extern_fn| {
- _ = try self.resolveLLVMFunction(extern_fn.data);
+ _ = try self.resolveLlvmFunction(extern_fn.data);
} else {
_ = try self.resolveGlobalDecl(decl);
}
}
/// If the llvm function does not exist, create it
- fn resolveLLVMFunction(self: *DeclGen, func: *Module.Decl) !*const llvm.Value {
- // TODO: do we want to store this in our own datastructure?
- if (self.llvmModule().getNamedFunction(func.name)) |llvm_fn| return llvm_fn;
+ fn resolveLlvmFunction(self: *DeclGen, decl: *Module.Decl) !*const llvm.Value {
+ if (self.llvmModule().getNamedFunction(decl.name)) |llvm_fn| return llvm_fn;
- assert(func.has_tv);
- const zig_fn_type = func.ty;
+ assert(decl.has_tv);
+ const zig_fn_type = decl.ty;
const return_type = zig_fn_type.fnReturnType();
-
const fn_param_len = zig_fn_type.fnParamLen();
const fn_param_types = try self.gpa.alloc(Type, fn_param_len);
@@ -495,9 +530,17 @@ pub const DeclGen = struct {
@intCast(c_uint, fn_param_len),
.False,
);
- const llvm_fn = self.llvmModule().addFunction(func.name, fn_type);
+ const llvm_fn = self.llvmModule().addFunction(decl.name, fn_type);
- if (return_type.tag() == .noreturn) {
+ const is_extern = decl.val.tag() == .extern_fn;
+ if (!is_extern) {
+ llvm_fn.setLinkage(.Internal);
+ llvm_fn.setUnnamedAddr(.True);
+ }
+
+ // TODO: calling convention, linkage, tsan, etc. see codegen.cpp `make_fn_llvm_value`.
+
+ if (return_type.isNoReturn()) {
self.addFnAttr(llvm_fn, "noreturn");
}
@@ -505,7 +548,6 @@ pub const DeclGen = struct {
}
fn resolveGlobalDecl(self: *DeclGen, decl: *Module.Decl) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
- // TODO: do we want to store this in our own datastructure?
if (self.llvmModule().getNamedGlobal(decl.name)) |val| return val;
assert(decl.has_tv);
@@ -515,9 +557,11 @@ pub const DeclGen = struct {
const global = self.llvmModule().addGlobal(llvm_type, decl.name);
const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
const variable = payload.data;
- global.setGlobalConstant(.False);
break :init_val variable.init;
- } else decl.val;
+ } else init_val: {
+ global.setGlobalConstant(.True);
+ break :init_val decl.val;
+ };
const llvm_init = try self.genTypedValue(.{ .ty = decl.ty, .val = init_val }, null);
llvm.setInitializer(global, llvm_init);
@@ -602,12 +646,13 @@ pub const DeclGen = struct {
llvm_param.* = try self.llvmType(t.fnParamType(i));
}
const is_var_args = t.fnIsVarArgs();
- return llvm.functionType(
+ const llvm_fn_ty = llvm.functionType(
ret_ty,
llvm_params.ptr,
@intCast(c_uint, llvm_params.len),
llvm.Bool.fromBool(is_var_args),
);
+ return llvm_fn_ty.pointerType(0);
},
.ComptimeInt => unreachable,
.ComptimeFloat => unreachable,
@@ -717,6 +762,42 @@ pub const DeclGen = struct {
return self.todo("implement const of optional pointer", .{});
}
},
+ .Fn => {
+ const fn_decl = if (tv.val.castTag(.extern_fn)) |extern_fn|
+ extern_fn.data
+ else if (tv.val.castTag(.function)) |func_payload|
+ func_payload.data.owner_decl
+ else
+ unreachable;
+
+ return self.resolveLlvmFunction(fn_decl);
+ },
+ .ErrorSet => {
+ const llvm_ty = try self.llvmType(tv.ty);
+ switch (tv.val.tag()) {
+ .@"error" => {
+ const err_name = tv.val.castTag(.@"error").?.data.name;
+ const kv = try self.module.getErrorValue(err_name);
+ return llvm_ty.constInt(kv.value, .False);
+ },
+ else => {
+ // In this case we are rendering an error union which has a 0 bits payload.
+ return llvm_ty.constNull();
+ },
+ }
+ },
+ .ErrorUnion => {
+ const error_type = tv.ty.errorUnionSet();
+ const payload_type = tv.ty.errorUnionPayload();
+ const sub_val = tv.val.castTag(.error_union).?.data;
+
+ if (!payload_type.hasCodeGenBits()) {
+ // We use the error type directly as the type.
+ return self.genTypedValue(.{ .ty = error_type, .val = sub_val }, fg);
+ }
+
+ return self.todo("implement error union const of type '{}'", .{tv.ty});
+ },
else => return self.todo("implement const of type '{}'", .{tv.ty}),
}
}
@@ -801,8 +882,17 @@ pub const FuncGen = struct {
for (body) |inst| {
const opt_value: ?*const llvm.Value = switch (air_tags[inst]) {
// zig fmt: off
- .add => try self.airAdd(inst),
- .sub => try self.airSub(inst),
+ .add => try self.airAdd(inst, false),
+ .addwrap => try self.airAdd(inst, true),
+ .sub => try self.airSub(inst, false),
+ .subwrap => try self.airSub(inst, true),
+ .mul => try self.airMul(inst, false),
+ .mulwrap => try self.airMul(inst, true),
+ .div => try self.airDiv(inst),
+
+ .bit_and, .bool_and => try self.airAnd(inst),
+ .bit_or, .bool_or => try self.airOr(inst),
+ .xor => try self.airXor(inst),
.cmp_eq => try self.airCmp(inst, .eq),
.cmp_gt => try self.airCmp(inst, .gt),
@@ -825,10 +915,12 @@ pub const FuncGen = struct {
.bitcast => try self.airBitCast(inst),
.block => try self.airBlock(inst),
.br => try self.airBr(inst),
+ .switch_br => try self.airSwitchBr(inst),
.breakpoint => try self.airBreakpoint(inst),
.call => try self.airCall(inst),
.cond_br => try self.airCondBr(inst),
.intcast => try self.airIntCast(inst),
+ .floatcast => try self.airFloatCast(inst),
.ptrtoint => try self.airPtrToInt(inst),
.load => try self.airLoad(inst),
.loop => try self.airLoop(inst),
@@ -840,6 +932,9 @@ pub const FuncGen = struct {
.slice_ptr => try self.airSliceField(inst, 0),
.slice_len => try self.airSliceField(inst, 1),
+ .struct_field_ptr => try self.airStructFieldPtr(inst),
+ .struct_field_val => try self.airStructFieldVal(inst),
+
.slice_elem_val => try self.airSliceElemVal(inst, false),
.ptr_slice_elem_val => try self.airSliceElemVal(inst, true),
@@ -851,12 +946,18 @@ pub const FuncGen = struct {
.unwrap_errunion_err => try self.airErrUnionErr(inst, false),
.unwrap_errunion_err_ptr => try self.airErrUnionErr(inst, true),
+ .wrap_optional => try self.airWrapOptional(inst),
+ .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
+ .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
+
+ .constant => unreachable,
+ .const_ty => unreachable,
+ .ref => unreachable, // TODO eradicate this instruction
.unreach => self.airUnreach(inst),
.dbg_stmt => blk: {
// TODO: implement debug info
break :blk null;
},
- else => |tag| return self.todo("implement AIR instruction: {}", .{tag}),
// zig fmt: on
};
if (opt_value) |val| try self.func_inst_table.putNoClobber(self.gpa, inst, val);
@@ -867,47 +968,32 @@ pub const FuncGen = struct {
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
const extra = self.air.extraData(Air.Call, pl_op.payload);
const args = @bitCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
+ const zig_fn_type = self.air.typeOf(pl_op.operand);
+ const return_type = zig_fn_type.fnReturnType();
+ const llvm_fn = try self.resolveInst(pl_op.operand);
- if (self.air.value(pl_op.operand)) |func_value| {
- const fn_decl = if (func_value.castTag(.extern_fn)) |extern_fn|
- extern_fn.data
- else if (func_value.castTag(.function)) |func_payload|
- func_payload.data.owner_decl
- else
- unreachable;
+ const llvm_param_vals = try self.gpa.alloc(*const llvm.Value, args.len);
+ defer self.gpa.free(llvm_param_vals);
- assert(fn_decl.has_tv);
- const zig_fn_type = fn_decl.ty;
- const llvm_fn = try self.dg.resolveLLVMFunction(fn_decl);
-
- const llvm_param_vals = try self.gpa.alloc(*const llvm.Value, args.len);
- defer self.gpa.free(llvm_param_vals);
-
- for (args) |arg, i| {
- llvm_param_vals[i] = try self.resolveInst(arg);
- }
-
- // TODO: LLVMBuildCall2 handles opaque function pointers, according to llvm docs
- // Do we need that?
- const call = self.builder.buildCall(
- llvm_fn,
- llvm_param_vals.ptr,
- @intCast(c_uint, args.len),
- "",
- );
-
- const return_type = zig_fn_type.fnReturnType();
- if (return_type.tag() == .noreturn) {
- _ = self.builder.buildUnreachable();
- }
-
- // No need to store the LLVM value if the return type is void or noreturn
- if (!return_type.hasCodeGenBits()) return null;
-
- return call;
- } else {
- return self.todo("implement calling runtime known function pointer", .{});
+ for (args) |arg, i| {
+ llvm_param_vals[i] = try self.resolveInst(arg);
}
+
+ const call = self.builder.buildCall(
+ llvm_fn,
+ llvm_param_vals.ptr,
+ @intCast(c_uint, args.len),
+ "",
+ );
+
+ if (return_type.isNoReturn()) {
+ _ = self.builder.buildUnreachable();
+ }
+
+ // No need to store the LLVM value if the return type is void or noreturn
+ if (!return_type.hasCodeGenBits()) return null;
+
+ return call;
}
fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
@@ -1026,6 +1112,11 @@ pub const FuncGen = struct {
return null;
}
+ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ _ = inst;
+ return self.todo("implement llvm codegen for switch_br", .{});
+ }
+
fn airLoop(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const loop = self.air.extraData(Air.Block, ty_pl.payload);
@@ -1082,10 +1173,32 @@ pub const FuncGen = struct {
};
const indices: [1]*const llvm.Value = .{rhs};
- const ptr = self.builder.buildInBoundsGEP(base_ptr, &indices, 1, "");
+ const ptr = self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, "");
return self.builder.buildLoad(ptr, "");
}
+ fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
+ const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
+ const struct_ptr = try self.resolveInst(struct_field.struct_operand);
+ const field_index = @intCast(c_uint, struct_field.field_index);
+ return self.builder.buildStructGEP(struct_ptr, field_index, "");
+ }
+
+ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
+ const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
+ const struct_byval = try self.resolveInst(struct_field.struct_operand);
+ const field_index = @intCast(c_uint, struct_field.field_index);
+ return self.builder.buildExtractValue(struct_byval, field_index, "");
+ }
+
fn airNot(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
@@ -1321,7 +1434,7 @@ pub const FuncGen = struct {
_ = operand;
_ = operand_is_ptr;
- return self.todo("implement 'airErrUnionPayload' for type {}", .{self.air.typeOf(ty_op.operand)});
+ return self.todo("implement llvm codegen for 'airErrUnionPayload' for type {}", .{self.air.typeOf(ty_op.operand)});
}
fn airErrUnionErr(
@@ -1332,42 +1445,123 @@ pub const FuncGen = struct {
if (self.liveness.isUnused(inst))
return null;
- _ = operand_is_ptr;
- return self.todo("implement 'airErrUnionErr'", .{});
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const operand = try self.resolveInst(ty_op.operand);
+ const operand_ty = self.air.typeOf(ty_op.operand);
+
+ const payload_ty = operand_ty.errorUnionPayload();
+ if (!payload_ty.hasCodeGenBits()) {
+ if (!operand_is_ptr) return operand;
+ return self.builder.buildLoad(operand, "");
+ }
+ return self.todo("implement llvm codegen for 'airErrUnionErr'", .{});
}
- fn airAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
+
+ return self.todo("implement llvm codegen for 'airWrapOptional'", .{});
+ }
+
+ fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ return self.todo("implement llvm codegen for 'airWrapErrUnionPayload'", .{});
+ }
+
+ fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ return self.todo("implement llvm codegen for 'airWrapErrUnionErr'", .{});
+ }
+
+ fn airAdd(self: *FuncGen, inst: Air.Inst.Index, wrap: bool) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
const rhs = try self.resolveInst(bin_op.rhs);
const inst_ty = self.air.typeOfIndex(inst);
- if (!inst_ty.isInt())
- return self.todo("implement 'airAdd' for type {}", .{inst_ty});
-
- return if (inst_ty.isSignedInt())
- self.builder.buildNSWAdd(lhs, rhs, "")
- else
- self.builder.buildNUWAdd(lhs, rhs, "");
+ if (inst_ty.isFloat()) return self.builder.buildFAdd(lhs, rhs, "");
+ if (wrap) return self.builder.buildAdd(lhs, rhs, "");
+ if (inst_ty.isSignedInt()) return self.builder.buildNSWAdd(lhs, rhs, "");
+ return self.builder.buildNUWAdd(lhs, rhs, "");
}
- fn airSub(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airSub(self: *FuncGen, inst: Air.Inst.Index, wrap: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
+
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
const rhs = try self.resolveInst(bin_op.rhs);
const inst_ty = self.air.typeOfIndex(inst);
- if (!inst_ty.isInt())
- return self.todo("implement 'airSub' for type {}", .{inst_ty});
+ if (inst_ty.isFloat()) return self.builder.buildFSub(lhs, rhs, "");
+ if (wrap) return self.builder.buildSub(lhs, rhs, "");
+ if (inst_ty.isSignedInt()) return self.builder.buildNSWSub(lhs, rhs, "");
+ return self.builder.buildNUWSub(lhs, rhs, "");
+ }
- return if (inst_ty.isSignedInt())
- self.builder.buildNSWSub(lhs, rhs, "")
- else
- self.builder.buildNUWSub(lhs, rhs, "");
+ fn airMul(self: *FuncGen, inst: Air.Inst.Index, wrap: bool) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
+ const inst_ty = self.air.typeOfIndex(inst);
+
+ if (inst_ty.isFloat()) return self.builder.buildFMul(lhs, rhs, "");
+ if (wrap) return self.builder.buildMul(lhs, rhs, "");
+ if (inst_ty.isSignedInt()) return self.builder.buildNSWMul(lhs, rhs, "");
+ return self.builder.buildNUWMul(lhs, rhs, "");
+ }
+
+ fn airDiv(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
+ const inst_ty = self.air.typeOfIndex(inst);
+
+ if (inst_ty.isFloat()) return self.builder.buildFDiv(lhs, rhs, "");
+ if (inst_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, "");
+ return self.builder.buildUDiv(lhs, rhs, "");
+ }
+
+ fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
+ return self.builder.buildAnd(lhs, rhs, "");
+ }
+
+ fn airOr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
+ return self.builder.buildOr(lhs, rhs, "");
+ }
+
+ fn airXor(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
+ return self.builder.buildXor(lhs, rhs, "");
}
fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
@@ -1384,6 +1578,14 @@ pub const FuncGen = struct {
return self.builder.buildIntCast2(operand, try self.dg.llvmType(inst_ty), llvm.Bool.fromBool(signed), "");
}
+ fn airFloatCast(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ // TODO split floatcast AIR into float_widen and float_shorten
+ return self.todo("implement 'airFloatCast'", .{});
+ }
+
fn airPtrToInt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
@@ -1474,8 +1676,8 @@ pub const FuncGen = struct {
fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
_ = inst;
- const llvn_fn = self.getIntrinsic("llvm.debugtrap");
- _ = self.builder.buildCall(llvn_fn, undefined, 0, "");
+ const llvm_fn = self.getIntrinsic("llvm.debugtrap");
+ _ = self.builder.buildCall(llvm_fn, undefined, 0, "");
return null;
}
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index 3b76361030..9ef6d7e1ac 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -82,6 +82,24 @@ pub const Value = opaque {
pub const setGlobalConstant = LLVMSetGlobalConstant;
extern fn LLVMSetGlobalConstant(GlobalVar: *const Value, IsConstant: Bool) void;
+
+ pub const setLinkage = LLVMSetLinkage;
+ extern fn LLVMSetLinkage(Global: *const Value, Linkage: Linkage) void;
+
+ pub const setUnnamedAddr = LLVMSetUnnamedAddr;
+ extern fn LLVMSetUnnamedAddr(Global: *const Value, HasUnnamedAddr: Bool) void;
+
+ pub const deleteGlobal = LLVMDeleteGlobal;
+ extern fn LLVMDeleteGlobal(GlobalVar: *const Value) void;
+
+ pub const getNextGlobalAlias = LLVMGetNextGlobalAlias;
+ extern fn LLVMGetNextGlobalAlias(GA: *const Value) *const Value;
+
+ pub const getAliasee = LLVMAliasGetAliasee;
+ extern fn LLVMAliasGetAliasee(Alias: *const Value) *const Value;
+
+ pub const setAliasee = LLVMAliasSetAliasee;
+ extern fn LLVMAliasSetAliasee(Alias: *const Value, Aliasee: *const Value) void;
};
pub const Type = opaque {
@@ -145,6 +163,27 @@ pub const Module = opaque {
pub const dump = LLVMDumpModule;
extern fn LLVMDumpModule(M: *const Module) void;
+
+ pub const getFirstGlobalAlias = LLVMGetFirstGlobalAlias;
+ extern fn LLVMGetFirstGlobalAlias(M: *const Module) *const Value;
+
+ pub const getLastGlobalAlias = LLVMGetLastGlobalAlias;
+ extern fn LLVMGetLastGlobalAlias(M: *const Module) *const Value;
+
+ pub const addAlias = LLVMAddAlias;
+ extern fn LLVMAddAlias(
+ M: *const Module,
+ Ty: *const Type,
+ Aliasee: *const Value,
+ Name: [*:0]const u8,
+ ) *const Value;
+
+ pub const getNamedGlobalAlias = LLVMGetNamedGlobalAlias;
+ extern fn LLVMGetNamedGlobalAlias(
+ M: *const Module,
+ Name: [*]const u8,
+ NameLen: usize,
+ ) ?*const Value;
};
pub const lookupIntrinsicID = LLVMLookupIntrinsicID;
@@ -252,18 +291,60 @@ pub const Builder = opaque {
pub const buildNot = LLVMBuildNot;
extern fn LLVMBuildNot(*const Builder, V: *const Value, Name: [*:0]const u8) *const Value;
+ pub const buildFAdd = LLVMBuildFAdd;
+ extern fn LLVMBuildFAdd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildAdd = LLVMBuildAdd;
+ extern fn LLVMBuildAdd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
pub const buildNSWAdd = LLVMBuildNSWAdd;
extern fn LLVMBuildNSWAdd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
pub const buildNUWAdd = LLVMBuildNUWAdd;
extern fn LLVMBuildNUWAdd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+ pub const buildFSub = LLVMBuildFSub;
+ extern fn LLVMBuildFSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildSub = LLVMBuildSub;
+ extern fn LLVMBuildSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
pub const buildNSWSub = LLVMBuildNSWSub;
extern fn LLVMBuildNSWSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
pub const buildNUWSub = LLVMBuildNUWSub;
extern fn LLVMBuildNUWSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+ pub const buildFMul = LLVMBuildFMul;
+ extern fn LLVMBuildFMul(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildMul = LLVMBuildMul;
+ extern fn LLVMBuildMul(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildNSWMul = LLVMBuildNSWMul;
+ extern fn LLVMBuildNSWMul(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildNUWMul = LLVMBuildNUWMul;
+ extern fn LLVMBuildNUWMul(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildUDiv = LLVMBuildUDiv;
+ extern fn LLVMBuildUDiv(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildSDiv = LLVMBuildSDiv;
+ extern fn LLVMBuildSDiv(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildFDiv = LLVMBuildFDiv;
+ extern fn LLVMBuildFDiv(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildAnd = LLVMBuildAnd;
+ extern fn LLVMBuildAnd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildOr = LLVMBuildOr;
+ extern fn LLVMBuildOr(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildXor = LLVMBuildXor;
+ extern fn LLVMBuildXor(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
+
pub const buildIntCast2 = LLVMBuildIntCast2;
extern fn LLVMBuildIntCast2(*const Builder, Val: *const Value, DestTy: *const Type, IsSigned: Bool, Name: [*:0]const u8) *const Value;
@@ -279,6 +360,16 @@ pub const Builder = opaque {
Name: [*:0]const u8,
) *const Value;
+ pub const buildInBoundsGEP2 = LLVMBuildInBoundsGEP2;
+ extern fn LLVMBuildInBoundsGEP2(
+ B: *const Builder,
+ Ty: *const Type,
+ Pointer: *const Value,
+ Indices: [*]const *const Value,
+ NumIndices: c_uint,
+ Name: [*:0]const u8,
+ ) *const Value;
+
pub const buildICmp = LLVMBuildICmp;
extern fn LLVMBuildICmp(*const Builder, Op: IntPredicate, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
@@ -292,10 +383,28 @@ pub const Builder = opaque {
extern fn LLVMBuildPhi(*const Builder, Ty: *const Type, Name: [*:0]const u8) *const Value;
pub const buildExtractValue = LLVMBuildExtractValue;
- extern fn LLVMBuildExtractValue(*const Builder, AggVal: *const Value, Index: c_uint, Name: [*:0]const u8) *const Value;
+ extern fn LLVMBuildExtractValue(
+ *const Builder,
+ AggVal: *const Value,
+ Index: c_uint,
+ Name: [*:0]const u8,
+ ) *const Value;
pub const buildPtrToInt = LLVMBuildPtrToInt;
- extern fn LLVMBuildPtrToInt(*const Builder, Val: *const Value, DestTy: *const Type, Name: [*:0]const u8) *const Value;
+ extern fn LLVMBuildPtrToInt(
+ *const Builder,
+ Val: *const Value,
+ DestTy: *const Type,
+ Name: [*:0]const u8,
+ ) *const Value;
+
+ pub const buildStructGEP = LLVMBuildStructGEP;
+ extern fn LLVMBuildStructGEP(
+ B: *const Builder,
+ Pointer: *const Value,
+ Idx: c_uint,
+ Name: [*:0]const u8,
+ ) *const Value;
};
pub const IntPredicate = enum(c_int) {
@@ -715,3 +824,23 @@ extern fn ZigLLVMWriteImportLibrary(
output_lib_path: [*c]const u8,
kill_at: bool,
) bool;
+
+pub const Linkage = enum(c_uint) {
+ External,
+ AvailableExternally,
+ LinkOnceAny,
+ LinkOnceODR,
+ LinkOnceODRAutoHide,
+ WeakAny,
+ WeakODR,
+ Appending,
+ Internal,
+ Private,
+ DLLImport,
+ DLLExport,
+ ExternalWeak,
+ Ghost,
+ Common,
+ LinkerPrivate,
+ LinkerPrivateWeak,
+};
diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig
index ca0d53988d..bf9010fbff 100644
--- a/src/codegen/wasm.zig
+++ b/src/codegen/wasm.zig
@@ -1306,7 +1306,7 @@ pub const Context = struct {
fn airStructFieldPtr(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const extra = self.air.extraData(Air.StructField, ty_pl.payload);
- const struct_ptr = self.resolveInst(extra.data.struct_ptr);
+ const struct_ptr = self.resolveInst(extra.data.struct_operand);
return WValue{ .local = struct_ptr.multi_value.index + @intCast(u32, extra.data.field_index) };
}
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index 0bae2cc6cc..0c9e513742 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -777,8 +777,18 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
self.offset_table_free_list.append(self.base.allocator, decl.link.coff.offset_table_index) catch {};
}
-pub fn updateDeclExports(self: *Coff, module: *Module, decl: *Module.Decl, exports: []const *Module.Export) !void {
- if (self.llvm_object) |_| return;
+pub fn updateDeclExports(
+ self: *Coff,
+ module: *Module,
+ decl: *Module.Decl,
+ exports: []const *Module.Export,
+) !void {
+ if (build_options.skip_non_native and builtin.object_format != .coff) {
+ @panic("Attempted to compile for object format that was disabled by build configuration");
+ }
+ if (build_options.have_llvm) {
+ if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports);
+ }
for (exports) |exp| {
if (exp.options.section) |section_name| {
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index c95af23026..502575f3c8 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -2716,7 +2716,12 @@ pub fn updateDeclExports(
decl: *Module.Decl,
exports: []const *Module.Export,
) !void {
- if (self.llvm_object) |_| return;
+ if (build_options.skip_non_native and builtin.object_format != .elf) {
+ @panic("Attempted to compile for object format that was disabled by build configuration");
+ }
+ if (build_options.have_llvm) {
+ if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports);
+ }
const tracy = trace(@src());
defer tracy.end();
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 21f4e9c33c..1f2e0616ba 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -3785,6 +3785,12 @@ pub fn updateDeclExports(
decl: *Module.Decl,
exports: []const *Module.Export,
) !void {
+ if (build_options.skip_non_native and builtin.object_format != .macho) {
+ @panic("Attempted to compile for object format that was disabled by build configuration");
+ }
+ if (build_options.have_llvm) {
+ if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports);
+ }
const tracy = trace(@src());
defer tracy.end();
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index 2ed6576033..23d0543494 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -330,10 +330,12 @@ pub fn updateDeclExports(
decl: *const Module.Decl,
exports: []const *Module.Export,
) !void {
- _ = self;
- _ = module;
- _ = decl;
- _ = exports;
+ if (build_options.skip_non_native and builtin.object_format != .wasm) {
+ @panic("Attempted to compile for object format that was disabled by build configuration");
+ }
+ if (build_options.have_llvm) {
+ if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports);
+ }
}
pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
diff --git a/src/print_air.zig b/src/print_air.zig
index 2c756670ad..c20a6995e5 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -171,7 +171,8 @@ const Writer = struct {
.loop,
=> try w.writeBlock(s, inst),
- .struct_field_ptr => try w.writeStructFieldPtr(s, inst),
+ .struct_field_ptr => try w.writeStructField(s, inst),
+ .struct_field_val => try w.writeStructField(s, inst),
.varptr => try w.writeVarPtr(s, inst),
.constant => try w.writeConstant(s, inst),
.assembly => try w.writeAssembly(s, inst),
@@ -233,11 +234,11 @@ const Writer = struct {
try s.writeAll("}");
}
- fn writeStructFieldPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
+ fn writeStructField(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
const extra = w.air.extraData(Air.StructField, ty_pl.payload);
- try w.writeOperand(s, inst, 0, extra.data.struct_ptr);
+ try w.writeOperand(s, inst, 0, extra.data.struct_operand);
try s.print(", {d}", .{extra.data.field_index});
}
From ba71b96fe6c0e01b8445a2f7bd49541a07c360db Mon Sep 17 00:00:00 2001
From: Jarred Sumner
Date: Mon, 26 Jul 2021 18:42:28 -0700
Subject: [PATCH 04/96] Add zld.id to list of files to skip
---
lib/std/build.zig | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/std/build.zig b/lib/std/build.zig
index 36a71d5061..cf592f2016 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -2802,6 +2802,7 @@ pub const LibExeObjStep = struct {
mem.eql(u8, entry.name, "llvm-ar.id") or
mem.eql(u8, entry.name, "libs.txt") or
mem.eql(u8, entry.name, "builtin.zig") or
+ mem.eql(u8, entry.name, "zld.id") or
mem.eql(u8, entry.name, "lld.id")) continue;
_ = try src_dir.updateFile(entry.name, dest_dir, entry.name, .{});
From a8e964eadd3496330043985cacaaee7db92886c6 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 27 Jul 2021 14:06:42 -0700
Subject: [PATCH 05/96] stage2: `zig test` now works with the LLVM backend
Frontend improvements:
* When compiling in `zig test` mode, put a task on the work queue to
analyze the main package root file. Normally, start code does
`_ = import("root");` to make Zig analyze the user's code, however in
the case of `zig test`, the root source file is the test runner.
Without this change, no tests are picked up.
* In the main pipeline, once semantic analysis is finished, if there
are no compile errors, populate the `test_functions` Decl with the
set of test functions picked up from semantic analysis.
* Value: add `array` and `slice` Tags.
LLVM backend improvements:
* Fix incremental updates of globals. Previously the
value of a global would not get replaced with a new value.
* Fix LLVM type of arrays. They were incorrectly sending
the ABI size as the element count.
* Remove the FuncGen parameter from genTypedValue. This function is for
generating global constants and there is no function available when
it is being called.
- The `ref_val` case is now commented out. I'd like to eliminate
`ref_val` as one of the possible Value Tags. Instead it should
always be done via `decl_ref`.
* Implement constant value generation for slices, arrays, and structs.
* Constant value generation for functions supports the `decl_ref` tag.
---
src/Compilation.zig | 34 ++++-----
src/Module.zig | 135 ++++++++++++++++++++++++++++++----
src/codegen/llvm.zig | 134 ++++++++++++++++++++++-----------
src/codegen/llvm/bindings.zig | 16 +++-
src/type.zig | 22 ++++++
src/value.zig | 73 ++++++++++++++++--
6 files changed, 332 insertions(+), 82 deletions(-)
diff --git a/src/Compilation.zig b/src/Compilation.zig
index a34d0cd198..00cdba85a4 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1709,7 +1709,9 @@ pub fn update(self: *Compilation) !void {
// in the start code, but when using the stage1 backend that won't happen,
// so in order to run AstGen on the root source file we put it into the
// import_table here.
- if (use_stage1) {
+ // Likewise, in the case of `zig test`, the test runner is the root source file,
+ // and so there is nothing to import the main file.
+ if (use_stage1 or self.bin_file.options.is_test) {
_ = try module.importPkg(module.main_pkg);
}
@@ -1725,6 +1727,9 @@ pub fn update(self: *Compilation) !void {
if (!use_stage1) {
try self.work_queue.writeItem(.{ .analyze_pkg = std_pkg });
+ if (self.bin_file.options.is_test) {
+ try self.work_queue.writeItem(.{ .analyze_pkg = module.main_pkg });
+ }
}
}
@@ -2053,24 +2058,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
assert(decl.has_tv);
assert(decl.ty.hasCodeGenBits());
- self.bin_file.updateDecl(module, decl) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.AnalysisFail => {
- decl.analysis = .codegen_failure;
- continue;
- },
- else => {
- try module.failed_decls.ensureUnusedCapacity(gpa, 1);
- module.failed_decls.putAssumeCapacityNoClobber(decl, try Module.ErrorMsg.create(
- gpa,
- decl.srcLoc(),
- "unable to codegen: {s}",
- .{@errorName(err)},
- ));
- decl.analysis = .codegen_failure_retryable;
- continue;
- },
- };
+ try module.linkerUpdateDecl(decl);
},
},
.codegen_func => |func| switch (func.owner_decl.analysis) {
@@ -2396,6 +2384,14 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
};
},
};
+
+ if (self.bin_file.options.is_test and self.totalErrorCount() == 0) {
+ // The `test_functions` decl has been intentionally postponed until now,
+ // at which point we must populate it with the list of test functions that
+ // have been discovered and not filtered out.
+ const mod = self.bin_file.options.module.?;
+ try mod.populateTestFunctions();
+ }
}
const AstGenSrc = union(enum) {
diff --git a/src/Module.zig b/src/Module.zig
index 99f314c5cb..4ddce33655 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -112,6 +112,8 @@ compile_log_text: ArrayListUnmanaged(u8) = .{},
emit_h: ?*GlobalEmitH,
+test_functions: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
+
/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
pub const GlobalEmitH = struct {
/// Where to put the output.
@@ -282,6 +284,7 @@ pub const Decl = struct {
pub fn destroy(decl: *Decl, module: *Module) void {
const gpa = module.gpa;
log.debug("destroy {*} ({s})", .{ decl, decl.name });
+ _ = module.test_functions.swapRemove(decl);
if (decl.deletion_flag) {
assert(module.deletion_set.swapRemove(decl));
}
@@ -3319,6 +3322,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi
// the test name filter.
if (!mod.comp.bin_file.options.is_test) break :blk false;
if (decl_pkg != mod.main_pkg) break :blk false;
+ try mod.test_functions.put(gpa, new_decl, {});
break :blk true;
},
else => blk: {
@@ -3326,6 +3330,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi
if (!mod.comp.bin_file.options.is_test) break :blk false;
if (decl_pkg != mod.main_pkg) break :blk false;
// TODO check the name against --test-filter
+ try mod.test_functions.put(gpa, new_decl, {});
break :blk true;
},
};
@@ -3765,17 +3770,38 @@ pub fn createAnonymousDeclNamed(
scope: *Scope,
typed_value: TypedValue,
name: [:0]u8,
+) !*Decl {
+ return mod.createAnonymousDeclFromDeclNamed(scope.ownerDecl().?, typed_value, name);
+}
+
+pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {
+ return mod.createAnonymousDeclFromDecl(scope.ownerDecl().?, typed_value);
+}
+
+pub fn createAnonymousDeclFromDecl(mod: *Module, owner_decl: *Decl, tv: TypedValue) !*Decl {
+ const name_index = mod.getNextAnonNameIndex();
+ const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{
+ owner_decl.name, name_index,
+ });
+ return mod.createAnonymousDeclFromDeclNamed(owner_decl, tv, name);
+}
+
+/// Takes ownership of `name` even if it returns an error.
+pub fn createAnonymousDeclFromDeclNamed(
+ mod: *Module,
+ owner_decl: *Decl,
+ typed_value: TypedValue,
+ name: [:0]u8,
) !*Decl {
errdefer mod.gpa.free(name);
- const scope_decl = scope.ownerDecl().?;
- const namespace = scope_decl.namespace;
+ const namespace = owner_decl.namespace;
try namespace.anon_decls.ensureUnusedCapacity(mod.gpa, 1);
- const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
+ const new_decl = try mod.allocateNewDecl(namespace, owner_decl.src_node);
new_decl.name = name;
- new_decl.src_line = scope_decl.src_line;
+ new_decl.src_line = owner_decl.src_line;
new_decl.ty = typed_value.ty;
new_decl.val = typed_value.val;
new_decl.has_tv = true;
@@ -3796,15 +3822,6 @@ pub fn createAnonymousDeclNamed(
return new_decl;
}
-pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {
- const scope_decl = scope.ownerDecl().?;
- const name_index = mod.getNextAnonNameIndex();
- const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{
- scope_decl.name, name_index,
- });
- return mod.createAnonymousDeclNamed(scope, typed_value, name);
-}
-
pub fn getNextAnonNameIndex(mod: *Module) usize {
return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic);
}
@@ -4801,3 +4818,95 @@ pub fn processExports(mod: *Module) !void {
};
}
}
+
+pub fn populateTestFunctions(mod: *Module) !void {
+ const gpa = mod.gpa;
+ const builtin_pkg = mod.main_pkg.table.get("builtin").?;
+ const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file;
+ const builtin_namespace = builtin_file.root_decl.?.namespace;
+ const decl = builtin_namespace.decls.get("test_functions").?;
+ var buf: Type.Payload.ElemType = undefined;
+ const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType();
+
+ const array_decl = d: {
+ // Add mod.test_functions to an array decl then make the test_functions
+ // decl reference it as a slice.
+ var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
+ errdefer new_decl_arena.deinit();
+ const arena = &new_decl_arena.allocator;
+
+ const test_fn_vals = try arena.alloc(Value, mod.test_functions.count());
+ const array_decl = try mod.createAnonymousDeclFromDecl(decl, .{
+ .ty = try Type.Tag.array.create(arena, .{
+ .len = test_fn_vals.len,
+ .elem_type = try tmp_test_fn_ty.copy(arena),
+ }),
+ .val = try Value.Tag.array.create(arena, test_fn_vals),
+ });
+ for (mod.test_functions.keys()) |test_decl, i| {
+ const test_name_slice = mem.sliceTo(test_decl.name, 0);
+ const test_name_decl = n: {
+ var name_decl_arena = std.heap.ArenaAllocator.init(gpa);
+ errdefer name_decl_arena.deinit();
+ const bytes = try name_decl_arena.allocator.dupe(u8, test_name_slice);
+ const test_name_decl = try mod.createAnonymousDeclFromDecl(array_decl, .{
+ .ty = try Type.Tag.array_u8.create(&name_decl_arena.allocator, bytes.len),
+ .val = try Value.Tag.bytes.create(&name_decl_arena.allocator, bytes),
+ });
+ try test_name_decl.finalizeNewArena(&name_decl_arena);
+ break :n test_name_decl;
+ };
+ try mod.linkerUpdateDecl(test_name_decl);
+
+ const field_vals = try arena.create([3]Value);
+ field_vals.* = .{
+ try Value.Tag.slice.create(arena, .{
+ .ptr = try Value.Tag.decl_ref.create(arena, test_name_decl),
+ .len = try Value.Tag.int_u64.create(arena, test_name_slice.len),
+ }), // name
+ try Value.Tag.decl_ref.create(arena, test_decl), // func
+ Value.initTag(.null_value), // async_frame_size
+ };
+ test_fn_vals[i] = try Value.Tag.@"struct".create(arena, field_vals);
+ }
+
+ try array_decl.finalizeNewArena(&new_decl_arena);
+ break :d array_decl;
+ };
+ try mod.linkerUpdateDecl(array_decl);
+
+ {
+ var arena_instance = decl.value_arena.?.promote(gpa);
+ defer decl.value_arena.?.* = arena_instance.state;
+ const arena = &arena_instance.allocator;
+
+ decl.ty = try Type.Tag.const_slice.create(arena, try tmp_test_fn_ty.copy(arena));
+ decl.val = try Value.Tag.slice.create(arena, .{
+ .ptr = try Value.Tag.decl_ref.create(arena, array_decl),
+ .len = try Value.Tag.int_u64.create(arena, mod.test_functions.count()),
+ });
+ }
+ try mod.linkerUpdateDecl(decl);
+}
+
+pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void {
+ mod.comp.bin_file.updateDecl(mod, decl) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.AnalysisFail => {
+ decl.analysis = .codegen_failure;
+ return;
+ },
+ else => {
+ const gpa = mod.gpa;
+ try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
+ mod.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
+ gpa,
+ decl.srcLoc(),
+ "unable to codegen: {s}",
+ .{@errorName(err)},
+ ));
+ decl.analysis = .codegen_failure_retryable;
+ return;
+ },
+ };
+}
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 1b3c36fc69..2468b1dbde 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -500,7 +500,18 @@ pub const DeclGen = struct {
} else if (decl.val.castTag(.extern_fn)) |extern_fn| {
_ = try self.resolveLlvmFunction(extern_fn.data);
} else {
- _ = try self.resolveGlobalDecl(decl);
+ const global = try self.resolveGlobalDecl(decl);
+ assert(decl.has_tv);
+ const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
+ const variable = payload.data;
+ break :init_val variable.init;
+ } else init_val: {
+ global.setGlobalConstant(.True);
+ break :init_val decl.val;
+ };
+
+ const llvm_init = try self.genTypedValue(.{ .ty = decl.ty, .val = init_val });
+ llvm.setInitializer(global, llvm_init);
}
}
@@ -548,25 +559,11 @@ pub const DeclGen = struct {
}
fn resolveGlobalDecl(self: *DeclGen, decl: *Module.Decl) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
- if (self.llvmModule().getNamedGlobal(decl.name)) |val| return val;
-
- assert(decl.has_tv);
-
+ const llvm_module = self.object.llvm_module;
+ if (llvm_module.getNamedGlobal(decl.name)) |val| return val;
// TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`.
const llvm_type = try self.llvmType(decl.ty);
- const global = self.llvmModule().addGlobal(llvm_type, decl.name);
- const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
- const variable = payload.data;
- break :init_val variable.init;
- } else init_val: {
- global.setGlobalConstant(.True);
- break :init_val decl.val;
- };
-
- const llvm_init = try self.genTypedValue(.{ .ty = decl.ty, .val = init_val }, null);
- llvm.setInitializer(global, llvm_init);
-
- return global;
+ return llvm_module.addGlobal(llvm_type, decl.name);
}
fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type {
@@ -596,7 +593,8 @@ pub const DeclGen = struct {
},
.Array => {
const elem_type = try self.llvmType(t.elemType());
- return elem_type.arrayType(@intCast(c_uint, t.abiSize(self.module.getTarget())));
+ const total_len = t.arrayLen() + @boolToInt(t.sentinel() != null);
+ return elem_type.arrayType(@intCast(c_uint, total_len));
},
.Optional => {
if (!t.isPtrLikeOptional()) {
@@ -674,8 +672,7 @@ pub const DeclGen = struct {
}
}
- // TODO: figure out a way to remove the FuncGen argument
- fn genTypedValue(self: *DeclGen, tv: TypedValue, fg: ?*FuncGen) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
+ fn genTypedValue(self: *DeclGen, tv: TypedValue) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
const llvm_type = try self.llvmType(tv.ty);
if (tv.val.isUndef())
@@ -711,20 +708,36 @@ pub const DeclGen = struct {
usize_type.constNull(),
};
- // TODO: consider using buildInBoundsGEP2 for opaque pointers
- return fg.?.builder.buildInBoundsGEP(val, &indices, 2, "");
+ return val.constInBoundsGEP(&indices, indices.len);
},
.ref_val => {
- const elem_value = tv.val.castTag(.ref_val).?.data;
- const elem_type = tv.ty.castPointer().?.data;
- const alloca = fg.?.buildAlloca(try self.llvmType(elem_type));
- _ = fg.?.builder.buildStore(try self.genTypedValue(.{ .ty = elem_type, .val = elem_value }, fg), alloca);
- return alloca;
+ //const elem_value = tv.val.castTag(.ref_val).?.data;
+ //const elem_type = tv.ty.castPointer().?.data;
+ //const alloca = fg.?.buildAlloca(try self.llvmType(elem_type));
+ //_ = fg.?.builder.buildStore(try self.genTypedValue(.{ .ty = elem_type, .val = elem_value }, fg), alloca);
+ //return alloca;
+ // TODO eliminate the ref_val Value Tag
+ return self.todo("implement const of pointer tag ref_val", .{});
},
.variable => {
const variable = tv.val.castTag(.variable).?.data;
return self.resolveGlobalDecl(variable.owner_decl);
},
+ .slice => {
+ const slice = tv.val.castTag(.slice).?.data;
+ var buf: Type.Payload.ElemType = undefined;
+ const fields: [2]*const llvm.Value = .{
+ try self.genTypedValue(.{
+ .ty = tv.ty.slicePtrFieldType(&buf),
+ .val = slice.ptr,
+ }),
+ try self.genTypedValue(.{
+ .ty = Type.initTag(.usize),
+ .val = slice.len,
+ }),
+ };
+ return self.context.constStruct(&fields, fields.len, .False);
+ },
else => |tag| return self.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }),
},
.Array => {
@@ -734,10 +747,28 @@ pub const DeclGen = struct {
return self.todo("handle other sentinel values", .{});
} else false;
- return self.context.constString(payload.data.ptr, @intCast(c_uint, payload.data.len), llvm.Bool.fromBool(!zero_sentinel));
- } else {
- return self.todo("handle more array values", .{});
+ return self.context.constString(
+ payload.data.ptr,
+ @intCast(c_uint, payload.data.len),
+ llvm.Bool.fromBool(!zero_sentinel),
+ );
}
+ if (tv.val.castTag(.array)) |payload| {
+ const gpa = self.gpa;
+ const elem_ty = tv.ty.elemType();
+ const elem_vals = payload.data;
+ const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len);
+ defer gpa.free(llvm_elems);
+ for (elem_vals) |elem_val, i| {
+ llvm_elems[i] = try self.genTypedValue(.{ .ty = elem_ty, .val = elem_val });
+ }
+ const llvm_elem_ty = try self.llvmType(elem_ty);
+ return llvm_elem_ty.constArray(
+ llvm_elems.ptr,
+ @intCast(c_uint, llvm_elems.len),
+ );
+ }
+ return self.todo("handle more array values", .{});
},
.Optional => {
if (!tv.ty.isPtrLikeOptional()) {
@@ -750,26 +781,25 @@ pub const DeclGen = struct {
llvm_child_type.constNull(),
self.context.intType(1).constNull(),
};
- return self.context.constStruct(&optional_values, 2, .False);
+ return self.context.constStruct(&optional_values, optional_values.len, .False);
} else {
var optional_values: [2]*const llvm.Value = .{
- try self.genTypedValue(.{ .ty = child_type, .val = tv.val }, fg),
+ try self.genTypedValue(.{ .ty = child_type, .val = tv.val }),
self.context.intType(1).constAllOnes(),
};
- return self.context.constStruct(&optional_values, 2, .False);
+ return self.context.constStruct(&optional_values, optional_values.len, .False);
}
} else {
return self.todo("implement const of optional pointer", .{});
}
},
.Fn => {
- const fn_decl = if (tv.val.castTag(.extern_fn)) |extern_fn|
- extern_fn.data
- else if (tv.val.castTag(.function)) |func_payload|
- func_payload.data.owner_decl
- else
- unreachable;
-
+ const fn_decl = switch (tv.val.tag()) {
+ .extern_fn => tv.val.castTag(.extern_fn).?.data,
+ .function => tv.val.castTag(.function).?.data.owner_decl,
+ .decl_ref => tv.val.castTag(.decl_ref).?.data,
+ else => unreachable,
+ };
return self.resolveLlvmFunction(fn_decl);
},
.ErrorSet => {
@@ -793,11 +823,29 @@ pub const DeclGen = struct {
if (!payload_type.hasCodeGenBits()) {
// We use the error type directly as the type.
- return self.genTypedValue(.{ .ty = error_type, .val = sub_val }, fg);
+ return self.genTypedValue(.{ .ty = error_type, .val = sub_val });
}
return self.todo("implement error union const of type '{}'", .{tv.ty});
},
+ .Struct => {
+ const fields_len = tv.ty.structFieldCount();
+ const field_vals = tv.val.castTag(.@"struct").?.data;
+ const gpa = self.gpa;
+ const llvm_fields = try gpa.alloc(*const llvm.Value, fields_len);
+ defer gpa.free(llvm_fields);
+ for (llvm_fields) |*llvm_field, i| {
+ llvm_field.* = try self.genTypedValue(.{
+ .ty = tv.ty.structFieldType(i),
+ .val = field_vals[i],
+ });
+ }
+ return self.context.constStruct(
+ llvm_fields.ptr,
+ @intCast(c_uint, llvm_fields.len),
+ .False,
+ );
+ },
else => return self.todo("implement const of type '{}'", .{tv.ty}),
}
}
@@ -869,7 +917,7 @@ pub const FuncGen = struct {
fn resolveInst(self: *FuncGen, inst: Air.Inst.Ref) !*const llvm.Value {
if (self.air.value(inst)) |val| {
- return self.dg.genTypedValue(.{ .ty = self.air.typeOf(inst), .val = val }, self);
+ return self.dg.genTypedValue(.{ .ty = self.air.typeOf(inst), .val = val });
}
const inst_index = Air.refToIndex(inst).?;
if (self.func_inst_table.get(inst_index)) |value| return value;
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index 9ef6d7e1ac..d63a75d8bd 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -49,7 +49,12 @@ pub const Context = opaque {
extern fn LLVMConstStringInContext(C: *const Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) *const Value;
pub const constStruct = LLVMConstStructInContext;
- extern fn LLVMConstStructInContext(C: *const Context, ConstantVals: [*]*const Value, Count: c_uint, Packed: Bool) *const Value;
+ extern fn LLVMConstStructInContext(
+ C: *const Context,
+ ConstantVals: [*]const *const Value,
+ Count: c_uint,
+ Packed: Bool,
+ ) *const Value;
pub const createBasicBlock = LLVMCreateBasicBlockInContext;
extern fn LLVMCreateBasicBlockInContext(C: *const Context, Name: [*:0]const u8) *const BasicBlock;
@@ -100,6 +105,13 @@ pub const Value = opaque {
pub const setAliasee = LLVMAliasSetAliasee;
extern fn LLVMAliasSetAliasee(Alias: *const Value, Aliasee: *const Value) void;
+
+ pub const constInBoundsGEP = LLVMConstInBoundsGEP;
+ extern fn LLVMConstInBoundsGEP(
+ ConstantVal: *const Value,
+ ConstantIndices: [*]const *const Value,
+ NumIndices: c_uint,
+ ) *const Value;
};
pub const Type = opaque {
@@ -113,7 +125,7 @@ pub const Type = opaque {
extern fn LLVMConstInt(IntTy: *const Type, N: c_ulonglong, SignExtend: Bool) *const Value;
pub const constArray = LLVMConstArray;
- extern fn LLVMConstArray(ElementTy: *const Type, ConstantVals: ?[*]*const Value, Length: c_uint) *const Value;
+ extern fn LLVMConstArray(ElementTy: *const Type, ConstantVals: [*]*const Value, Length: c_uint) *const Value;
pub const getUndef = LLVMGetUndef;
extern fn LLVMGetUndef(Ty: *const Type) *const Value;
diff --git a/src/type.zig b/src/type.zig
index 731c69b806..4dd1a15fdd 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -1526,6 +1526,8 @@ pub const Type = extern union {
.var_args_param => unreachable,
.@"struct" => {
+ const s = self.castTag(.@"struct").?.data;
+ assert(s.status == .have_layout);
@panic("TODO abiSize struct");
},
.enum_simple, .enum_full, .enum_nonexhaustive => {
@@ -2768,6 +2770,26 @@ pub const Type = extern union {
}
}
+ pub fn structFieldCount(ty: Type) usize {
+ switch (ty.tag()) {
+ .@"struct" => {
+ const struct_obj = ty.castTag(.@"struct").?.data;
+ return struct_obj.fields.count();
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn structFieldType(ty: Type, index: usize) Type {
+ switch (ty.tag()) {
+ .@"struct" => {
+ const struct_obj = ty.castTag(.@"struct").?.data;
+ return struct_obj.fields.values()[index].ty;
+ },
+ else => unreachable,
+ }
+ }
+
pub fn declSrcLoc(ty: Type) Module.SrcLoc {
switch (ty.tag()) {
.enum_full, .enum_nonexhaustive => {
diff --git a/src/value.zig b/src/value.zig
index abb2ea7b1e..fc34473921 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -112,6 +112,10 @@ pub const Value = extern union {
/// This value is repeated some number of times. The amount of times to repeat
/// is stored externally.
repeated,
+ /// Each element stored as a `Value`.
+ array,
+ /// Pointer and length as sub `Value` objects.
+ slice,
float_16,
float_32,
float_64,
@@ -217,6 +221,9 @@ pub const Value = extern union {
.enum_literal,
=> Payload.Bytes,
+ .array => Payload.Array,
+ .slice => Payload.Slice,
+
.enum_field_index => Payload.U32,
.ty => Payload.Ty,
@@ -442,6 +449,28 @@ pub const Value = extern union {
};
return Value{ .ptr_otherwise = &new_payload.base };
},
+ .array => {
+ const payload = self.castTag(.array).?;
+ const new_payload = try allocator.create(Payload.Array);
+ new_payload.* = .{
+ .base = payload.base,
+ .data = try allocator.alloc(Value, payload.data.len),
+ };
+ std.mem.copy(Value, new_payload.data, payload.data);
+ return Value{ .ptr_otherwise = &new_payload.base };
+ },
+ .slice => {
+ const payload = self.castTag(.slice).?;
+ const new_payload = try allocator.create(Payload.Slice);
+ new_payload.* = .{
+ .base = payload.base,
+ .data = .{
+ .ptr = try payload.data.ptr.copy(allocator),
+ .len = try payload.data.len.copy(allocator),
+ },
+ };
+ return Value{ .ptr_otherwise = &new_payload.base };
+ },
.float_16 => return self.copyPayloadShallow(allocator, Payload.Float_16),
.float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32),
.float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),
@@ -605,6 +634,8 @@ pub const Value = extern union {
try out_stream.writeAll("(repeated) ");
val = val.castTag(.repeated).?.data;
},
+ .array => return out_stream.writeAll("(array)"),
+ .slice => return out_stream.writeAll("(slice)"),
.float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}),
.float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),
.float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),
@@ -729,6 +760,8 @@ pub const Value = extern union {
.field_ptr,
.bytes,
.repeated,
+ .array,
+ .slice,
.float_16,
.float_32,
.float_64,
@@ -1075,6 +1108,8 @@ pub const Value = extern union {
return orderAgainstZero(lhs).compare(op);
}
+ /// TODO we can't compare value equality without also knowing the type to treat
+ /// the values as
pub fn eql(a: Value, b: Value) bool {
const a_tag = a.tag();
const b_tag = b.tag();
@@ -1109,6 +1144,8 @@ pub const Value = extern union {
return @truncate(u32, self.hash());
}
+ /// TODO we can't hash without also knowing the type of the value.
+ /// we have to hash as if there were a canonical value memory layout.
pub fn hash(self: Value) u64 {
var hasher = std.hash.Wyhash.init(0);
@@ -1203,6 +1240,15 @@ pub const Value = extern union {
const payload = self.castTag(.bytes).?;
hasher.update(payload.data);
},
+ .repeated => {
+ @panic("TODO Value.hash for repeated");
+ },
+ .array => {
+ @panic("TODO Value.hash for array");
+ },
+ .slice => {
+ @panic("TODO Value.hash for slice");
+ },
.int_u64 => {
const payload = self.castTag(.int_u64).?;
std.hash.autoHash(&hasher, payload.data);
@@ -1211,10 +1257,6 @@ pub const Value = extern union {
const payload = self.castTag(.int_i64).?;
std.hash.autoHash(&hasher, payload.data);
},
- .repeated => {
- const payload = self.castTag(.repeated).?;
- std.hash.autoHash(&hasher, payload.data.hash());
- },
.ref_val => {
const payload = self.castTag(.ref_val).?;
std.hash.autoHash(&hasher, payload.data.hash());
@@ -1340,6 +1382,8 @@ pub const Value = extern union {
return switch (val.tag()) {
.empty_array => 0,
.bytes => val.castTag(.bytes).?.data.len,
+ .array => val.castTag(.array).?.data.len,
+ .slice => val.castTag(.slice).?.data.len.toUnsignedInt(),
.ref_val => sliceLen(val.castTag(.ref_val).?.data),
.decl_ref => {
const decl = val.castTag(.decl_ref).?.data;
@@ -1364,6 +1408,9 @@ pub const Value = extern union {
// No matter the index; all the elements are the same!
.repeated => return self.castTag(.repeated).?.data,
+ .array => return self.castTag(.array).?.data[index],
+ .slice => return self.castTag(.slice).?.data.ptr.elemValue(allocator, index),
+
else => unreachable,
}
}
@@ -1450,7 +1497,8 @@ pub const Value = extern union {
}
/// Valid for all types. Asserts the value is not undefined.
- pub fn isType(self: Value) bool {
+ /// TODO this function is a code smell and should be deleted
+ fn isType(self: Value) bool {
return switch (self.tag()) {
.ty,
.int_type,
@@ -1528,6 +1576,8 @@ pub const Value = extern union {
.field_ptr,
.bytes,
.repeated,
+ .array,
+ .slice,
.float_16,
.float_32,
.float_64,
@@ -1638,6 +1688,19 @@ pub const Value = extern union {
data: []const u8,
};
+ pub const Array = struct {
+ base: Payload,
+ data: []Value,
+ };
+
+ pub const Slice = struct {
+ base: Payload,
+ data: struct {
+ ptr: Value,
+ len: Value,
+ },
+ };
+
pub const Ty = struct {
base: Payload,
data: Type,
From 1eeafc39675a349c912910da2a1b70097a934d57 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 27 Jul 2021 15:10:49 -0700
Subject: [PATCH 06/96] stage2: move call to populateTestFunctions() outside
performAllTheWork()
Before calling populateTestFunctions() we want to check
totalErrorCount() but that will read from some tables that might get
populated by the thread pool for C compilation tasks. So we wait until
all those tasks are finished before proceeding.
---
src/Compilation.zig | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 00cdba85a4..8672a346c3 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1737,6 +1737,13 @@ pub fn update(self: *Compilation) !void {
if (!use_stage1) {
if (self.bin_file.options.module) |module| {
+ if (self.bin_file.options.is_test and self.totalErrorCount() == 0) {
+ // The `test_functions` decl has been intentionally postponed until now,
+ // at which point we must populate it with the list of test functions that
+ // have been discovered and not filtered out.
+ try module.populateTestFunctions();
+ }
+
// Process the deletion set. We use a while loop here because the
// deletion set may grow as we call `clearDecl` within this loop,
// and more unreferenced Decls are revealed.
@@ -2384,14 +2391,6 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
};
},
};
-
- if (self.bin_file.options.is_test and self.totalErrorCount() == 0) {
- // The `test_functions` decl has been intentionally postponed until now,
- // at which point we must populate it with the list of test functions that
- // have been discovered and not filtered out.
- const mod = self.bin_file.options.module.?;
- try mod.populateTestFunctions();
- }
}
const AstGenSrc = union(enum) {
From a2eb91c42294ef380d70742e1111e4dc36ab2192 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 27 Jul 2021 15:44:21 -0700
Subject: [PATCH 07/96] stage2: add deinit for test_functions
---
src/Module.zig | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Module.zig b/src/Module.zig
index 4ddce33655..48c2eb8d0d 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -2123,6 +2123,7 @@ pub fn deinit(mod: *Module) void {
mod.global_error_set.deinit(gpa);
mod.error_name_list.deinit(gpa);
+ mod.test_functions.deinit(gpa);
}
fn freeExportList(gpa: *Allocator, export_list: []*Export) void {
From 66e5920dc3411daa4f0c84a8f4c733c1263e8523 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 27 Jul 2021 15:47:25 -0700
Subject: [PATCH 08/96] llvm backend: LLVMGetNamedGlobalAlias requires a null
terminated string
---
src/codegen/llvm.zig | 8 ++++----
src/codegen/llvm/bindings.zig | 5 ++++-
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 2468b1dbde..74a51e6634 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -454,12 +454,12 @@ pub const Object = struct {
// Until then we iterate over existing aliases and make them point
// to the correct decl, or otherwise add a new alias. Old aliases are leaked.
for (exports) |exp| {
- if (self.llvm_module.getNamedGlobalAlias(exp.options.name.ptr, exp.options.name.len)) |alias| {
+ const exp_name_z = try module.gpa.dupeZ(u8, exp.options.name);
+ defer module.gpa.free(exp_name_z);
+
+ if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| {
alias.setAliasee(llvm_fn);
} else {
- const exp_name_z = try module.gpa.dupeZ(u8, exp.options.name);
- defer module.gpa.free(exp_name_z);
-
const alias = self.llvm_module.addAlias(llvm_fn.typeOf(), llvm_fn, exp_name_z);
_ = alias;
}
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index d63a75d8bd..6d09d69447 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -193,7 +193,10 @@ pub const Module = opaque {
pub const getNamedGlobalAlias = LLVMGetNamedGlobalAlias;
extern fn LLVMGetNamedGlobalAlias(
M: *const Module,
- Name: [*]const u8,
+ /// Empirically, LLVM will call strlen() on `Name` and so it
+ /// must be both null terminated and also have `NameLen` set
+ /// to the size.
+ Name: [*:0]const u8,
NameLen: usize,
) ?*const Value;
};
From dc88864c9742029c2980fc16cd2c9e6f04ff3568 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 27 Jul 2021 17:08:37 -0700
Subject: [PATCH 09/96] stage2: implement `@boolToInt`
This is the first commit in which some behavior tests are passing for
both stage1 and stage2.
---
doc/langref.html.in | 4 ++--
src/Air.zig | 6 ++++++
src/AstGen.zig | 2 ++
src/Liveness.zig | 1 +
src/Sema.zig | 11 +++++++++--
src/Zir.zig | 5 +++++
src/codegen.zig | 8 ++++++++
src/codegen/c.zig | 15 +++++++++++++++
src/codegen/llvm.zig | 10 ++++++++++
src/link/Coff.zig | 7 +++++--
src/link/Elf.zig | 7 ++++---
src/print_air.zig | 1 +
src/type.zig | 17 +++++++++++++++--
src/value.zig | 7 +++++++
test/behavior.zig | 7 ++-----
15 files changed, 92 insertions(+), 16 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 38b91468e2..4efa7d0e3c 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -7165,8 +7165,8 @@ fn func(y: *i32) void {
{#header_open|@boolToInt#}
{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}
- Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to
- {#syntax#}u1(0){#endsyntax#}.
+ Converts {#syntax#}true{#endsyntax#} to {#syntax#}@as(u1, 1){#endsyntax#} and {#syntax#}false{#endsyntax#} to
+ {#syntax#}@as(u1, 0){#endsyntax#}.
If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#}
diff --git a/src/Air.zig b/src/Air.zig
index 8cb7b943e3..bd7b3af733 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -189,6 +189,10 @@ pub const Inst = struct {
/// Converts a pointer to its address. Result type is always `usize`.
/// Uses the `un_op` field.
ptrtoint,
+ /// Given a boolean, returns 0 or 1.
+ /// Result type is always `u1`.
+ /// Uses the `un_op` field.
+ bool_to_int,
/// Stores a value onto the stack and returns a pointer to it.
/// TODO audit where this AIR instruction is emitted, maybe it should instead be emitting
/// alloca instruction and storing to the alloca.
@@ -490,6 +494,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.slice_len,
=> return Type.initTag(.usize),
+ .bool_to_int => return Type.initTag(.u1),
+
.call => {
const callee_ty = air.typeOf(datas[inst].pl_op.operand);
return callee_ty.fnReturnType();
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 34f906fab1..b5e5d60b2c 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -7754,6 +7754,7 @@ pub const simple_types = std.ComptimeStringMap(Zir.Inst.Ref, .{
.{ "u32", .u32_type },
.{ "u64", .u64_type },
.{ "u128", .u128_type },
+ .{ "u1", .u1_type },
.{ "u8", .u8_type },
.{ "undefined", .undef },
.{ "usize", .usize_type },
@@ -8400,6 +8401,7 @@ fn rvalue(
const as_usize = @as(u64, @enumToInt(Zir.Inst.Ref.usize_type)) << 32;
const as_void = @as(u64, @enumToInt(Zir.Inst.Ref.void_type)) << 32;
switch ((@as(u64, @enumToInt(ty_inst)) << 32) | @as(u64, @enumToInt(result))) {
+ as_ty | @enumToInt(Zir.Inst.Ref.u1_type),
as_ty | @enumToInt(Zir.Inst.Ref.u8_type),
as_ty | @enumToInt(Zir.Inst.Ref.i8_type),
as_ty | @enumToInt(Zir.Inst.Ref.u16_type),
diff --git a/src/Liveness.zig b/src/Liveness.zig
index a4c6d8c016..a44b582424 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -291,6 +291,7 @@ fn analyzeInst(
.is_err_ptr,
.is_non_err_ptr,
.ptrtoint,
+ .bool_to_int,
.ret,
=> {
const operand = inst_datas[inst].un_op;
diff --git a/src/Sema.zig b/src/Sema.zig
index 46a41426c8..88a83fd661 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -5848,8 +5848,14 @@ fn zirAlignOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
fn zirBoolToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
- const src = inst_data.src();
- return sema.mod.fail(&block.base, src, "TODO: Sema.zirBoolToInt", .{});
+ const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+ const operand = sema.resolveInst(inst_data.operand);
+ if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
+ if (val.isUndef()) return sema.addConstUndef(Type.initTag(.u1));
+ const bool_ints = [2]Air.Inst.Ref{ .zero, .one };
+ return bool_ints[@boolToInt(val.toBool())];
+ }
+ return block.addUnOp(.bool_to_int, operand);
}
fn zirEmbedFile(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -8252,6 +8258,7 @@ fn typeHasOnePossibleValue(
.c_longdouble,
.comptime_int,
.comptime_float,
+ .u1,
.u8,
.i8,
.u16,
diff --git a/src/Zir.zig b/src/Zir.zig
index 2b88a3415d..a8320b65d4 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -1633,6 +1633,7 @@ pub const Inst = struct {
/// value and may instead be used as a sentinel to indicate null.
none,
+ u1_type,
u8_type,
i8_type,
u16_type,
@@ -1719,6 +1720,10 @@ pub const Inst = struct {
pub const typed_value_map = std.enums.directEnumArray(Ref, TypedValue, 0, .{
.none = undefined,
+ .u1_type = .{
+ .ty = Type.initTag(.type),
+ .val = Value.initTag(.u1_type),
+ },
.u8_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.u8_type),
diff --git a/src/codegen.zig b/src/codegen.zig
index 4924b68ca3..3b822c0f88 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -835,6 +835,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.dbg_stmt => try self.airDbgStmt(inst),
.floatcast => try self.airFloatCast(inst),
.intcast => try self.airIntCast(inst),
+ .bool_to_int => try self.airBoolToInt(inst),
.is_non_null => try self.airIsNonNull(inst),
.is_non_null_ptr => try self.airIsNonNullPtr(inst),
.is_null => try self.airIsNull(inst),
@@ -1110,6 +1111,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
+ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
+ const un_op = self.air.instructions.items(.data)[inst].un_op;
+ const operand = try self.resolveInst(un_op);
+ const result: MCValue = if (self.liveness.isUnused(inst)) .dead else operand;
+ return self.finishAir(inst, result, .{ un_op, .none, .none });
+ }
+
fn airNot(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index fa254af293..7299b21a61 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -925,6 +925,7 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
.call => try airCall(o, inst),
.dbg_stmt => try airDbgStmt(o, inst),
.intcast => try airIntCast(o, inst),
+ .bool_to_int => try airBoolToInt(o, inst),
.load => try airLoad(o, inst),
.ret => try airRet(o, inst),
.store => try airStore(o, inst),
@@ -1083,6 +1084,20 @@ fn airIntCast(o: *Object, inst: Air.Inst.Index) !CValue {
return local;
}
+fn airBoolToInt(o: *Object, inst: Air.Inst.Index) !CValue {
+ if (o.liveness.isUnused(inst))
+ return CValue.none;
+ const un_op = o.air.instructions.items(.data)[inst].un_op;
+ const writer = o.writer();
+ const inst_ty = o.air.typeOfIndex(inst);
+ const operand = try o.resolveInst(un_op);
+ const local = try o.allocLocal(inst_ty, .Const);
+ try writer.writeAll(" = ");
+ try o.writeCValue(writer, operand);
+ try writer.writeAll(";\n");
+ return local;
+}
+
fn airStore(o: *Object, inst: Air.Inst.Index) !CValue {
// *a = b;
const bin_op = o.air.instructions.items(.data)[inst].bin_op;
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 74a51e6634..22f117aa1c 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -961,6 +961,7 @@ pub const FuncGen = struct {
.alloc => try self.airAlloc(inst),
.arg => try self.airArg(inst),
.bitcast => try self.airBitCast(inst),
+ .bool_to_int=> try self.airBoolToInt(inst),
.block => try self.airBlock(inst),
.br => try self.airBr(inst),
.switch_br => try self.airSwitchBr(inst),
@@ -1656,6 +1657,15 @@ pub const FuncGen = struct {
return self.builder.buildBitCast(operand, dest_type, "");
}
+ fn airBoolToInt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ const un_op = self.air.instructions.items(.data)[inst].un_op;
+ const operand = try self.resolveInst(un_op);
+ return operand;
+ }
+
fn airArg(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
const arg_val = self.args[self.arg_index];
self.arg_index += 1;
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index 0c9e513742..4f5df73f8d 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -885,7 +885,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
// Both stage1 and stage2 LLVM backend put the object file in the cache directory.
if (self.base.options.use_llvm) {
// Stage2 has to call flushModule since that outputs the LLVM object file.
- if (!build_options.is_stage1) try self.flushModule(comp);
+ if (!build_options.is_stage1 or !self.base.options.use_stage1) try self.flushModule(comp);
const obj_basename = try std.zig.binNameAlloc(arena, .{
.root_name = self.base.options.root_name,
@@ -1269,7 +1269,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
// TODO: remove when stage2 can build compiler_rt.zig, c.zig and ssp.zig
// compiler-rt, libc and libssp
- if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies and build_options.is_stage1) {
+ if (is_exe_or_dyn_lib and
+ !self.base.options.skip_linker_dependencies and
+ build_options.is_stage1 and self.base.options.use_stage1)
+ {
if (!self.base.options.link_libc) {
try argv.append(comp.libc_static_lib.?.full_object_path);
}
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 502575f3c8..9ddebd3453 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1257,7 +1257,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
// Both stage1 and stage2 LLVM backend put the object file in the cache directory.
if (self.base.options.use_llvm) {
// Stage2 has to call flushModule since that outputs the LLVM object file.
- if (!build_options.is_stage1) try self.flushModule(comp);
+ if (!build_options.is_stage1 or !self.base.options.use_stage1) try self.flushModule(comp);
const obj_basename = try std.zig.binNameAlloc(arena, .{
.root_name = self.base.options.root_name,
@@ -1287,7 +1287,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;
const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt) blk: {
// TODO: remove when stage2 can build compiler_rt.zig
- if (!build_options.is_stage1) break :blk null;
+ if (!build_options.is_stage1 or !self.base.options.use_stage1) break :blk null;
// In the case of build-obj we include the compiler-rt symbols directly alongside
// the symbols of the root source file, in the same compilation unit.
@@ -1605,7 +1605,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
if (is_exe_or_dyn_lib and
!self.base.options.skip_linker_dependencies and
!self.base.options.link_libc and
- build_options.is_stage1)
+ build_options.is_stage1 and
+ self.base.options.use_stage1)
{
try argv.append(comp.libc_static_lib.?.full_object_path);
}
diff --git a/src/print_air.zig b/src/print_air.zig
index c20a6995e5..2d5d6b588e 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -137,6 +137,7 @@ const Writer = struct {
.is_err_ptr,
.is_non_err_ptr,
.ptrtoint,
+ .bool_to_int,
.ret,
=> try w.writeUnOp(s, inst),
diff --git a/src/type.zig b/src/type.zig
index 4dd1a15fdd..d828df550b 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -23,6 +23,7 @@ pub const Type = extern union {
pub fn zigTypeTag(self: Type) std.builtin.TypeId {
switch (self.tag()) {
+ .u1,
.u8,
.i8,
.u16,
@@ -638,6 +639,7 @@ pub const Type = extern union {
if (self.tag_if_small_enough < Tag.no_payload_count) {
return Type{ .tag_if_small_enough = self.tag_if_small_enough };
} else switch (self.ptr_otherwise.tag) {
+ .u1,
.u8,
.i8,
.u16,
@@ -819,6 +821,7 @@ pub const Type = extern union {
while (true) {
const t = ty.tag();
switch (t) {
+ .u1,
.u8,
.i8,
.u16,
@@ -1082,6 +1085,7 @@ pub const Type = extern union {
pub fn toValue(self: Type, allocator: *Allocator) Allocator.Error!Value {
switch (self.tag()) {
+ .u1 => return Value.initTag(.u1_type),
.u8 => return Value.initTag(.u8_type),
.i8 => return Value.initTag(.i8_type),
.u16 => return Value.initTag(.u16_type),
@@ -1141,6 +1145,7 @@ pub const Type = extern union {
pub fn hasCodeGenBits(self: Type) bool {
return switch (self.tag()) {
+ .u1,
.u8,
.i8,
.u16,
@@ -1321,6 +1326,7 @@ pub const Type = extern union {
/// Asserts that hasCodeGenBits() is true.
pub fn abiAlignment(self: Type, target: Target) u32 {
return switch (self.tag()) {
+ .u1,
.u8,
.i8,
.bool,
@@ -1539,6 +1545,7 @@ pub const Type = extern union {
@panic("TODO abiSize unions");
},
+ .u1,
.u8,
.i8,
.bool,
@@ -1704,7 +1711,7 @@ pub const Type = extern union {
.u8, .i8 => 8,
- .bool => 1,
+ .bool, .u1 => 1,
.vector => {
const payload = self.castTag(.vector).?.data;
@@ -2217,12 +2224,13 @@ pub const Type = extern union {
pub fn isUnsignedInt(self: Type) bool {
return switch (self.tag()) {
.int_unsigned,
- .u8,
.usize,
.c_ushort,
.c_uint,
.c_ulong,
.c_ulonglong,
+ .u1,
+ .u8,
.u16,
.u32,
.u64,
@@ -2244,6 +2252,7 @@ pub const Type = extern union {
.signedness = .signed,
.bits = self.castTag(.int_signed).?.data,
},
+ .u1 => .{ .signedness = .unsigned, .bits = 1 },
.u8 => .{ .signedness = .unsigned, .bits = 8 },
.i8 => .{ .signedness = .signed, .bits = 8 },
.u16 => .{ .signedness = .unsigned, .bits = 16 },
@@ -2406,6 +2415,7 @@ pub const Type = extern union {
.c_longdouble,
.comptime_int,
.comptime_float,
+ .u1,
.u8,
.i8,
.u16,
@@ -2446,6 +2456,7 @@ pub const Type = extern union {
.c_longdouble,
.comptime_int,
.comptime_float,
+ .u1,
.u8,
.i8,
.u16,
@@ -2911,6 +2922,7 @@ pub const Type = extern union {
/// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`.
pub const Tag = enum {
// The first section of this enum are tags that require no payload.
+ u1,
u8,
i8,
u16,
@@ -3018,6 +3030,7 @@ pub const Type = extern union {
pub fn Type(comptime t: Tag) type {
return switch (t) {
+ .u1,
.u8,
.i8,
.u16,
diff --git a/src/value.zig b/src/value.zig
index fc34473921..5d9fd27414 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -22,6 +22,7 @@ pub const Value = extern union {
pub const Tag = enum {
// The first section of this enum are tags that require no payload.
+ u1_type,
u8_type,
i8_type,
u16_type,
@@ -138,6 +139,7 @@ pub const Value = extern union {
pub fn Type(comptime t: Tag) type {
return switch (t) {
+ .u1_type,
.u8_type,
.i8_type,
.u16_type,
@@ -314,6 +316,7 @@ pub const Value = extern union {
if (self.tag_if_small_enough < Tag.no_payload_count) {
return Value{ .tag_if_small_enough = self.tag_if_small_enough };
} else switch (self.ptr_otherwise.tag) {
+ .u1_type,
.u8_type,
.i8_type,
.u16_type,
@@ -520,6 +523,7 @@ pub const Value = extern union {
comptime assert(fmt.len == 0);
var val = start_val;
while (true) switch (val.tag()) {
+ .u1_type => return out_stream.writeAll("u1"),
.u8_type => return out_stream.writeAll("u8"),
.i8_type => return out_stream.writeAll("i8"),
.u16_type => return out_stream.writeAll("u16"),
@@ -671,6 +675,7 @@ pub const Value = extern union {
pub fn toType(self: Value, allocator: *Allocator) !Type {
return switch (self.tag()) {
.ty => self.castTag(.ty).?.data,
+ .u1_type => Type.initTag(.u1),
.u8_type => Type.initTag(.u8),
.i8_type => Type.initTag(.i8),
.u16_type => Type.initTag(.u16),
@@ -1150,6 +1155,7 @@ pub const Value = extern union {
var hasher = std.hash.Wyhash.init(0);
switch (self.tag()) {
+ .u1_type,
.u8_type,
.i8_type,
.u16_type,
@@ -1502,6 +1508,7 @@ pub const Value = extern union {
return switch (self.tag()) {
.ty,
.int_type,
+ .u1_type,
.u8_type,
.i8_type,
.u16_type,
diff --git a/test/behavior.zig b/test/behavior.zig
index 101ee2ce53..a286b1a6e2 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -2,11 +2,9 @@ const builtin = @import("builtin");
test {
// Tests that pass for both.
- {}
+ _ = @import("behavior/bool.zig");
- if (builtin.zig_is_stage2) {
- // Tests that only pass for stage2.
- } else {
+ if (!builtin.zig_is_stage2) {
// Tests that only pass for stage1.
_ = @import("behavior/align.zig");
_ = @import("behavior/alignof.zig");
@@ -20,7 +18,6 @@ test {
_ = @import("behavior/bit_shifting.zig");
_ = @import("behavior/bitcast.zig");
_ = @import("behavior/bitreverse.zig");
- _ = @import("behavior/bool.zig");
_ = @import("behavior/bugs/1025.zig");
_ = @import("behavior/bugs/1076.zig");
_ = @import("behavior/bugs/1111.zig");
From bb2accba9bf1ec2bf32e7d461785b3084524dbf1 Mon Sep 17 00:00:00 2001
From: Meghan Denny
Date: Mon, 26 Jul 2021 12:26:11 -0700
Subject: [PATCH 10/96] stage1: add c_longdouble mapping for s390x
---
src/stage1/codegen.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp
index d1bea6990a..083d15068a 100644
--- a/src/stage1/codegen.cpp
+++ b/src/stage1/codegen.cpp
@@ -8794,6 +8794,9 @@ static void define_builtin_types(CodeGen *g) {
case ZigLLVM_sparcv9:
add_fp_entry(g, "c_longdouble", 128, LLVMFP128Type(), &g->builtin_types.entry_c_longdouble);
break;
+ case ZigLLVM_systemz:
+ add_fp_entry(g, "c_longdouble", 128, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
+ break;
case ZigLLVM_avr:
// It's either a float or a double, depending on a toolchain switch
add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
From c234d4790ef51ac05e317e42a0a4836632a5d7a0 Mon Sep 17 00:00:00 2001
From: Lee Cannon
Date: Wed, 28 Jul 2021 02:30:53 +0100
Subject: [PATCH 11/96] Add option to hide build command on compilation error
to build_runner (#8513)
Co-authored-by: Veikka Tuominen
---
lib/std/build.zig | 12 ++++++--
lib/std/build/RunStep.zig | 18 ++++++++----
lib/std/special/build_runner.zig | 49 +++++++++++++++++---------------
src/main.zig | 13 +++++++--
4 files changed, 60 insertions(+), 32 deletions(-)
diff --git a/lib/std/build.zig b/lib/std/build.zig
index cf592f2016..02774c6dad 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -45,6 +45,8 @@ pub const Builder = struct {
verbose_llvm_ir: bool,
verbose_cimport: bool,
verbose_llvm_cpu_features: bool,
+ /// The purpose of executing the command is for a human to read compile errors from the terminal
+ prominent_compile_errors: bool,
color: enum { auto, on, off } = .auto,
invalid_user_input: bool,
zig_exe: []const u8,
@@ -157,6 +159,7 @@ pub const Builder = struct {
.verbose_llvm_ir = false,
.verbose_cimport = false,
.verbose_llvm_cpu_features = false,
+ .prominent_compile_errors = false,
.invalid_user_input = false,
.allocator = allocator,
.user_input_options = UserInputOptionsMap.init(allocator),
@@ -1162,8 +1165,13 @@ pub const Builder = struct {
},
error.ExitCodeFailure => {
if (src_step) |s| warn("{s}...", .{s.name});
- warn("The following command exited with error code {d}:\n", .{code});
- printCmd(null, argv);
+ if (self.prominent_compile_errors) {
+ warn("The step exited with error code {d}\n", .{code});
+ } else {
+ warn("The following command exited with error code {d}:\n", .{code});
+ printCmd(null, argv);
+ }
+
std.os.exit(@truncate(u8, code));
},
error.ProcessTerminated => {
diff --git a/lib/std/build/RunStep.zig b/lib/std/build/RunStep.zig
index 50fea83784..89d9cd911c 100644
--- a/lib/std/build/RunStep.zig
+++ b/lib/std/build/RunStep.zig
@@ -221,11 +221,19 @@ fn make(step: *Step) !void {
switch (term) {
.Exited => |code| {
if (code != self.expected_exit_code) {
- warn("The following command exited with error code {} (expected {}):\n", .{
- code,
- self.expected_exit_code,
- });
- printCmd(cwd, argv);
+ if (self.builder.prominent_compile_errors) {
+ warn("Run step exited with error code {} (expected {})\n", .{
+ code,
+ self.expected_exit_code,
+ });
+ } else {
+ warn("The following command exited with error code {} (expected {}):\n", .{
+ code,
+ self.expected_exit_code,
+ });
+ printCmd(cwd, argv);
+ }
+
return error.UncleanExit;
}
},
diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig
index 475199eaf4..20f72d2674 100644
--- a/lib/std/special/build_runner.zig
+++ b/lib/std/special/build_runner.zig
@@ -157,6 +157,8 @@ pub fn main() !void {
builder.verbose_cc = true;
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
builder.verbose_llvm_cpu_features = true;
+ } else if (mem.eql(u8, arg, "--prominent-compile-errors")) {
+ builder.prominent_compile_errors = true;
} else if (mem.eql(u8, arg, "--")) {
builder.args = argsRest(args, arg_idx);
break;
@@ -214,24 +216,25 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void
try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name})
else
top_level_step.step.name;
- try out_stream.print(" {s:<27} {s}\n", .{ name, top_level_step.description });
+ try out_stream.print(" {s:<28} {s}\n", .{ name, top_level_step.description });
}
try out_stream.writeAll(
\\
\\General Options:
- \\ -p, --prefix [path] Override default install prefix
- \\ --prefix-lib-dir [path] Override default library directory path
- \\ --prefix-exe-dir [path] Override default executable directory path
- \\ --prefix-include-dir [path] Override default include directory path
+ \\ -p, --prefix [path] Override default install prefix
+ \\ --prefix-lib-dir [path] Override default library directory path
+ \\ --prefix-exe-dir [path] Override default executable directory path
+ \\ --prefix-include-dir [path] Override default include directory path
\\
- \\ --sysroot [path] Set the system root directory (usually /)
- \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
- \\ --libc [file] Provide a file which specifies libc paths
+ \\ --sysroot [path] Set the system root directory (usually /)
+ \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
+ \\ --libc [file] Provide a file which specifies libc paths
\\
- \\ -h, --help Print this help and exit
- \\ --verbose Print commands before executing them
- \\ --color [auto|off|on] Enable or disable colored error messages
+ \\ -h, --help Print this help and exit
+ \\ --verbose Print commands before executing them
+ \\ --color [auto|off|on] Enable or disable colored error messages
+ \\ --prominent-compile-errors Output compile errors formatted for a human to read
\\
\\Project-Specific Options:
\\
@@ -246,24 +249,24 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void
@tagName(option.type_id),
});
defer allocator.free(name);
- try out_stream.print("{s:<29} {s}\n", .{ name, option.description });
+ try out_stream.print("{s:<30} {s}\n", .{ name, option.description });
}
}
try out_stream.writeAll(
\\
\\Advanced Options:
- \\ --build-file [file] Override path to build.zig
- \\ --cache-dir [path] Override path to zig cache directory
- \\ --zig-lib-dir [arg] Override path to Zig lib directory
- \\ --verbose-tokenize Enable compiler debug output for tokenization
- \\ --verbose-ast Enable compiler debug output for parsing into an AST
- \\ --verbose-link Enable compiler debug output for linking
- \\ --verbose-ir Enable compiler debug output for Zig IR
- \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
- \\ --verbose-cimport Enable compiler debug output for C imports
- \\ --verbose-cc Enable compiler debug output for C compilation
- \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
+ \\ --build-file [file] Override path to build.zig
+ \\ --cache-dir [path] Override path to zig cache directory
+ \\ --zig-lib-dir [arg] Override path to Zig lib directory
+ \\ --verbose-tokenize Enable compiler debug output for tokenization
+ \\ --verbose-ast Enable compiler debug output for parsing into an AST
+ \\ --verbose-link Enable compiler debug output for linking
+ \\ --verbose-ir Enable compiler debug output for Zig IR
+ \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
+ \\ --verbose-cimport Enable compiler debug output for C imports
+ \\ --verbose-cc Enable compiler debug output for C compilation
+ \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
\\
);
}
diff --git a/src/main.zig b/src/main.zig
index d0aa6213cb..5b0c9edc8f 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -2753,6 +2753,8 @@ pub const usage_build =
;
pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !void {
+ var prominent_compile_errors: bool = false;
+
// We want to release all the locks before executing the child process, so we make a nice
// big block here to ensure the cleanup gets run when we extract out our argv.
const child_argv = argv: {
@@ -2804,6 +2806,8 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
i += 1;
override_global_cache_dir = args[i];
continue;
+ } else if (mem.eql(u8, arg, "--prominent-compile-errors")) {
+ prominent_compile_errors = true;
}
}
try child_argv.append(arg);
@@ -2973,8 +2977,13 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
switch (term) {
.Exited => |code| {
if (code == 0) return cleanExit();
- const cmd = try argvCmd(arena, child_argv);
- fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd });
+
+ if (prominent_compile_errors) {
+ fatal("the build command failed with exit code {d}", .{code});
+ } else {
+ const cmd = try argvCmd(arena, child_argv);
+ fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd });
+ }
},
else => {
const cmd = try argvCmd(arena, child_argv);
From a8e8927c4926176c683a4b66f86c8b011064e7b7 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 27 Jul 2021 18:33:49 -0700
Subject: [PATCH 12/96] fix old references to verbose-ir to be verbose-air
---
lib/std/build.zig | 6 +++---
lib/std/special/build_runner.zig | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/lib/std/build.zig b/lib/std/build.zig
index 02774c6dad..22f454adca 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -41,7 +41,7 @@ pub const Builder = struct {
verbose_ast: bool,
verbose_link: bool,
verbose_cc: bool,
- verbose_ir: bool,
+ verbose_air: bool,
verbose_llvm_ir: bool,
verbose_cimport: bool,
verbose_llvm_cpu_features: bool,
@@ -155,7 +155,7 @@ pub const Builder = struct {
.verbose_ast = false,
.verbose_link = false,
.verbose_cc = false,
- .verbose_ir = false,
+ .verbose_air = false,
.verbose_llvm_ir = false,
.verbose_cimport = false,
.verbose_llvm_cpu_features = false,
@@ -2451,7 +2451,7 @@ pub const LibExeObjStep = struct {
if (builder.verbose_tokenize) zig_args.append("--verbose-tokenize") catch unreachable;
if (builder.verbose_ast) zig_args.append("--verbose-ast") catch unreachable;
if (builder.verbose_cimport) zig_args.append("--verbose-cimport") catch unreachable;
- if (builder.verbose_ir) zig_args.append("--verbose-ir") catch unreachable;
+ if (builder.verbose_air) zig_args.append("--verbose-air") catch unreachable;
if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable;
if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable;
if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable;
diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig
index 20f72d2674..2da273a673 100644
--- a/lib/std/special/build_runner.zig
+++ b/lib/std/special/build_runner.zig
@@ -147,8 +147,8 @@ pub fn main() !void {
builder.verbose_ast = true;
} else if (mem.eql(u8, arg, "--verbose-link")) {
builder.verbose_link = true;
- } else if (mem.eql(u8, arg, "--verbose-ir")) {
- builder.verbose_ir = true;
+ } else if (mem.eql(u8, arg, "--verbose-air")) {
+ builder.verbose_air = true;
} else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
builder.verbose_llvm_ir = true;
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
@@ -262,7 +262,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void
\\ --verbose-tokenize Enable compiler debug output for tokenization
\\ --verbose-ast Enable compiler debug output for parsing into an AST
\\ --verbose-link Enable compiler debug output for linking
- \\ --verbose-ir Enable compiler debug output for Zig IR
+ \\ --verbose-air Enable compiler debug output for Zig AIR
\\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
\\ --verbose-cimport Enable compiler debug output for C imports
\\ --verbose-cc Enable compiler debug output for C compilation
From eb010ce65ddddb23ceddae86d377432cf1b2b01c Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Mon, 26 Jul 2021 16:03:30 -0500
Subject: [PATCH 13/96] Skip empty strings in std.fs.path.join function
---
lib/std/fs/path.zig | 48 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 37 insertions(+), 11 deletions(-)
diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig
index 04404a61bb..ed04f0b09d 100644
--- a/lib/std/fs/path.zig
+++ b/lib/std/fs/path.zig
@@ -43,17 +43,32 @@ pub fn isSep(byte: u8) bool {
fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {
if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{};
+ // Find first non-empty path index.
+ const first_path_index = blk: {
+ for (paths) |path, index| {
+ if (path.len == 0) continue else break :blk index;
+ }
+
+ // All paths provided were empty, so return early.
+ return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{};
+ };
+
+ // Calculate length needed for resulting joined path buffer.
const total_len = blk: {
- var sum: usize = paths[0].len;
- var i: usize = 1;
+ var sum: usize = paths[first_path_index].len;
+ var prev_path = paths[first_path_index];
+ assert(prev_path.len > 0);
+ var i: usize = first_path_index + 1;
while (i < paths.len) : (i += 1) {
- const prev_path = paths[i - 1];
const this_path = paths[i];
- const prev_sep = (prev_path.len != 0 and sepPredicate(prev_path[prev_path.len - 1]));
- const this_sep = (this_path.len != 0 and sepPredicate(this_path[0]));
+ if (this_path.len == 0) continue;
+ const prev_sep = sepPredicate(prev_path[prev_path.len - 1]);
+ const this_sep = sepPredicate(this_path[0]);
sum += @boolToInt(!prev_sep and !this_sep);
sum += if (prev_sep and this_sep) this_path.len - 1 else this_path.len;
+ prev_path = this_path;
}
+
if (zero) sum += 1;
break :blk sum;
};
@@ -61,14 +76,16 @@ fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) boo
const buf = try allocator.alloc(u8, total_len);
errdefer allocator.free(buf);
- mem.copy(u8, buf, paths[0]);
- var buf_index: usize = paths[0].len;
- var i: usize = 1;
+ mem.copy(u8, buf, paths[first_path_index]);
+ var buf_index: usize = paths[first_path_index].len;
+ var prev_path = paths[first_path_index];
+ assert(prev_path.len > 0);
+ var i: usize = first_path_index + 1;
while (i < paths.len) : (i += 1) {
- const prev_path = paths[i - 1];
const this_path = paths[i];
- const prev_sep = (prev_path.len != 0 and sepPredicate(prev_path[prev_path.len - 1]));
- const this_sep = (this_path.len != 0 and sepPredicate(this_path[0]));
+ if (this_path.len == 0) continue;
+ const prev_sep = sepPredicate(prev_path[prev_path.len - 1]);
+ const this_sep = sepPredicate(this_path[0]);
if (!prev_sep and !this_sep) {
buf[buf_index] = separator;
buf_index += 1;
@@ -76,6 +93,7 @@ fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) boo
const adjusted_path = if (prev_sep and this_sep) this_path[1..] else this_path;
mem.copy(u8, buf[buf_index..], adjusted_path);
buf_index += adjusted_path.len;
+ prev_path = this_path;
}
if (zero) buf[buf.len - 1] = 0;
@@ -148,6 +166,10 @@ test "join" {
try testJoinMaybeZWindows(&[_][]const u8{ "c:\\", "a", "b/", "c" }, "c:\\a\\b/c", zero);
try testJoinMaybeZWindows(&[_][]const u8{ "c:\\a/", "b\\", "/c" }, "c:\\a/b\\c", zero);
+ try testJoinMaybeZWindows(&[_][]const u8{ "", "c:\\", "", "", "a", "b\\", "c", "" }, "c:\\a\\b\\c", zero);
+ try testJoinMaybeZWindows(&[_][]const u8{ "c:\\a/", "", "b\\", "", "/c" }, "c:\\a/b\\c", zero);
+ try testJoinMaybeZWindows(&[_][]const u8{ "", "" }, "", zero);
+
try testJoinMaybeZPosix(&[_][]const u8{}, "", zero);
try testJoinMaybeZPosix(&[_][]const u8{ "/a/b", "c" }, "/a/b/c", zero);
try testJoinMaybeZPosix(&[_][]const u8{ "/a/b/", "c" }, "/a/b/c", zero);
@@ -163,6 +185,10 @@ test "join" {
try testJoinMaybeZPosix(&[_][]const u8{ "a", "/c" }, "a/c", zero);
try testJoinMaybeZPosix(&[_][]const u8{ "a/", "/c" }, "a/c", zero);
+
+ try testJoinMaybeZPosix(&[_][]const u8{ "", "/", "a", "", "b/", "c", "" }, "/a/b/c", zero);
+ try testJoinMaybeZPosix(&[_][]const u8{ "/a/", "", "", "b/", "c" }, "/a/b/c", zero);
+ try testJoinMaybeZPosix(&[_][]const u8{ "", "" }, "", zero);
}
}
From 98eea963deb85d2174262d5f45ddd614a7906231 Mon Sep 17 00:00:00 2001
From: Evan Haas
Date: Mon, 26 Jul 2021 12:08:29 -0700
Subject: [PATCH 14/96] translate-c: fix import path in translation failure
comment
---
src/translate_c.zig | 4 ++--
test/run_translated_c.zig | 2 +-
test/translate_c.zig | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/translate_c.zig b/src/translate_c.zig
index 395a314f7c..df8e285b59 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -1969,7 +1969,7 @@ fn transBuiltinFnExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used:
const node = try transExpr(c, scope, expr, used);
if (node.castTag(.identifier)) |ident| {
const name = ident.data;
- if (!isBuiltinDefined(name)) return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO implement function '{s}' in std.c.builtins", .{name});
+ if (!isBuiltinDefined(name)) return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO implement function '{s}' in std.zig.c_builtins", .{name});
}
return node;
}
@@ -5574,7 +5574,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
.Identifier => {
const mangled_name = scope.getAlias(slice);
if (mem.startsWith(u8, mangled_name, "__builtin_") and !isBuiltinDefined(mangled_name)) {
- try m.fail(c, "TODO implement function '{s}' in std.c.builtins", .{mangled_name});
+ try m.fail(c, "TODO implement function '{s}' in std.zig.c_builtins", .{mangled_name});
return error.ParseError;
}
const identifier = try Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig
index 4953896636..ef2fd187df 100644
--- a/test/run_translated_c.zig
+++ b/test/run_translated_c.zig
@@ -1243,7 +1243,7 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\}
, "");
- // See __builtin_alloca_with_align comment in std.c.builtins
+ // See __builtin_alloca_with_align comment in std.zig.c_builtins
cases.add("use of unimplemented builtin in unused function does not prevent compilation",
\\#include
\\void unused() {
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 1ceaf15e5c..b75d3b5cac 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -3461,11 +3461,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const MAY_NEED_PROMOTION_OCT = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0o20000000000, .octal);
});
- // See __builtin_alloca_with_align comment in std.c.builtins
+ // See __builtin_alloca_with_align comment in std.zig.c_builtins
cases.add("demote un-implemented builtins",
\\#define FOO(X) __builtin_alloca_with_align((X), 8)
, &[_][]const u8{
- \\pub const FOO = @compileError("TODO implement function '__builtin_alloca_with_align' in std.c.builtins");
+ \\pub const FOO = @compileError("TODO implement function '__builtin_alloca_with_align' in std.zig.c_builtins");
});
cases.add("null sentinel arrays when initialized from string literal. Issue #8256",
From c090e38340f3b0df30e1affb838a6e171f943280 Mon Sep 17 00:00:00 2001
From: Evan Haas
Date: Tue, 27 Jul 2021 16:06:38 -0700
Subject: [PATCH 15/96] translate-c: add support for ChooseExpr
---
src/clang.zig | 5 ++++
src/translate_c.zig | 4 ++++
src/zig_clang.cpp | 5 ++++
src/zig_clang.h | 3 +++
test/run_translated_c.zig | 50 +++++++++++++++++++++++++++++++++++++++
5 files changed, 67 insertions(+)
diff --git a/src/clang.zig b/src/clang.zig
index 023d1aba4b..0632c5ab67 100644
--- a/src/clang.zig
+++ b/src/clang.zig
@@ -269,6 +269,11 @@ pub const CharacterLiteral = opaque {
extern fn ZigClangCharacterLiteral_getValue(*const CharacterLiteral) c_uint;
};
+pub const ChooseExpr = opaque {
+ pub const getChosenSubExpr = ZigClangChooseExpr_getChosenSubExpr;
+ extern fn ZigClangChooseExpr_getChosenSubExpr(*const ChooseExpr) *const Expr;
+};
+
pub const CompoundAssignOperator = opaque {
pub const getType = ZigClangCompoundAssignOperator_getType;
extern fn ZigClangCompoundAssignOperator_getType(*const CompoundAssignOperator) QualType;
diff --git a/src/translate_c.zig b/src/translate_c.zig
index df8e285b59..fb40344b34 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -1308,6 +1308,10 @@ fn transStmt(
const shuffle_vec_node = try transShuffleVectorExpr(c, scope, shuffle_vec_expr);
return maybeSuppressResult(c, scope, result_used, shuffle_vec_node);
},
+ .ChooseExprClass => {
+ const choose_expr = @ptrCast(*const clang.ChooseExpr, stmt);
+ return transExpr(c, scope, choose_expr.getChosenSubExpr(), result_used);
+ },
// When adding new cases here, see comment for maybeBlockify()
.GCCAsmStmtClass,
.GotoStmtClass,
diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp
index 7c923021d8..4fe1dfc286 100644
--- a/src/zig_clang.cpp
+++ b/src/zig_clang.cpp
@@ -2832,6 +2832,11 @@ unsigned ZigClangCharacterLiteral_getValue(const struct ZigClangCharacterLiteral
return casted->getValue();
}
+const struct ZigClangExpr *ZigClangChooseExpr_getChosenSubExpr(const struct ZigClangChooseExpr *self) {
+ auto casted = reinterpret_cast(self);
+ return reinterpret_cast(casted->getChosenSubExpr());
+}
+
const struct ZigClangExpr *ZigClangAbstractConditionalOperator_getCond(const struct ZigClangAbstractConditionalOperator *self) {
auto casted = reinterpret_cast(self);
return reinterpret_cast(casted->getCond());
diff --git a/src/zig_clang.h b/src/zig_clang.h
index 634534dfb4..dc35df3772 100644
--- a/src/zig_clang.h
+++ b/src/zig_clang.h
@@ -104,6 +104,7 @@ struct ZigClangCStyleCastExpr;
struct ZigClangCallExpr;
struct ZigClangCaseStmt;
struct ZigClangCharacterLiteral;
+struct ZigClangChooseExpr;
struct ZigClangCompoundAssignOperator;
struct ZigClangCompoundStmt;
struct ZigClangConditionalOperator;
@@ -1242,6 +1243,8 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangCharacterLiteral_getBeginLoc(
ZIG_EXTERN_C enum ZigClangCharacterLiteral_CharacterKind ZigClangCharacterLiteral_getKind(const struct ZigClangCharacterLiteral *);
ZIG_EXTERN_C unsigned ZigClangCharacterLiteral_getValue(const struct ZigClangCharacterLiteral *);
+ZIG_EXTERN_C const struct ZigClangExpr *ZigClangChooseExpr_getChosenSubExpr(const struct ZigClangChooseExpr *);
+
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangAbstractConditionalOperator_getCond(const struct ZigClangAbstractConditionalOperator *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangAbstractConditionalOperator_getTrueExpr(const struct ZigClangAbstractConditionalOperator *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangAbstractConditionalOperator_getFalseExpr(const struct ZigClangAbstractConditionalOperator *);
diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig
index ef2fd187df..dab200af0d 100644
--- a/test/run_translated_c.zig
+++ b/test/run_translated_c.zig
@@ -1659,4 +1659,54 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
+
+ cases.add("__builtin_choose_expr (unchosen expression is not evaluated)",
+ \\#include
+ \\int main(void) {
+ \\ int x = 0.0;
+ \\ int y = 0.0;
+ \\ int res;
+ \\ res = __builtin_choose_expr(1, 1, x / y);
+ \\ if (res != 1) abort();
+ \\ res = __builtin_choose_expr(0, x / y, 2);
+ \\ if (res != 2) abort();
+ \\ return 0;
+ \\}
+ , "");
+
+ // TODO: add isnan check for long double once bitfield support is added
+ // (needed for x86_64-windows-gnu)
+ // TODO: add isinf check for long double once std.math.isInf supports c_longdouble
+ cases.add("NAN and INFINITY",
+ \\#include
+ \\#include
+ \\#include
+ \\union uf { uint32_t u; float f; };
+ \\#define CHECK_NAN(STR, VAL) { \
+ \\ union uf unpack = {.f = __builtin_nanf(STR)}; \
+ \\ if (!isnan(unpack.f)) abort(); \
+ \\ if (unpack.u != VAL) abort(); \
+ \\}
+ \\int main(void) {
+ \\ float f_nan = NAN;
+ \\ if (!isnan(f_nan)) abort();
+ \\ double d_nan = NAN;
+ \\ if (!isnan(d_nan)) abort();
+ \\ CHECK_NAN("0", 0x7FC00000);
+ \\ CHECK_NAN("", 0x7FC00000);
+ \\ CHECK_NAN("1", 0x7FC00001);
+ \\ CHECK_NAN("0x7FC00000", 0x7FC00000);
+ \\ CHECK_NAN("0x7FC0000F", 0x7FC0000F);
+ \\ CHECK_NAN("0x7FC000F0", 0x7FC000F0);
+ \\ CHECK_NAN("0x7FC00F00", 0x7FC00F00);
+ \\ CHECK_NAN("0x7FC0F000", 0x7FC0F000);
+ \\ CHECK_NAN("0x7FCF0000", 0x7FCF0000);
+ \\ CHECK_NAN("0xFFFFFFFF", 0x7FFFFFFF);
+ \\ float f_inf = INFINITY;
+ \\ if (!isinf(f_inf)) abort();
+ \\ double d_inf = INFINITY;
+ \\ if (!isinf(d_inf)) abort();
+ \\ return 0;
+ \\}
+ , "");
}
From d4d3a9dcc93d517ffec43c9b4572977c05ee4d4b Mon Sep 17 00:00:00 2001
From: Evan Haas
Date: Mon, 26 Jul 2021 12:05:53 -0700
Subject: [PATCH 16/96] translate-c: handle floating point NAN and INFINITY
macros
---
lib/std/zig/c_builtins.zig | 43 ++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/lib/std/zig/c_builtins.zig b/lib/std/zig/c_builtins.zig
index afa3ae0a87..479f7a3b0e 100644
--- a/lib/std/zig/c_builtins.zig
+++ b/lib/std/zig/c_builtins.zig
@@ -191,6 +191,49 @@ pub inline fn __builtin_expect(expr: c_long, c: c_long) c_long {
return expr;
}
+/// returns a quiet NaN. Quiet NaNs have many representations; tagp is used to select one in an
+/// implementation-defined way.
+/// This implementation is based on the description for __builtin_nan provided in the GCC docs at
+/// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fnan
+/// Comment is reproduced below:
+/// Since ISO C99 defines this function in terms of strtod, which we do not implement, a description
+/// of the parsing is in order.
+/// The string is parsed as by strtol; that is, the base is recognized by leading ‘0’ or ‘0x’ prefixes.
+/// The number parsed is placed in the significand such that the least significant bit of the number is
+/// at the least significant bit of the significand.
+/// The number is truncated to fit the significand field provided.
+/// The significand is forced to be a quiet NaN.
+///
+/// If tagp contains any non-numeric characters, the function returns a NaN whose significand is zero.
+/// If tagp is empty, the function returns a NaN whose significand is zero.
+pub inline fn __builtin_nanf(tagp: []const u8) f32 {
+ const parsed = std.fmt.parseUnsigned(c_ulong, tagp, 0) catch 0;
+ const bits = @truncate(u23, parsed); // single-precision float trailing significand is 23 bits
+ return @bitCast(f32, @as(u32, bits) | std.math.qnan_u32);
+}
+
+pub inline fn __builtin_huge_valf() f32 {
+ return std.math.inf(f32);
+}
+
+pub inline fn __builtin_inff() f32 {
+ return std.math.inf(f32);
+}
+
+pub inline fn __builtin_isnan(x: anytype) c_int {
+ return @boolToInt(std.math.isNan(x));
+}
+
+pub inline fn __builtin_isinf(x: anytype) c_int {
+ return @boolToInt(std.math.isInf(x));
+}
+
+/// Similar to isinf, except the return value is -1 for an argument of -Inf and 1 for an argument of +Inf.
+pub inline fn __builtin_isinf_sign(x: anytype) c_int {
+ if (!std.math.isInf(x)) return 0;
+ return if (std.math.isPositiveInf(x)) 1 else -1;
+}
+
// __builtin_alloca_with_align is not currently implemented.
// It is used in a run-translated-c test and a test-translate-c test to ensure that non-implemented
// builtins are correctly demoted. If you implement __builtin_alloca_with_align, please update the
From c1285a1bbe04ab9960768ed8eb583ba8eb32cbe1 Mon Sep 17 00:00:00 2001
From: Ominitay <37453713+Ominitay@users.noreply.github.com>
Date: Sat, 17 Apr 2021 18:33:43 +0100
Subject: [PATCH 17/96] Move fs.Walker to fs.Dir.Walker
fs.Walker has been replaced with fs.Dir.Walker. Paths of entries
returned are relative to the Dir.
---
lib/std/build.zig | 12 ++-
lib/std/fs.zig | 183 +++++++++++++++++++++-----------------------
lib/std/fs/test.zig | 5 +-
3 files changed, 100 insertions(+), 100 deletions(-)
diff --git a/lib/std/build.zig b/lib/std/build.zig
index 22f454adca..685fd2bdc5 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -3015,7 +3015,8 @@ pub const InstallDirStep = struct {
const self = @fieldParentPtr(InstallDirStep, "step", step);
const dest_prefix = self.builder.getInstallPath(self.options.install_dir, self.options.install_subdir);
const full_src_dir = self.builder.pathFromRoot(self.options.source_dir);
- var it = try fs.walkPath(self.builder.allocator, full_src_dir);
+ const src_dir = try std.fs.cwd().openDir(full_src_dir, .{ .iterate = true });
+ var it = try src_dir.walk(self.builder.allocator);
next_entry: while (try it.next()) |entry| {
for (self.options.exclude_extensions) |ext| {
if (mem.endsWith(u8, entry.path, ext)) {
@@ -3023,9 +3024,12 @@ pub const InstallDirStep = struct {
}
}
- const rel_path = entry.path[full_src_dir.len + 1 ..];
+ const full_path = try fs.path.join(self.builder.allocator, &[_][]const u8{
+ full_src_dir, entry.path,
+ });
+
const dest_path = try fs.path.join(self.builder.allocator, &[_][]const u8{
- dest_prefix, rel_path,
+ dest_prefix, entry.path,
});
switch (entry.kind) {
@@ -3038,7 +3042,7 @@ pub const InstallDirStep = struct {
}
}
- try self.builder.updateFile(entry.path, dest_path);
+ try self.builder.updateFile(full_path, dest_path);
},
else => continue,
}
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 4ecdc3803b..2504965e3a 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -737,6 +737,94 @@ pub const Dir = struct {
}
}
+ pub const Walker = struct {
+ stack: std.ArrayList(StackItem),
+ name_buffer: std.ArrayList(u8),
+
+ pub const WalkerEntry = struct {
+ /// The containing directory. This can be used to operate directly on `basename`
+ /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths.
+ /// The directory remains open until `next` or `deinit` is called.
+ dir: Dir,
+ basename: []const u8,
+ path: []const u8,
+ kind: Dir.Entry.Kind,
+ };
+
+ const StackItem = struct {
+ iter: Dir.Iterator,
+ dirname_len: usize,
+ };
+
+ /// After each call to this function, and on deinit(), the memory returned
+ /// from this function becomes invalid. A copy must be made in order to keep
+ /// a reference to the path.
+ pub fn next(self: *Walker) !?WalkerEntry {
+ while (self.stack.items.len != 0) {
+ // `top` becomes invalid after appending to `self.stack`
+ var top = &self.stack.items[self.stack.items.len - 1];
+ const dirname_len = top.dirname_len;
+ if (try top.iter.next()) |base| {
+ self.name_buffer.shrinkRetainingCapacity(dirname_len);
+ if (self.name_buffer.items.len != 0) {
+ try self.name_buffer.append(path.sep);
+ }
+ try self.name_buffer.appendSlice(base.name);
+ if (base.kind == .Directory) {
+ var new_dir = top.iter.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
+ error.NameTooLong => unreachable, // no path sep in base.name
+ else => |e| return e,
+ };
+ {
+ errdefer new_dir.close();
+ try self.stack.append(StackItem{
+ .iter = new_dir.iterate(),
+ .dirname_len = self.name_buffer.items.len,
+ });
+ top = &self.stack.items[self.stack.items.len - 1];
+ }
+ }
+ return WalkerEntry{
+ .dir = top.iter.dir,
+ .basename = self.name_buffer.items[dirname_len + 1 ..],
+ .path = self.name_buffer.items,
+ .kind = base.kind,
+ };
+ } else {
+ self.stack.pop().iter.dir.close();
+ }
+ }
+ return null;
+ }
+
+ pub fn deinit(self: *Walker) void {
+ while (self.stack.popOrNull()) |*item| item.iter.dir.close();
+ self.stack.deinit();
+ self.name_buffer.deinit();
+ }
+ };
+
+ /// Recursively iterates over a directory.
+ /// Must call `Walker.deinit` when done.
+ /// The order of returned file system entries is undefined.
+ pub fn walk(self: Dir, allocator: *Allocator) !Walker {
+ var name_buffer = std.ArrayList(u8).init(allocator);
+ errdefer name_buffer.deinit();
+
+ var stack = std.ArrayList(Walker.StackItem).init(allocator);
+ errdefer stack.deinit();
+
+ try stack.append(Walker.StackItem{
+ .iter = self.iterate(),
+ .dirname_len = 0,
+ });
+
+ return Walker{
+ .stack = stack,
+ .name_buffer = name_buffer,
+ };
+ }
+
pub const OpenError = error{
FileNotFound,
NotDir,
@@ -2259,100 +2347,7 @@ pub fn symLinkAbsoluteZ(target_path_c: [*:0]const u8, sym_link_path_c: [*:0]cons
pub const symLink = @compileError("deprecated: use Dir.symLink or symLinkAbsolute");
pub const symLinkC = @compileError("deprecated: use Dir.symLinkZ or symLinkAbsoluteZ");
-pub const Walker = struct {
- stack: std.ArrayList(StackItem),
- name_buffer: std.ArrayList(u8),
-
- pub const Entry = struct {
- /// The containing directory. This can be used to operate directly on `basename`
- /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths.
- /// The directory remains open until `next` or `deinit` is called.
- dir: Dir,
- /// TODO make this null terminated for API convenience
- basename: []const u8,
-
- path: []const u8,
- kind: Dir.Entry.Kind,
- };
-
- const StackItem = struct {
- dir_it: Dir.Iterator,
- dirname_len: usize,
- };
-
- /// After each call to this function, and on deinit(), the memory returned
- /// from this function becomes invalid. A copy must be made in order to keep
- /// a reference to the path.
- pub fn next(self: *Walker) !?Entry {
- while (true) {
- if (self.stack.items.len == 0) return null;
- // `top` becomes invalid after appending to `self.stack`.
- var top = &self.stack.items[self.stack.items.len - 1];
- const dirname_len = top.dirname_len;
- if (try top.dir_it.next()) |base| {
- self.name_buffer.shrinkRetainingCapacity(dirname_len);
- try self.name_buffer.append(path.sep);
- try self.name_buffer.appendSlice(base.name);
- if (base.kind == .Directory) {
- var new_dir = top.dir_it.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
- error.NameTooLong => unreachable, // no path sep in base.name
- else => |e| return e,
- };
- {
- errdefer new_dir.close();
- try self.stack.append(StackItem{
- .dir_it = new_dir.iterate(),
- .dirname_len = self.name_buffer.items.len,
- });
- top = &self.stack.items[self.stack.items.len - 1];
- }
- }
- return Entry{
- .dir = top.dir_it.dir,
- .basename = self.name_buffer.items[dirname_len + 1 ..],
- .path = self.name_buffer.items,
- .kind = base.kind,
- };
- } else {
- self.stack.pop().dir_it.dir.close();
- }
- }
- }
-
- pub fn deinit(self: *Walker) void {
- while (self.stack.popOrNull()) |*item| item.dir_it.dir.close();
- self.stack.deinit();
- self.name_buffer.deinit();
- }
-};
-
-/// Recursively iterates over a directory.
-/// Must call `Walker.deinit` when done.
-/// `dir_path` must not end in a path separator.
-/// The order of returned file system entries is undefined.
-pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {
- assert(!mem.endsWith(u8, dir_path, path.sep_str));
-
- var dir = try cwd().openDir(dir_path, .{ .iterate = true });
- errdefer dir.close();
-
- var name_buffer = std.ArrayList(u8).init(allocator);
- errdefer name_buffer.deinit();
-
- try name_buffer.appendSlice(dir_path);
-
- var walker = Walker{
- .stack = std.ArrayList(Walker.StackItem).init(allocator),
- .name_buffer = name_buffer,
- };
-
- try walker.stack.append(Walker.StackItem{
- .dir_it = dir.iterate(),
- .dirname_len = dir_path.len,
- });
-
- return walker;
-}
+pub const walkPath = @compileError("deprecated: use Dir.walk");
pub const OpenSelfExeError = error{
SharingViolation,
diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig
index 9464959cdb..54f3e238d3 100644
--- a/lib/std/fs/test.zig
+++ b/lib/std/fs/test.zig
@@ -927,8 +927,9 @@ test "walker" {
}
const tmp_path = try fs.path.join(allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });
+ const tmp_dir = try fs.cwd().openDir(tmp_path, .{ .iterate = true });
- var walker = try fs.walkPath(testing.allocator, tmp_path);
+ var walker = try tmp_dir.walk(testing.allocator);
defer walker.deinit();
i = 0;
@@ -941,7 +942,7 @@ test "walker" {
try fs.path.join(allocator, &[_][]const u8{ expected_dir_name, name });
var entry = (try walker.next()).?;
- try testing.expectEqualStrings(expected_dir_name, try fs.path.relative(allocator, tmp_path, entry.path));
+ try testing.expectEqualStrings(expected_dir_name, entry.path);
}
}
From c47b46fc8dcb24a9af8e28d169d93170fce0e061 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 27 Jul 2021 17:16:26 -0700
Subject: [PATCH 18/96] CI: enable stage2 behavior test coverage
---
ci/azure/linux_script | 8 +++++---
ci/azure/macos_script | 9 ++++++---
ci/azure/windows_msvc_script.bat | 4 ++++
ci/srht/freebsd_script | 5 +++++
ci/srht/netbsd_script | 5 +++++
5 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/ci/azure/linux_script b/ci/azure/linux_script
index 33ad349044..dac7bac614 100755
--- a/ci/azure/linux_script
+++ b/ci/azure/linux_script
@@ -69,9 +69,11 @@ release/bin/zig fmt --check ..
cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig"
make $JOBS install
-for step in test-toolchain test-std docs; do
- release/bin/zig build $step -Denable-qemu -Denable-wasmtime
-done
+release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test
+
+release/bin/zig build test-toolchain -Denable-qemu -Denable-wasmtime
+release/bin/zig build test-std -Denable-qemu -Denable-wasmtime
+release/bin/zig build docs -Denable-qemu -Denable-wasmtime
# Look for HTML errors.
tidy -qe ../zig-cache/langref.html
diff --git a/ci/azure/macos_script b/ci/azure/macos_script
index 4afaedfa12..01ac3f5838 100755
--- a/ci/azure/macos_script
+++ b/ci/azure/macos_script
@@ -54,9 +54,12 @@ make $JOBS install
cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig"
make $JOBS install
-for step in test-toolchain test-std docs; do
- release/bin/zig build $step
-done
+# TODO figure out why this causes a segmentation fault
+# release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test
+
+release/bin/zig build test-toolchain
+release/bin/zig build test-std
+release/bin/zig build docs
if [ "${BUILD_REASON}" != "PullRequest" ]; then
mv ../LICENSE release/
diff --git a/ci/azure/windows_msvc_script.bat b/ci/azure/windows_msvc_script.bat
index df1b63b485..a073650717 100644
--- a/ci/azure/windows_msvc_script.bat
+++ b/ci/azure/windows_msvc_script.bat
@@ -26,6 +26,10 @@ cd %ZIGBUILDDIR%
cmake.exe .. -Thost=x64 -G"Visual Studio 16 2019" -A x64 "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release -DZIG_OMIT_STAGE2=ON || exit /b
msbuild /maxcpucount /p:Configuration=Release INSTALL.vcxproj || exit /b
+REM Sadly, stage2 is omitted from this build to save memory on the CI server. Once self-hosted is
+REM built with itself and does not gobble as much memory, we can enable these tests.
+REM "%ZIGINSTALLDIR%\bin\zig.exe" test "..\test\behavior.zig" -fno-stage1 -fLLVM -I "..\test" || exit /b
+
"%ZIGINSTALLDIR%\bin\zig.exe" build test-toolchain -Dskip-non-native -Dskip-stage2-tests || exit /b
"%ZIGINSTALLDIR%\bin\zig.exe" build test-std -Dskip-non-native || exit /b
"%ZIGINSTALLDIR%\bin\zig.exe" build docs || exit /b
diff --git a/ci/srht/freebsd_script b/ci/srht/freebsd_script
index 44b0330542..27c7df4933 100755
--- a/ci/srht/freebsd_script
+++ b/ci/srht/freebsd_script
@@ -38,6 +38,11 @@ cmake .. \
-GNinja
samu install
+# TODO ld.lld: error: undefined symbol: main
+# >>> referenced by crt1_c.c:75 (/usr/src/lib/csu/amd64/crt1_c.c:75)
+# >>> /usr/lib/crt1.o:(_start)
+#release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test
+
# Here we skip some tests to save time.
release/bin/zig build test -Dskip-compile-errors -Dskip-non-native
diff --git a/ci/srht/netbsd_script b/ci/srht/netbsd_script
index 508da4b324..f2d2f09467 100755
--- a/ci/srht/netbsd_script
+++ b/ci/srht/netbsd_script
@@ -51,6 +51,11 @@ samu install
unset CC
unset CXX
+# TODO ld.lld: error: undefined symbol: main
+#>>> referenced by crt0-common.c
+#>>> /usr/lib/crt0.o:(___start)
+#release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test
+
# Here we skip some tests to save time.
release/bin/zig build test -Dskip-compile-errors -Dskip-non-native
From 8028e46f0150842df4ac6fc050dca8dc58ae5f18 Mon Sep 17 00:00:00 2001
From: Evan Haas
Date: Mon, 19 Apr 2021 12:15:38 -0700
Subject: [PATCH 19/96] translate-c: handle signed array subscripts
A rather complicated workaround for handling signed array subscripts.
Once `[*]T + isize` is allowed, this can be removed.
Fixes #8556
---
src/translate_c.zig | 103 ++++++++++++++++++++++++++++++++++----
test/run_translated_c.zig | 40 +++++++++++++++
2 files changed, 133 insertions(+), 10 deletions(-)
diff --git a/src/translate_c.zig b/src/translate_c.zig
index fb40344b34..8b465fff96 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -3273,30 +3273,113 @@ fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, re
return maybeSuppressResult(c, scope, result_used, node);
}
+/// ptr[subscr] (`subscr` is a signed integer expression, `ptr` a pointer) becomes:
+/// (blk: {
+/// const tmp = subscr;
+/// if (tmp >= 0) break :blk ptr + @intCast(usize, tmp) else break :blk ptr - ~@bitCast(usize, @intCast(isize, tmp) +% -1);
+/// }).*
+/// Todo: rip this out once `[*]T + isize` becomes valid.
+fn transSignedArrayAccess(
+ c: *Context,
+ scope: *Scope,
+ container_expr: *const clang.Expr,
+ subscr_expr: *const clang.Expr,
+ result_used: ResultUsed,
+) TransError!Node {
+ var block_scope = try Scope.Block.init(c, scope, true);
+ defer block_scope.deinit();
+
+ const tmp = try block_scope.makeMangledName(c, "tmp");
+
+ const subscr_node = try transExpr(c, &block_scope.base, subscr_expr, .used);
+ const subscr_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = subscr_node });
+ try block_scope.statements.append(subscr_decl);
+
+ const tmp_ref = try Tag.identifier.create(c.arena, tmp);
+
+ const container_node = try transExpr(c, &block_scope.base, container_expr, .used);
+
+ const cond_node = try Tag.greater_than_equal.create(c.arena, .{ .lhs = tmp_ref, .rhs = Tag.zero_literal.init() });
+
+ const then_value = try Tag.add.create(c.arena, .{
+ .lhs = container_node,
+ .rhs = try Tag.int_cast.create(c.arena, .{
+ .lhs = try Tag.identifier.create(c.arena, "usize"),
+ .rhs = tmp_ref,
+ }),
+ });
+
+ const then_body = try Tag.break_val.create(c.arena, .{
+ .label = block_scope.label,
+ .val = then_value,
+ });
+
+ const minuend = container_node;
+ const signed_size = try Tag.int_cast.create(c.arena, .{
+ .lhs = try Tag.identifier.create(c.arena, "isize"),
+ .rhs = tmp_ref,
+ });
+ const to_cast = try Tag.add_wrap.create(c.arena, .{
+ .lhs = signed_size,
+ .rhs = try Tag.negate.create(c.arena, Tag.one_literal.init()),
+ });
+ const bitcast_node = try Tag.bit_cast.create(c.arena, .{
+ .lhs = try Tag.identifier.create(c.arena, "usize"),
+ .rhs = to_cast,
+ });
+ const subtrahend = try Tag.bit_not.create(c.arena, bitcast_node);
+ const difference = try Tag.sub.create(c.arena, .{
+ .lhs = minuend,
+ .rhs = subtrahend,
+ });
+ const else_body = try Tag.break_val.create(c.arena, .{
+ .label = block_scope.label,
+ .val = difference,
+ });
+
+ const if_node = try Tag.@"if".create(c.arena, .{
+ .cond = cond_node,
+ .then = then_body,
+ .@"else" = else_body,
+ });
+
+ try block_scope.statements.append(if_node);
+ const block_node = try block_scope.complete(c);
+
+ const derefed = try Tag.deref.create(c.arena, block_node);
+
+ return maybeSuppressResult(c, &block_scope.base, result_used, derefed);
+}
+
fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscriptExpr, result_used: ResultUsed) TransError!Node {
- var base_stmt = stmt.getBase();
+ const base_stmt = stmt.getBase();
+ const base_qt = getExprQualType(c, base_stmt);
+ const is_vector = cIsVector(base_qt);
+
+ const subscr_expr = stmt.getIdx();
+ const subscr_qt = getExprQualType(c, subscr_expr);
+ const is_longlong = cIsLongLongInteger(subscr_qt);
+ const is_signed = cIsSignedInteger(subscr_qt);
// Unwrap the base statement if it's an array decayed to a bare pointer type
// so that we index the array itself
+ var unwrapped_base = base_stmt;
if (@ptrCast(*const clang.Stmt, base_stmt).getStmtClass() == .ImplicitCastExprClass) {
const implicit_cast = @ptrCast(*const clang.ImplicitCastExpr, base_stmt);
if (implicit_cast.getCastKind() == .ArrayToPointerDecay) {
- base_stmt = implicit_cast.getSubExpr();
+ unwrapped_base = implicit_cast.getSubExpr();
}
}
- const container_node = try transExpr(c, scope, base_stmt, .used);
-
- // cast if the index is long long or signed
- const subscr_expr = stmt.getIdx();
- const qt = getExprQualType(c, subscr_expr);
- const is_longlong = cIsLongLongInteger(qt);
- const is_signed = cIsSignedInteger(qt);
+ // Special case: actual pointer (not decayed array) and signed integer subscript
+ // See discussion at https://github.com/ziglang/zig/pull/8589
+ if (is_signed and (base_stmt == unwrapped_base) and !is_vector) return transSignedArrayAccess(c, scope, base_stmt, subscr_expr, result_used);
+ const container_node = try transExpr(c, scope, unwrapped_base, .used);
const rhs = if (is_longlong or is_signed) blk: {
// check if long long first so that signed long long doesn't just become unsigned long long
- var typeid_node = if (is_longlong) try Tag.identifier.create(c.arena, "usize") else try transQualTypeIntWidthOf(c, qt, false);
+ const typeid_node = if (is_longlong) try Tag.identifier.create(c.arena, "usize") else try transQualTypeIntWidthOf(c, subscr_qt, false);
break :blk try Tag.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used) });
} else try transExpr(c, scope, subscr_expr, .used);
diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig
index dab200af0d..2e579b06c7 100644
--- a/test/run_translated_c.zig
+++ b/test/run_translated_c.zig
@@ -1709,4 +1709,44 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
+
+ cases.add("signed array subscript. Issue #8556",
+ \\#include
+ \\#include
+ \\#define TEST_NEGATIVE(type) { type x = -1; if (ptr[x] != 42) abort(); }
+ \\#define TEST_UNSIGNED(type) { type x = 2; if (arr[x] != 42) abort(); }
+ \\int main(void) {
+ \\ int arr[] = {40, 41, 42, 43};
+ \\ int *ptr = arr + 3;
+ \\ if (ptr[-1] != 42) abort();
+ \\ TEST_NEGATIVE(int);
+ \\ TEST_NEGATIVE(long);
+ \\ TEST_NEGATIVE(long long);
+ \\ TEST_NEGATIVE(int64_t);
+ \\ TEST_NEGATIVE(__int128);
+ \\ TEST_UNSIGNED(unsigned);
+ \\ TEST_UNSIGNED(unsigned long);
+ \\ TEST_UNSIGNED(unsigned long long);
+ \\ TEST_UNSIGNED(uint64_t);
+ \\ TEST_UNSIGNED(size_t);
+ \\ TEST_UNSIGNED(unsigned __int128);
+ \\ return 0;
+ \\}
+ , "");
+
+ cases.add("Ensure side-effects only evaluated once for signed array indices",
+ \\#include
+ \\int main(void) {
+ \\ int foo[] = {1, 2, 3, 4};
+ \\ int *p = foo;
+ \\ int idx = 1;
+ \\ if ((++p)[--idx] != 2) abort();
+ \\ if (p != foo + 1) abort();
+ \\ if (idx != 0) abort();
+ \\ if ((p++)[idx++] != 2) abort();
+ \\ if (p != foo + 2) abort();
+ \\ if (idx != 1) abort();
+ \\ return 0;
+ \\}
+ , "");
}
From 9c028b2078649941366663c6b9a7ed7983c1621e Mon Sep 17 00:00:00 2001
From: Zach Banks
Date: Fri, 23 Apr 2021 14:24:58 -0400
Subject: [PATCH 20/96] std/ArrayList: Allow `ArrayList(u0)` to be created
Enable creating ArrayList with zero-sized types.
This type still tracks length, but does not allocate
additional memory.
---
lib/std/array_list.zig | 77 ++++++++++++++++++++++++++++++------------
1 file changed, 56 insertions(+), 21 deletions(-)
diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig
index 8b46ec2145..1e74d34922 100644
--- a/lib/std/array_list.zig
+++ b/lib/std/array_list.zig
@@ -65,16 +65,23 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
var self = Self.init(allocator);
- const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least);
- self.items.ptr = new_memory.ptr;
- self.capacity = new_memory.len;
+ if (@sizeOf(T) > 0) {
+ const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least);
+ self.items.ptr = new_memory.ptr;
+ self.capacity = new_memory.len;
+ } else {
+ // If `T` is a zero-sized type, then we do not need to allocate memory.
+ self.capacity = std.math.maxInt(usize);
+ }
return self;
}
/// Release all allocated memory.
pub fn deinit(self: Self) void {
- self.allocator.free(self.allocatedSlice());
+ if (@sizeOf(T) > 0) {
+ self.allocator.free(self.allocatedSlice());
+ }
}
pub const span = @compileError("deprecated: use `items` field directly");
@@ -279,13 +286,17 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
pub fn shrinkAndFree(self: *Self, new_len: usize) void {
assert(new_len <= self.items.len);
- self.items = self.allocator.realloc(self.allocatedSlice(), new_len) catch |e| switch (e) {
- error.OutOfMemory => { // no problem, capacity is still correct then.
- self.items.len = new_len;
- return;
- },
- };
- self.capacity = new_len;
+ if (@sizeOf(T) > 0) {
+ self.items = self.allocator.realloc(self.allocatedSlice(), new_len) catch |e| switch (e) {
+ error.OutOfMemory => { // no problem, capacity is still correct then.
+ self.items.len = new_len;
+ return;
+ },
+ };
+ self.capacity = new_len;
+ } else {
+ self.items.len = new_len;
+ }
}
/// Reduce length to `new_len`.
@@ -313,18 +324,22 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
/// Modify the array so that it can hold at least `new_capacity` items.
/// Invalidates pointers if additional memory is needed.
pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) !void {
- var better_capacity = self.capacity;
- if (better_capacity >= new_capacity) return;
+ if (@sizeOf(T) > 0) {
+ var better_capacity = self.capacity;
+ if (better_capacity >= new_capacity) return;
- while (true) {
- better_capacity += better_capacity / 2 + 8;
- if (better_capacity >= new_capacity) break;
+ while (true) {
+ better_capacity += better_capacity / 2 + 8;
+ if (better_capacity >= new_capacity) break;
+ }
+
+ // TODO This can be optimized to avoid needlessly copying undefined memory.
+ const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);
+ self.items.ptr = new_memory.ptr;
+ self.capacity = new_memory.len;
+ } else {
+ self.capacity = std.math.maxInt(usize);
}
-
- // TODO This can be optimized to avoid needlessly copying undefined memory.
- const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);
- self.items.ptr = new_memory.ptr;
- self.capacity = new_memory.len;
}
/// Modify the array so that it can hold at least `additional_count` **more** items.
@@ -1299,3 +1314,23 @@ test "ArrayListAligned/ArrayListAlignedUnmanaged accepts unaligned slices" {
try testing.expectEqualSlices(u8, list.items, &.{ 0, 8, 9, 6, 7, 2, 3 });
}
}
+
+test "std.ArrayList(u0)" {
+ // An ArrayList on zero-sized types should not need to allocate
+ const a = &testing.FailingAllocator.init(testing.allocator, 0).allocator;
+
+ var list = ArrayList(u0).init(a);
+ defer list.deinit();
+
+ try list.append(0);
+ try list.append(0);
+ try list.append(0);
+ try testing.expectEqual(list.items.len, 3);
+
+ var count: usize = 0;
+ for (list.items) |x| {
+ try testing.expectEqual(x, 0);
+ count += 1;
+ }
+ try testing.expectEqual(count, 3);
+}
From 2f9e498c6fa0395e4318b2359291353b495a94e1 Mon Sep 17 00:00:00 2001
From: Matt Knight
Date: Wed, 28 Jul 2021 07:38:36 -0700
Subject: [PATCH 21/96] add build dependency when linkerscript is a generated
file
---
lib/std/build.zig | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/std/build.zig b/lib/std/build.zig
index 685fd2bdc5..a88667a613 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -1731,6 +1731,7 @@ pub const LibExeObjStep = struct {
pub fn setLinkerScriptPath(self: *LibExeObjStep, source: FileSource) void {
self.linker_script = source.dupe(self.builder);
+ source.addStepDependencies(&self.step);
}
pub fn linkFramework(self: *LibExeObjStep, framework_name: []const u8) void {
From f5d9d739d70f5d99756e277cc7c77484d60ddf42 Mon Sep 17 00:00:00 2001
From: Belhorma Bendebiche
Date: Fri, 23 Jul 2021 12:43:38 -0400
Subject: [PATCH 22/96] stage1: Expand SysV C ABI support for small structs
While the SysV ABI is not that complicated, LLVM does not allow us
direct access to enforce it. By mimicking the IR generated by clang,
we can trick LLVM into doing the right thing. This involves two main
additions:
1. `AGG` ABI class
This is not part of the spec, but since we have to track class per
eightbyte and not per struct, the current enum is not enough. I
considered adding multiple classes like: `INTEGER_INTEGER`,
`INTEGER_SSE`, `SSE_INTEGER`. However, all of those cases would trigger
the same code path so it's simpler to collapse into one. This class is
only used on SysV.
2. LLVM C ABI type
Clang uses different types in C ABI function signatures than the
original structs passed in, and does conversion. For example, this
struct: `{ i8, i8, float }` would use `{ i16, float }` at ABI boundaries.
When passed as an argument, it is instead split into two arguments `i16`
and `float`. Therefore, for every struct that passes ABI boundaries we
need to keep track of its corresponding ABI type. Here are some more
examples:
```
| Struct | ABI equivalent |
| { i8, i8, i8, i8 } | i32 |
| { float, float } | double |
| { float, i32, i8 } | { float, i64 } |
```
Then, we must update function calls, returns, parameter lists and inits
to properly convert back and forth as needed.
---
src/stage1/all_types.hpp | 5 +-
src/stage1/analyze.cpp | 124 +++++++++++++++++++++++++++-
src/stage1/analyze.hpp | 3 +
src/stage1/codegen.cpp | 160 +++++++++++++++++++++++++++----------
test/stage1/c_abi/cfuncs.c | 89 +++++++++++++++++++++
test/stage1/c_abi/main.zig | 87 ++++++++++++++++++++
6 files changed, 419 insertions(+), 49 deletions(-)
diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp
index a72faa15ce..dfebc66cfd 100644
--- a/src/stage1/all_types.hpp
+++ b/src/stage1/all_types.hpp
@@ -107,6 +107,7 @@ enum X64CABIClass {
X64CABIClass_MEMORY_nobyval,
X64CABIClass_INTEGER,
X64CABIClass_SSE,
+ X64CABIClass_AGG,
};
struct Stage1Zir {
@@ -1569,8 +1570,9 @@ struct ZigType {
// These are not supposed to be accessed directly. They're
// null during semantic analysis, memoized with get_llvm_type
- // and get_llvm_di_type
+ // get_llvm_c_abi_type and get_llvm_di_type
LLVMTypeRef llvm_type;
+ LLVMTypeRef llvm_c_abi_type;
ZigLLVMDIType *llvm_di_type;
union {
@@ -1624,6 +1626,7 @@ struct GlobalExport {
struct ZigFn {
LLVMValueRef llvm_value;
+ LLVMValueRef abi_return_value; // alloca used when converting at SysV ABI boundaries
const char *llvm_name;
AstNode *proto_node;
AstNode *body_node;
diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp
index 501e43373d..cf61bf79b7 100644
--- a/src/stage1/analyze.cpp
+++ b/src/stage1/analyze.cpp
@@ -6063,6 +6063,12 @@ Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result) {
return ErrorNone;
}
+bool fn_returns_c_abi_small_struct(FnTypeId *fn_type_id) {
+ ZigType *type = fn_type_id->return_type;
+ return !calling_convention_allows_zig_types(fn_type_id->cc) &&
+ type->id == ZigTypeIdStruct && type->abi_size <= 16;
+}
+
// Whether you can infer the value based solely on the type.
OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
assert(type_entry != nullptr);
@@ -8376,6 +8382,9 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size
// be memory.
return X64CABIClass_MEMORY;
}
+ // "If the size of the aggregate exceeds a single eightbyte, each is classified
+ // separately.".
+ // "If one of the classes is MEMORY, the whole argument is passed in memory"
X64CABIClass working_class = X64CABIClass_Unknown;
for (uint32_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields[0]->type_entry);
@@ -8385,7 +8394,10 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size
working_class = field_class;
}
}
- return working_class;
+ if (working_class == X64CABIClass_MEMORY) {
+ return X64CABIClass_MEMORY;
+ }
+ return X64CABIClass_AGG;
}
case ZigTypeIdUnion: {
// "If the size of an object is larger than four eightbytes, or it contains unaligned
@@ -8407,7 +8419,7 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size
X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.unionation.fields->type_entry);
if (field_class == X64CABIClass_Unknown)
return X64CABIClass_Unknown;
- if (i == 0 || field_class == X64CABIClass_MEMORY || working_class == X64CABIClass_SSE) {
+ if (i == 0 || field_class == X64CABIClass_MEMORY || field_class == X64CABIClass_INTEGER || working_class == X64CABIClass_SSE) {
working_class = field_class;
}
}
@@ -8678,6 +8690,95 @@ static LLVMTypeRef get_llvm_type_of_n_bytes(unsigned byte_size) {
LLVMInt8Type() : LLVMArrayType(LLVMInt8Type(), byte_size);
}
+static LLVMTypeRef llvm_int_for_size(size_t size) {
+ if (size > 4) {
+ return LLVMInt64Type();
+ } else if (size > 2) {
+ return LLVMInt32Type();
+ } else if (size == 2) {
+ return LLVMInt16Type();
+ } else {
+ return LLVMInt8Type();
+ }
+}
+
+static LLVMTypeRef llvm_sse_for_size(size_t size) {
+ if (size > 4)
+ return LLVMDoubleType();
+ else
+ return LLVMFloatType();
+}
+
+// Since it's not possible to control calling convention or register
+// allocation in LLVM, clang seems to use intermediate types to manipulate
+// LLVM into doing the right thing. It uses a float to force SSE registers,
+// and a struct when 2 registers must be used. Some examples:
+// { f32 } -> float
+// { f32, i32 } -> { float, i32 }
+// { i32, i32, f32 } -> { i64, float }
+//
+// The implementation below does not match clang 1:1. For instance, clang
+// uses `<2x float>` while we generate `double`. There's a lot more edge
+// cases and complexity when converting back and forth in clang though,
+// so below is the simplest implementation that passes all tests.
+static Error resolve_llvm_c_abi_type(CodeGen *g, ZigType *ty) {
+ size_t ty_size = type_size(g, ty);
+ LLVMTypeRef abi_type;
+ switch (ty->id) {
+ case ZigTypeIdEnum:
+ case ZigTypeIdInt:
+ case ZigTypeIdBool:
+ abi_type = llvm_int_for_size(ty_size);
+ break;
+ case ZigTypeIdFloat:
+ case ZigTypeIdVector:
+ abi_type = llvm_sse_for_size(ty_size);
+ break;
+ case ZigTypeIdStruct: {
+ uint32_t eightbyte_index = 0;
+ size_t type_sizes[] = {0, 0};
+ X64CABIClass type_classes[] = {X64CABIClass_Unknown, X64CABIClass_Unknown};
+ for (uint32_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
+ if (ty->data.structure.fields[i]->offset >= 8) {
+ eightbyte_index = 1;
+ }
+ X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields[i]->type_entry);
+
+ if (field_class == X64CABIClass_INTEGER) {
+ type_classes[eightbyte_index] = X64CABIClass_INTEGER;
+ } else if (type_classes[eightbyte_index] == X64CABIClass_Unknown) {
+ type_classes[eightbyte_index] = field_class;
+ }
+ type_sizes[eightbyte_index] += ty->data.structure.fields[i]->type_entry->abi_size;
+ }
+
+ LLVMTypeRef return_elem_types[] = {
+ LLVMVoidType(),
+ LLVMVoidType(),
+ };
+ for (uint32_t i = 0; i <= eightbyte_index; i += 1) {
+ if (type_classes[i] == X64CABIClass_INTEGER) {
+ return_elem_types[i] = llvm_int_for_size(type_sizes[i]);
+ } else {
+ return_elem_types[i] = llvm_sse_for_size(type_sizes[i]);
+ }
+ }
+ if (eightbyte_index == 0) {
+ abi_type = return_elem_types[0];
+ } else {
+ abi_type = LLVMStructType(return_elem_types, 2, false);
+ }
+ break;
+ }
+ case ZigTypeIdUnion:
+ default:
+ // currently unreachable
+ zig_panic("TODO: support C ABI unions");
+ }
+ ty->llvm_c_abi_type = abi_type;
+ return ErrorNone;
+}
+
static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status,
ZigType *async_frame_type)
{
@@ -8936,6 +9037,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
g->type_resolve_stack.swap_remove(struct_type->data.structure.llvm_full_type_queue_index);
struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;
}
+
+ if (struct_type->abi_size <= 16 && struct_type->data.structure.layout == ContainerLayoutExtern)
+ resolve_llvm_c_abi_type(g, struct_type);
}
// This is to be used instead of void for debug info types, to avoid tripping
@@ -9536,8 +9640,13 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
assert(gen_param_types.items[i] != nullptr);
}
- fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),
- gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
+ if (!first_arg_return && fn_returns_c_abi_small_struct(fn_type_id)) {
+ fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_c_abi_type(g, gen_return_type),
+ gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
+ } else {
+ fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),
+ gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
+ }
const unsigned fn_addrspace = ZigLLVMDataLayoutGetProgramAddressSpace(g->target_data_ref);
fn_type->llvm_type = LLVMPointerType(fn_type->data.fn.raw_type_ref, fn_addrspace);
fn_type->data.fn.raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
@@ -9827,6 +9936,13 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
zig_unreachable();
}
+LLVMTypeRef get_llvm_c_abi_type(CodeGen *g, ZigType *type) {
+ assertNoError(type_resolve(g, type, ResolveStatusLLVMFull));
+ assert(type->abi_size == 0 || type->abi_size >= LLVMABISizeOfType(g->target_data_ref, type->llvm_type));
+ assert(type->abi_align == 0 || type->abi_align >= LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type));
+ return type->llvm_c_abi_type;
+}
+
LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type) {
assertNoError(type_resolve(g, type, ResolveStatusLLVMFull));
assert(type->abi_size == 0 || type->abi_size >= LLVMABISizeOfType(g->target_data_ref, type->llvm_type));
diff --git a/src/stage1/analyze.hpp b/src/stage1/analyze.hpp
index 22951db0f0..8290ef572c 100644
--- a/src/stage1/analyze.hpp
+++ b/src/stage1/analyze.hpp
@@ -54,6 +54,8 @@ uint32_t get_async_frame_align_bytes(CodeGen *g);
bool type_has_bits(CodeGen *g, ZigType *type_entry);
Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result);
+bool fn_returns_c_abi_small_struct(FnTypeId *fn_type_id);
+
enum ExternPosition {
ExternPositionFunctionParameter,
ExternPositionFunctionReturn,
@@ -268,6 +270,7 @@ Buf *type_bare_name(ZigType *t);
Buf *type_h_name(ZigType *t);
LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type);
+LLVMTypeRef get_llvm_c_abi_type(CodeGen *g, ZigType *type);
ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);
void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_path, bool translate_c,
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp
index 083d15068a..dcb69ca64a 100644
--- a/src/stage1/codegen.cpp
+++ b/src/stage1/codegen.cpp
@@ -2142,75 +2142,103 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
}
}
return true;
- } else if (abi_class == X64CABIClass_SSE) {
- // For now only handle structs with only floats/doubles in it.
- if (ty->id != ZigTypeIdStruct) {
- if (source_node != nullptr) {
- give_up_with_c_abi_error(g, source_node);
- }
- // otherwise allow codegen code to report a compile error
- return false;
- }
-
- for (uint32_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
- if (ty->data.structure.fields[i]->type_entry->id != ZigTypeIdFloat) {
- if (source_node != nullptr) {
- give_up_with_c_abi_error(g, source_node);
- }
- // otherwise allow codegen code to report a compile error
- return false;
- }
- }
-
- // The SystemV ABI says that we have to setup 1 FP register per f64.
+ } else if (abi_class == X64CABIClass_AGG) {
+ // The SystemV ABI says that we have to setup 1 register per eightbyte.
// So two f32 can be passed in one f64, but 3 f32 have to be passed in 2 FP registers.
- // To achieve this with LLVM API, we pass multiple f64 parameters to the LLVM function if
- // the type is bigger than 8 bytes.
+ // Similarly, two i32 can be passed in one i64, but 3 i32 have to be passed in 2 registers.
+ // LLVM does not allow us to control registers in this way, nor to request specific
+ // ABI conventions. So we have to trick it into allocating the right registers, based
+ // on how clang does it.
+
+ // First, we get the LLVM type corresponding to the C abi for the struct, then
+ // we pass each field as an argument.
// Example:
// extern struct {
// x: f32,
// y: f32,
- // z: f32,
+ // z: i32,
// };
- // const ptr = (*f64)*Struct;
- // Register 1: ptr.*
- // Register 2: (ptr + 1).*
+ // LLVM abi type: { double, i32 }
+ // const ptr = (*abi_type)*Struct;
+ // FP Register 1: abi_type[0]
+ // Register 1: abi_type[1]
- // One floating point register per f64 or 2 f32's
- size_t number_of_fp_regs = (ty_size + 7) / 8;
+ // However, if the struct fits in one register, then we'll pass it as such
+ size_t number_of_regs = (size_t)ceilf((float)ty_size / (float)8);
+
+ LLVMTypeRef abi_type = get_llvm_c_abi_type(g, ty);
+
+ assert(ty_size <= 16);
switch (fn_walk->id) {
case FnWalkIdAttrs: {
- fn_walk->data.attrs.gen_i += number_of_fp_regs;
+ fn_walk->data.attrs.gen_i += number_of_regs;
break;
}
case FnWalkIdCall: {
- LLVMValueRef f64_ptr_to_struct = LLVMBuildBitCast(g->builder, val, LLVMPointerType(LLVMDoubleType(), 0), "");
- for (uint32_t i = 0; i < number_of_fp_regs; i += 1) {
- LLVMValueRef index = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, i, false);
- LLVMValueRef indices[] = { index };
- LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP(g->builder, f64_ptr_to_struct, indices, 1, "");
+ LLVMValueRef abi_ptr_to_struct = LLVMBuildBitCast(g->builder, val, LLVMPointerType(abi_type, 0), "");
+ if (number_of_regs == 1) {
+ LLVMValueRef loaded = LLVMBuildLoad(g->builder, abi_ptr_to_struct, "");
+ fn_walk->data.call.gen_param_values->append(loaded);
+ break;
+ }
+ for (uint32_t i = 0; i < number_of_regs; i += 1) {
+ LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, false);
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, false);
+ LLVMValueRef indices[] = { zero, index };
+ LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP(g->builder, abi_ptr_to_struct, indices, 2, "");
LLVMValueRef loaded = LLVMBuildLoad(g->builder, adjusted_ptr_to_struct, "");
fn_walk->data.call.gen_param_values->append(loaded);
}
break;
}
case FnWalkIdTypes: {
- for (uint32_t i = 0; i < number_of_fp_regs; i += 1) {
- fn_walk->data.types.gen_param_types->append(get_llvm_type(g, g->builtin_types.entry_f64));
+ if (number_of_regs == 1) {
+ fn_walk->data.types.gen_param_types->append(abi_type);
+ fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, g->builtin_types.entry_f64));
+ break;
+ }
+ for (uint32_t i = 0; i < number_of_regs; i += 1) {
+ fn_walk->data.types.gen_param_types->append(LLVMStructGetTypeAtIndex(abi_type, i));
fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, g->builtin_types.entry_f64));
}
break;
}
- case FnWalkIdVars:
+ case FnWalkIdVars: {
+ var->value_ref = build_alloca(g, ty, var->name, var->align_bytes);
+ di_arg_index = fn_walk->data.vars.gen_i;
+ fn_walk->data.vars.gen_i += 1;
+ dest_ty = ty;
+ goto var_ok;
+ }
case FnWalkIdInits: {
- // TODO: Handle exporting functions
- if (source_node != nullptr) {
- give_up_with_c_abi_error(g, source_node);
+ // since we're representing the struct differently as an arg, and potentially
+ // splitting it, we have to do some work to put it back together.
+ // the one reg case is straightforward, but if we used two registers we have
+ // to iterate through the struct abi repr fields and load them one by one.
+ if (number_of_regs == 1) {
+ LLVMValueRef arg = LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i);
+ LLVMTypeRef ptr_to_int_type_ref = LLVMPointerType(abi_type, 0);
+ LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, var->value_ref, ptr_to_int_type_ref, "");
+ gen_store_untyped(g, arg, bitcasted, var->align_bytes, false);
+ } else {
+ LLVMValueRef abi_ptr_to_struct = LLVMBuildBitCast(g->builder, var->value_ref, LLVMPointerType(abi_type, 0), "");
+ for (uint32_t i = 0; i < number_of_regs; i += 1) {
+ LLVMValueRef arg = LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i + i);
+ LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, false);
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, false);
+ LLVMValueRef indices[] = { zero, index };
+ LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP(g->builder, abi_ptr_to_struct, indices, 2, "");
+ LLVMBuildStore(g->builder, arg, adjusted_ptr_to_struct);
+ }
+ fn_walk->data.inits.gen_i += 1;
}
- // otherwise allow codegen code to report a compile error
- return false;
+ if (var->decl_node) {
+ gen_var_debug_decl(g, var);
+ }
+ fn_walk->data.inits.gen_i += 1;
+ break;
}
}
return true;
@@ -2654,13 +2682,36 @@ static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) {
LLVMBuildRetVoid(g->builder);
}
+static LLVMValueRef gen_convert_to_c_abi(CodeGen *g, LLVMValueRef location, LLVMValueRef value) {
+ ZigType *return_type = g->cur_fn->type_entry->data.fn.gen_return_type;
+ size_t size = type_size(g, return_type);
+
+ LLVMTypeRef abi_return_type = get_llvm_c_abi_type(g, return_type);
+ LLVMTypeRef abi_return_type_pointer = LLVMPointerType(abi_return_type, 0);
+
+ if (size < 8) {
+ LLVMValueRef bitcast = LLVMBuildBitCast(g->builder, value, abi_return_type_pointer, "");
+ return LLVMBuildLoad(g->builder, bitcast, "");
+ } else {
+ LLVMTypeRef i8ptr = LLVMPointerType(LLVMInt8Type(), 0);
+ LLVMValueRef bc_location = LLVMBuildBitCast(g->builder, location, i8ptr, "");
+ LLVMValueRef bc_value = LLVMBuildBitCast(g->builder, value, i8ptr, "");
+
+ LLVMValueRef len = LLVMConstInt(LLVMInt64Type(), size, false);
+ ZigLLVMBuildMemCpy(g->builder, bc_location, 8, bc_value, return_type->abi_align, len, false);
+ return LLVMBuildLoad(g->builder, location, "");
+ }
+}
+
static LLVMValueRef ir_render_return(CodeGen *g, Stage1Air *executable, Stage1AirInstReturn *instruction) {
if (fn_is_async(g->cur_fn)) {
gen_async_return(g, instruction);
return nullptr;
}
- if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
+ FnTypeId *fn_type_id = &g->cur_fn->type_entry->data.fn.fn_type_id;
+
+ if (want_first_arg_sret(g, fn_type_id)) {
if (instruction->operand == nullptr) {
LLVMBuildRetVoid(g->builder);
return nullptr;
@@ -2671,6 +2722,16 @@ static LLVMValueRef ir_render_return(CodeGen *g, Stage1Air *executable, Stage1Ai
ZigType *return_type = instruction->operand->value->type;
gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
LLVMBuildRetVoid(g->builder);
+ } else if (fn_returns_c_abi_small_struct(fn_type_id)) {
+ LLVMValueRef location = g->cur_fn->abi_return_value;
+ if (instruction->operand == nullptr) {
+ LLVMValueRef converted = gen_convert_to_c_abi(g, location, g->cur_ret_ptr);
+ LLVMBuildRet(g->builder, converted);
+ } else {
+ LLVMValueRef value = ir_llvm_value(g, instruction->operand);
+ LLVMValueRef converted = gen_convert_to_c_abi(g, location, value);
+ LLVMBuildRet(g->builder, converted);
+ }
} else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync &&
handle_is_ptr(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type))
{
@@ -4678,6 +4739,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI
} else if (first_arg_ret) {
ZigLLVMSetCallSret(result, get_llvm_type(g, src_return_type));
return result_loc;
+ } else if (fn_returns_c_abi_small_struct(fn_type_id)) {
+ LLVMTypeRef abi_type = get_llvm_c_abi_type(g, src_return_type);
+ LLVMTypeRef abi_type_ptr = LLVMPointerType(abi_type, 0);
+ LLVMValueRef bitcast = LLVMBuildBitCast(g->builder, result_loc, abi_type_ptr, "");
+ LLVMBuildStore(g->builder, result, bitcast);
+ return result_loc;
} else if (handle_is_ptr(g, src_return_type)) {
LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value->type));
@@ -8291,6 +8358,11 @@ static void do_code_gen(CodeGen *g) {
g->cur_err_ret_trace_val_stack = nullptr;
}
+ if (fn_returns_c_abi_small_struct(fn_type_id)) {
+ LLVMTypeRef abi_type = get_llvm_c_abi_type(g, fn_type_id->return_type);
+ fn_table_entry->abi_return_value = LLVMBuildAlloca(g->builder, abi_type, "");
+ }
+
if (!is_async) {
// allocate async frames for nosuspend calls & awaits to async functions
ZigType *largest_call_frame_type = nullptr;
diff --git a/test/stage1/c_abi/cfuncs.c b/test/stage1/c_abi/cfuncs.c
index a3b8c9a8c6..0182462716 100644
--- a/test/stage1/c_abi/cfuncs.c
+++ b/test/stage1/c_abi/cfuncs.c
@@ -61,7 +61,20 @@ struct SmallStructInts {
uint8_t c;
uint8_t d;
};
+
void zig_small_struct_ints(struct SmallStructInts);
+struct SmallStructInts zig_ret_small_struct_ints();
+
+struct MedStructMixed {
+ uint32_t a;
+ float b;
+ float c;
+ uint32_t d;
+};
+
+void zig_med_struct_mixed(struct MedStructMixed);
+struct MedStructMixed zig_ret_med_struct_mixed();
+
struct SplitStructInts {
uint64_t a;
@@ -70,6 +83,14 @@ struct SplitStructInts {
};
void zig_split_struct_ints(struct SplitStructInts);
+struct SplitStructMixed {
+ uint64_t a;
+ uint8_t b;
+ float c;
+};
+void zig_split_struct_mixed(struct SplitStructMixed);
+struct SplitStructMixed zig_ret_split_struct_mixed();
+
struct BigStruct zig_big_struct_both(struct BigStruct);
typedef struct Vector3 {
@@ -121,6 +142,16 @@ void run_c_tests(void) {
zig_split_struct_ints(s);
}
+ {
+ struct MedStructMixed s = {1234, 100.0f, 1337.0f};
+ zig_med_struct_mixed(s);
+ }
+
+ {
+ struct SplitStructMixed s = {1234, 100, 1337.0f};
+ zig_split_struct_mixed(s);
+ }
+
{
struct BigStruct s = {30, 31, 32, 33, 34};
struct BigStruct res = zig_big_struct_both(s);
@@ -230,6 +261,44 @@ void c_small_struct_ints(struct SmallStructInts x) {
assert_or_panic(x.b == 2);
assert_or_panic(x.c == 3);
assert_or_panic(x.d == 4);
+
+ struct SmallStructInts y = zig_ret_small_struct_ints();
+
+ assert_or_panic(y.a == 1);
+ assert_or_panic(y.b == 2);
+ assert_or_panic(y.c == 3);
+ assert_or_panic(y.d == 4);
+}
+
+struct SmallStructInts c_ret_small_struct_ints() {
+ struct SmallStructInts s = {
+ .a = 1,
+ .b = 2,
+ .c = 3,
+ .d = 4,
+ };
+ return s;
+}
+
+void c_med_struct_mixed(struct MedStructMixed x) {
+ assert_or_panic(x.a == 1234);
+ assert_or_panic(x.b == 100.0f);
+ assert_or_panic(x.c == 1337.0f);
+
+ struct MedStructMixed y = zig_ret_med_struct_mixed();
+
+ assert_or_panic(y.a == 1234);
+ assert_or_panic(y.b == 100.0f);
+ assert_or_panic(y.c == 1337.0f);
+}
+
+struct MedStructMixed c_ret_med_struct_mixed() {
+ struct MedStructMixed s = {
+ .a = 1234,
+ .b = 100.0,
+ .c = 1337.0,
+ };
+ return s;
}
void c_split_struct_ints(struct SplitStructInts x) {
@@ -238,6 +307,26 @@ void c_split_struct_ints(struct SplitStructInts x) {
assert_or_panic(x.c == 1337);
}
+void c_split_struct_mixed(struct SplitStructMixed x) {
+ assert_or_panic(x.a == 1234);
+ assert_or_panic(x.b == 100);
+ assert_or_panic(x.c == 1337.0f);
+ struct SplitStructMixed y = zig_ret_split_struct_mixed();
+
+ assert_or_panic(y.a == 1234);
+ assert_or_panic(y.b == 100);
+ assert_or_panic(y.c == 1337.0f);
+}
+
+struct SplitStructMixed c_ret_split_struct_mixed() {
+ struct SplitStructMixed s = {
+ .a = 1234,
+ .b = 100,
+ .c = 1337.0f,
+ };
+ return s;
+}
+
struct BigStruct c_big_struct_both(struct BigStruct x) {
assert_or_panic(x.a == 1);
assert_or_panic(x.b == 2);
diff --git a/test/stage1/c_abi/main.zig b/test/stage1/c_abi/main.zig
index ed5cad7c56..b8137334ec 100644
--- a/test/stage1/c_abi/main.zig
+++ b/test/stage1/c_abi/main.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const print = std.debug.print;
const expect = std.testing.expect;
extern fn run_c_tests() void;
@@ -170,6 +171,34 @@ export fn zig_big_union(x: BigUnion) void {
expect(x.a.e == 5) catch @panic("test failure");
}
+const MedStructMixed = extern struct {
+ a: u32,
+ b: f32,
+ c: f32,
+ d: u32 = 0,
+};
+extern fn c_med_struct_mixed(MedStructMixed) void;
+extern fn c_ret_med_struct_mixed() MedStructMixed;
+
+test "C ABI medium struct of ints and floats" {
+ var s = MedStructMixed{
+ .a = 1234,
+ .b = 100.0,
+ .c = 1337.0,
+ };
+ c_med_struct_mixed(s);
+ var s2 = c_ret_med_struct_mixed();
+ expect(s2.a == 1234) catch @panic("test failure");
+ expect(s2.b == 100.0) catch @panic("test failure");
+ expect(s2.c == 1337.0) catch @panic("test failure");
+}
+
+export fn zig_med_struct_mixed(x: MedStructMixed) void {
+ expect(x.a == 1234) catch @panic("test failure");
+ expect(x.b == 100.0) catch @panic("test failure");
+ expect(x.c == 1337.0) catch @panic("test failure");
+}
+
const SmallStructInts = extern struct {
a: u8,
b: u8,
@@ -177,6 +206,7 @@ const SmallStructInts = extern struct {
d: u8,
};
extern fn c_small_struct_ints(SmallStructInts) void;
+extern fn c_ret_small_struct_ints() SmallStructInts;
test "C ABI small struct of ints" {
var s = SmallStructInts{
@@ -186,6 +216,11 @@ test "C ABI small struct of ints" {
.d = 4,
};
c_small_struct_ints(s);
+ var s2 = c_ret_small_struct_ints();
+ expect(s2.a == 1) catch @panic("test failure");
+ expect(s2.b == 2) catch @panic("test failure");
+ expect(s2.c == 3) catch @panic("test failure");
+ expect(s2.d == 4) catch @panic("test failure");
}
export fn zig_small_struct_ints(x: SmallStructInts) void {
@@ -217,6 +252,33 @@ export fn zig_split_struct_ints(x: SplitStructInt) void {
expect(x.c == 1337) catch @panic("test failure");
}
+const SplitStructMixed = extern struct {
+ a: u64,
+ b: u8,
+ c: f32,
+};
+extern fn c_split_struct_mixed(SplitStructMixed) void;
+extern fn c_ret_split_struct_mixed() SplitStructMixed;
+
+test "C ABI split struct of ints and floats" {
+ var s = SplitStructMixed{
+ .a = 1234,
+ .b = 100,
+ .c = 1337.0,
+ };
+ c_split_struct_mixed(s);
+ var s2 = c_ret_split_struct_mixed();
+ expect(s2.a == 1234) catch @panic("test failure");
+ expect(s2.b == 100) catch @panic("test failure");
+ expect(s2.c == 1337.0) catch @panic("test failure");
+}
+
+export fn zig_split_struct_mixed(x: SplitStructMixed) void {
+ expect(x.a == 1234) catch @panic("test failure");
+ expect(x.b == 100) catch @panic("test failure");
+ expect(x.c == 1337.0) catch @panic("test failure");
+}
+
extern fn c_big_struct_both(BigStruct) BigStruct;
test "C ABI sret and byval together" {
@@ -315,6 +377,31 @@ export fn zig_ret_i64() i64 {
return -1;
}
+export fn zig_ret_small_struct_ints() SmallStructInts {
+ return .{
+ .a = 1,
+ .b = 2,
+ .c = 3,
+ .d = 4,
+ };
+}
+
+export fn zig_ret_med_struct_mixed() MedStructMixed {
+ return .{
+ .a = 1234,
+ .b = 100.0,
+ .c = 1337.0,
+ };
+}
+
+export fn zig_ret_split_struct_mixed() SplitStructMixed {
+ return .{
+ .a = 1234,
+ .b = 100,
+ .c = 1337.0,
+ };
+}
+
extern fn c_ret_bool() bool;
extern fn c_ret_u8() u8;
extern fn c_ret_u16() u16;
From 15bec20b0013d8afb90a0a2a08c25ce9fb1f2693 Mon Sep 17 00:00:00 2001
From: Mahdi Khanalizadeh
Date: Tue, 13 Jul 2021 15:35:23 +0200
Subject: [PATCH 23/96] linux: add mknod and mknodat syscalls
---
lib/std/os/linux.zig | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index ef7c0ff077..ca8f0907e1 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -253,6 +253,18 @@ pub fn mkdirat(dirfd: i32, path: [*:0]const u8, mode: u32) usize {
return syscall3(.mkdirat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), mode);
}
+pub fn mknod(path: [*:0]const u8, mode: u32, dev: u32) usize {
+ if (@hasField(SYS, "mknod")) {
+ return syscall3(.mknod, @ptrToInt(path), mode, dev);
+ } else {
+ return mknodat(AT_FDCWD, path, mode, dev);
+ }
+}
+
+pub fn mknodat(dirfd: i32, path: [*:0]const u8, mode: u32, dev: u32) usize {
+ return syscall4(.mknodat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), mode, dev);
+}
+
pub fn mount(special: [*:0]const u8, dir: [*:0]const u8, fstype: [*:0]const u8, flags: u32, data: usize) usize {
return syscall5(.mount, @ptrToInt(special), @ptrToInt(dir), @ptrToInt(fstype), flags, data);
}
From ed174b7386cb5a6f2008cb6a25c3ff684645d847 Mon Sep 17 00:00:00 2001
From: Michael Dusan
Date: Mon, 19 Jul 2021 02:35:17 -0400
Subject: [PATCH 24/96] stage1: fix anon struct naming in certain cases
- generic "struct:L:C" naming if rloc is NodeTypeStructValueField
- generic "struct:L:C" naming if rloc is NodeTypeFnCallExpr
- move some tests from test/behavior/misc to test/behavior/typename
closes #4330
closes #9339
---
src/stage1/astgen.cpp | 93 ++++++++++++++++++++-----------
src/stage1/astgen.hpp | 2 +-
src/stage1/ir.cpp | 17 +++---
test/behavior/misc.zig | 24 --------
test/behavior/typename.zig | 111 ++++++++++++++++++++++++++++++++++++-
5 files changed, 181 insertions(+), 66 deletions(-)
diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp
index a5afe32d8b..44dc1080c2 100644
--- a/src/stage1/astgen.cpp
+++ b/src/stage1/astgen.cpp
@@ -3454,7 +3454,7 @@ static Stage1ZirInst *astgen_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstN
// TODO only pass type_name when the || operator is the top level AST node in the var decl expr
Buf bare_name = BUF_INIT;
- Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", scope, node, &bare_name);
+ Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", scope, node, &bare_name, nullptr);
return ir_build_merge_err_sets(ag, scope, node, op1, op2, type_name);
}
@@ -7588,42 +7588,73 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
}
Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name,
- Scope *scope, AstNode *source_node, Buf *out_bare_name)
+ Scope *scope, AstNode *source_node, Buf *out_bare_name, ResultLoc *result_loc)
{
- if (exec != nullptr && exec->name) {
- ZigType *import = get_scope_import(scope);
- Buf *namespace_name = buf_alloc();
- append_namespace_qualification(codegen, namespace_name, import);
- buf_append_buf(namespace_name, exec->name);
- buf_init_from_buf(out_bare_name, exec->name);
- return namespace_name;
- } else if (exec != nullptr && exec->name_fn != nullptr) {
- Buf *name = buf_alloc();
- buf_append_buf(name, &exec->name_fn->symbol_name);
- buf_appendf(name, "(");
- render_instance_name_recursive(codegen, name, &exec->name_fn->fndef_scope->base, exec->begin_scope);
- buf_appendf(name, ")");
- buf_init_from_buf(out_bare_name, name);
- return name;
- } else {
- ZigType *import = get_scope_import(scope);
- Buf *namespace_name = buf_alloc();
- append_namespace_qualification(codegen, namespace_name, import);
- RootStruct *root_struct = source_node->owner->data.structure.root_struct;
- TokenLoc tok_loc = root_struct->token_locs[source_node->main_token];
- buf_appendf(namespace_name, "%s:%u:%u", kind_name,
- tok_loc.line + 1, tok_loc.column + 1);
- buf_init_from_buf(out_bare_name, namespace_name);
- return namespace_name;
+ // See https://ziglang.org/documentation/master/#Struct-Naming .
+ bool force_generic = false;
+ if (result_loc != nullptr
+ && result_loc->source_instruction != nullptr
+ && result_loc->source_instruction->source_node != nullptr
+ ) {
+ switch (result_loc->source_instruction->source_node->type) {
+ case NodeTypeVariableDeclaration: {
+ ZigType *import = get_scope_import(scope);
+ Buf *name = buf_alloc();
+ append_namespace_qualification(codegen, name, import);
+ const auto &basename = result_loc->source_instruction->source_node->data.variable_declaration.symbol;
+ buf_append_buf(name, basename);
+ buf_init_from_buf(out_bare_name, basename);
+ return name;
+ }
+ case NodeTypeFnCallExpr:
+ case NodeTypeStructValueField:
+ force_generic = true;
+ break;
+ default:
+ break;
+ }
}
+
+ if (!force_generic) {
+ if (exec != nullptr && exec->name != nullptr) {
+ ZigType *import = get_scope_import(scope);
+ Buf *namespace_name = buf_alloc();
+ append_namespace_qualification(codegen, namespace_name, import);
+ buf_append_buf(namespace_name, exec->name);
+ buf_init_from_buf(out_bare_name, exec->name);
+ return namespace_name;
+ }
+ if (exec != nullptr && exec->name_fn != nullptr) {
+ Buf *name = buf_alloc();
+ buf_append_buf(name, &exec->name_fn->symbol_name);
+ buf_appendf(name, "(");
+ render_instance_name_recursive(codegen, name, &exec->name_fn->fndef_scope->base, exec->begin_scope);
+ buf_appendf(name, ")");
+ buf_init_from_buf(out_bare_name, name);
+ return name;
+ }
+ }
+
+ ZigType *import = get_scope_import(scope);
+ Buf *namespace_name = buf_alloc();
+ append_namespace_qualification(codegen, namespace_name, import);
+ RootStruct *root_struct = source_node->owner->data.structure.root_struct;
+ TokenLoc tok_loc = root_struct->token_locs[source_node->main_token];
+ buf_appendf(namespace_name, "%s:%u:%u", kind_name,
+ tok_loc.line + 1, tok_loc.column + 1);
+ buf_init_from_buf(out_bare_name, namespace_name);
+ return namespace_name;
}
-static Stage1ZirInst *astgen_container_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) {
+static Stage1ZirInst *astgen_container_decl(Stage1AstGen *ag, Scope *parent_scope,
+ AstNode *node, ResultLoc *result_loc)
+{
assert(node->type == NodeTypeContainerDecl);
ContainerKind kind = node->data.container_decl.kind;
Buf *bare_name = buf_alloc();
- Buf *name = get_anon_type_name(ag->codegen, ag->exec, container_string(kind), parent_scope, node, bare_name);
+ Buf *name = get_anon_type_name(ag->codegen,
+ ag->exec, container_string(kind), parent_scope, node, bare_name, result_loc);
ContainerLayout layout = node->data.container_decl.layout;
ZigType *container_type = get_partial_container_type(ag->codegen, parent_scope,
@@ -7653,7 +7684,7 @@ static Stage1ZirInst *astgen_err_set_decl(Stage1AstGen *ag, Scope *parent_scope,
uint32_t err_count = node->data.err_set_decl.decls.length;
Buf bare_name = BUF_INIT;
- Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", parent_scope, node, &bare_name);
+ Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", parent_scope, node, &bare_name, nullptr);
ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
buf_init_from_buf(&err_set_type->name, type_name);
err_set_type->data.error_set.err_count = err_count;
@@ -7963,7 +7994,7 @@ static Stage1ZirInst *astgen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *sc
case NodeTypeCatchExpr:
return astgen_catch(ag, scope, node, lval, result_loc);
case NodeTypeContainerDecl:
- return ir_lval_wrap(ag, scope, astgen_container_decl(ag, scope, node), lval, result_loc);
+ return ir_lval_wrap(ag, scope, astgen_container_decl(ag, scope, node, result_loc), lval, result_loc);
case NodeTypeFnProto:
return ir_lval_wrap(ag, scope, astgen_fn_proto(ag, scope, node), lval, result_loc);
case NodeTypeErrorSetDecl:
diff --git a/src/stage1/astgen.hpp b/src/stage1/astgen.hpp
index d4bb6923a1..c0ca583f56 100644
--- a/src/stage1/astgen.hpp
+++ b/src/stage1/astgen.hpp
@@ -32,6 +32,6 @@ void destroy_instruction_src(Stage1ZirInst *inst);
bool ir_should_inline(Stage1Zir *exec, Scope *scope);
Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name,
- Scope *scope, AstNode *source_node, Buf *out_bare_name);
+ Scope *scope, AstNode *source_node, Buf *out_bare_name, ResultLoc *result_loc);
#endif
diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp
index e9bb7b1d15..b1583cc6b4 100644
--- a/src/stage1/ir.cpp
+++ b/src/stage1/ir.cpp
@@ -10423,7 +10423,7 @@ static Stage1AirInst *ir_analyze_tuple_cat(IrAnalyze *ira, Scope *scope, AstNode
Buf *bare_name = buf_alloc();
Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
- scope, source_node, bare_name);
+ scope, source_node, bare_name, nullptr);
ZigType *new_type = get_partial_container_type(ira->codegen, scope,
ContainerKindStruct, source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);
new_type->data.structure.special = StructSpecialInferredTuple;
@@ -10755,7 +10755,7 @@ static Stage1AirInst *ir_analyze_tuple_mult(IrAnalyze *ira, Scope *scope, AstNod
Buf *bare_name = buf_alloc();
Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
- scope, source_node, bare_name);
+ scope, source_node, bare_name, nullptr);
ZigType *new_type = get_partial_container_type(ira->codegen, scope,
ContainerKindStruct, source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);
new_type->data.structure.special = StructSpecialInferredTuple;
@@ -12277,7 +12277,7 @@ static Stage1AirInst *ir_analyze_instruction_resolve_result(IrAnalyze *ira, Stag
if (implicit_elem_type == ira->codegen->builtin_types.entry_anytype) {
Buf *bare_name = buf_alloc();
Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
- instruction->base.scope, instruction->base.source_node, bare_name);
+ instruction->base.scope, instruction->base.source_node, bare_name, nullptr);
StructSpecial struct_special = StructSpecialInferredStruct;
if (instruction->base.source_node->type == NodeTypeContainerInitExpr &&
@@ -18898,7 +18898,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
Buf *bare_name = buf_alloc();
Buf *full_name = get_anon_type_name(ira->codegen,
- ira->zir, "opaque", scope, source_node, bare_name);
+ ira->zir, "opaque", scope, source_node, bare_name, nullptr);
return get_opaque_type(ira->codegen,
scope, source_node, buf_ptr(full_name), bare_name);
}
@@ -18945,7 +18945,8 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
assert(is_slice(slice->type));
ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
Buf bare_name = BUF_INIT;
- buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->zir, "error", scope, source_node, &bare_name));
+ buf_init_from_buf(&err_set_type->name,
+ get_anon_type_name(ira->codegen, ira->zir, "error", scope, source_node, &bare_name, nullptr));
err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
@@ -19024,7 +19025,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
buf_init_from_buf(&entry->name,
- get_anon_type_name(ira->codegen, ira->zir, "struct", scope, source_node, &entry->name));
+ get_anon_type_name(ira->codegen, ira->zir, "struct", scope, source_node, &entry->name, nullptr));
entry->data.structure.decl_node = source_node;
entry->data.structure.fields = alloc_type_struct_fields(fields_len);
entry->data.structure.fields_by_name.init(fields_len);
@@ -19134,7 +19135,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
ZigType *entry = new_type_table_entry(ZigTypeIdEnum);
buf_init_from_buf(&entry->name,
- get_anon_type_name(ira->codegen, ira->zir, "enum", scope, source_node, &entry->name));
+ get_anon_type_name(ira->codegen, ira->zir, "enum", scope, source_node, &entry->name, nullptr));
entry->data.enumeration.decl_node = source_node;
entry->data.enumeration.tag_int_type = tag_type;
entry->data.enumeration.decls_scope = create_decls_scope(
@@ -19216,7 +19217,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
ZigType *entry = new_type_table_entry(ZigTypeIdUnion);
buf_init_from_buf(&entry->name,
- get_anon_type_name(ira->codegen, ira->zir, "union", scope, source_node, &entry->name));
+ get_anon_type_name(ira->codegen, ira->zir, "union", scope, source_node, &entry->name, nullptr));
entry->data.unionation.decl_node = source_node;
entry->data.unionation.fields = heap::c_allocator.allocate(fields_len);
entry->data.unionation.fields_by_name.init(fields_len);
diff --git a/test/behavior/misc.zig b/test/behavior/misc.zig
index 6fabbf487b..fdd3f3477b 100644
--- a/test/behavior/misc.zig
+++ b/test/behavior/misc.zig
@@ -436,30 +436,6 @@ const AUnion = union {
Two: void,
};
-test "@typeName" {
- const Struct = struct {};
- const Union = union {
- unused: u8,
- };
- const Enum = enum {
- Unused,
- };
- comptime {
- try expect(mem.eql(u8, @typeName(i64), "i64"));
- try expect(mem.eql(u8, @typeName(*usize), "*usize"));
- // https://github.com/ziglang/zig/issues/675
- try expect(mem.eql(u8, "behavior.misc.TypeFromFn(u8)", @typeName(TypeFromFn(u8))));
- try expect(mem.eql(u8, @typeName(Struct), "Struct"));
- try expect(mem.eql(u8, @typeName(Union), "Union"));
- try expect(mem.eql(u8, @typeName(Enum), "Enum"));
- }
-}
-
-fn TypeFromFn(comptime T: type) type {
- _ = T;
- return struct {};
-}
-
test "double implicit cast in same expression" {
var x = @as(i32, @as(u16, nine()));
try expect(x == 9);
diff --git a/test/behavior/typename.zig b/test/behavior/typename.zig
index bf8464244b..4d87e0030c 100644
--- a/test/behavior/typename.zig
+++ b/test/behavior/typename.zig
@@ -2,6 +2,113 @@ const std = @import("std");
const expect = std.testing.expect;
const expectEqualSlices = std.testing.expectEqualSlices;
-test "slice" {
- try expectEqualSlices(u8, "[]u8", @typeName([]u8));
+// Most tests here can be comptime but use runtime so that a stacktrace
+// can show failure location.
+//
+// Note certain results of `@typeName()` expect `behavior.zig` to be the
+// root file. Running a test against this file as root will result in
+// failures.
+
+// CAUTION: this test is source-location sensitive.
+test "anon fn param - source-location sensitive" {
+ // https://github.com/ziglang/zig/issues/9339
+ try expectEqualSlices(u8, @typeName(TypeFromFn(struct {})), "behavior.typename.TypeFromFn(behavior.typename.struct:15:52)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(union { unused: u8 })), "behavior.typename.TypeFromFn(behavior.typename.union:16:52)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(enum { unused })), "behavior.typename.TypeFromFn(behavior.typename.enum:17:52)");
+
+ try expectEqualSlices(
+ u8,
+ @typeName(TypeFromFn3(struct {}, union { unused: u8 }, enum { unused })),
+ "behavior.typename.TypeFromFn3(behavior.typename.struct:21:31,behavior.typename.union:21:42,behavior.typename.enum:21:64)",
+ );
+}
+
+// CAUTION: this test is source-location sensitive.
+test "anon field init" {
+ const Foo = .{
+ .T1 = struct {},
+ .T2 = union { unused: u8 },
+ .T3 = enum { unused },
+ };
+
+ try expectEqualSlices(u8, @typeName(Foo.T1), "behavior.typename.struct:29:15");
+ try expectEqualSlices(u8, @typeName(Foo.T2), "behavior.typename.union:30:15");
+ try expectEqualSlices(u8, @typeName(Foo.T3), "behavior.typename.enum:31:15");
+}
+
+test "basic" {
+ try expectEqualSlices(u8, @typeName(i64), "i64");
+ try expectEqualSlices(u8, @typeName(*usize), "*usize");
+ try expectEqualSlices(u8, @typeName([]u8), "[]u8");
+}
+
+test "top level decl" {
+ try expectEqualSlices(u8, @typeName(A_Struct), "A_Struct");
+ try expectEqualSlices(u8, @typeName(A_Union), "A_Union");
+ try expectEqualSlices(u8, @typeName(A_Enum), "A_Enum");
+
+ // regular fn, without error
+ try expectEqualSlices(u8, @typeName(@TypeOf(regular)), "fn() void");
+ // regular fn inside struct, with error
+ try expectEqualSlices(u8, @typeName(@TypeOf(B.doTest)), "fn() @typeInfo(@typeInfo(@TypeOf(behavior.typename.B.doTest)).Fn.return_type.?).ErrorUnion.error_set!void");
+ // generic fn
+ try expectEqualSlices(u8, @typeName(@TypeOf(TypeFromFn)), "fn(type) anytype");
+}
+
+const A_Struct = struct {};
+const A_Union = union {
+ unused: u8,
+};
+const A_Enum = enum {
+ unused,
+};
+
+fn regular() void {}
+
+test "fn body decl" {
+ try B.doTest();
+}
+
+const B = struct {
+ fn doTest() !void {
+ const B_Struct = struct {};
+ const B_Union = union {
+ unused: u8,
+ };
+ const B_Enum = enum {
+ unused,
+ };
+
+ try expectEqualSlices(u8, @typeName(B_Struct), "B_Struct");
+ try expectEqualSlices(u8, @typeName(B_Union), "B_Union");
+ try expectEqualSlices(u8, @typeName(B_Enum), "B_Enum");
+ }
+};
+
+test "fn param" {
+ // https://github.com/ziglang/zig/issues/675
+ try expectEqualSlices(u8, @typeName(TypeFromFn(u8)), "behavior.typename.TypeFromFn(u8)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(A_Struct)), "behavior.typename.TypeFromFn(behavior.typename.A_Struct)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(A_Union)), "behavior.typename.TypeFromFn(behavior.typename.A_Union)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(A_Enum)), "behavior.typename.TypeFromFn(behavior.typename.A_Enum)");
+
+ try expectEqualSlices(u8, @typeName(TypeFromFn2(u8, bool)), "behavior.typename.TypeFromFn2(u8,bool)");
+}
+
+fn TypeFromFn(comptime T: type) type {
+ _ = T;
+ return struct {};
+}
+
+fn TypeFromFn2(comptime T1: type, comptime T2: type) type {
+ _ = T1;
+ _ = T2;
+ return struct {};
+}
+
+fn TypeFromFn3(comptime T1: type, comptime T2: type, comptime T3: type) type {
+ _ = T1;
+ _ = T2;
+ _ = T3;
+ return struct {};
}
From c0f40a5fe62bbd8e5e0ad5d127dbd4411c1e36f1 Mon Sep 17 00:00:00 2001
From: Vincent Rischmann
Date: Sun, 18 Apr 2021 19:24:01 +0200
Subject: [PATCH 25/96] std/c: add pthread_setname_np and pthread_getname_np
---
lib/std/c/darwin.zig | 2 ++
lib/std/c/freebsd.zig | 2 ++
lib/std/c/linux.zig | 3 +++
lib/std/c/netbsd.zig | 3 +++
lib/std/c/openbsd.zig | 3 +++
5 files changed, 13 insertions(+)
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig
index ca18b5130a..e216afd643 100644
--- a/lib/std/c/darwin.zig
+++ b/lib/std/c/darwin.zig
@@ -193,6 +193,8 @@ pub const pthread_attr_t = extern struct {
const pthread_t = std.c.pthread_t;
pub extern "c" fn pthread_threadid_np(thread: ?pthread_t, thread_id: *u64) c_int;
+pub extern "c" fn pthread_setname_np(name: [*:0]const u8) c_int;
+pub extern "c" fn pthread_getname_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) c_int;
pub extern "c" fn arc4random_buf(buf: [*]u8, len: usize) void;
diff --git a/lib/std/c/freebsd.zig b/lib/std/c/freebsd.zig
index 3e4b522685..eb449165d3 100644
--- a/lib/std/c/freebsd.zig
+++ b/lib/std/c/freebsd.zig
@@ -14,6 +14,8 @@ pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize;
pub extern "c" fn pthread_getthreadid_np() c_int;
+pub extern "c" fn pthread_set_name_np(thread: std.c.pthread_t, name: [*:0]const u8) void;
+pub extern "c" fn pthread_get_name_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) void;
pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int;
pub extern "c" fn posix_memalign(memptr: *?*c_void, alignment: usize, size: usize) c_int;
diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig
index 6e897c3098..694af28904 100644
--- a/lib/std/c/linux.zig
+++ b/lib/std/c/linux.zig
@@ -186,6 +186,9 @@ const __SIZEOF_PTHREAD_MUTEX_T = if (os_tag == .fuchsia) 40 else switch (abi) {
};
const __SIZEOF_SEM_T = 4 * @sizeOf(usize);
+pub extern "c" fn pthread_setname_np(thread: std.c.pthread_t, name: [*:0]const u8) c_int;
+pub extern "c" fn pthread_getname_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) c_int;
+
pub const RTLD_LAZY = 1;
pub const RTLD_NOW = 2;
pub const RTLD_NOLOAD = 4;
diff --git a/lib/std/c/netbsd.zig b/lib/std/c/netbsd.zig
index 8e6d556fbc..32b7cc69e3 100644
--- a/lib/std/c/netbsd.zig
+++ b/lib/std/c/netbsd.zig
@@ -94,3 +94,6 @@ pub const pthread_attr_t = extern struct {
};
pub const sem_t = ?*opaque {};
+
+pub extern "c" fn pthread_setname_np(thread: std.c.pthread_t, name: [*:0]const u8, arg: ?*c_void) c_int;
+pub extern "c" fn pthread_getname_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) c_int;
diff --git a/lib/std/c/openbsd.zig b/lib/std/c/openbsd.zig
index cac3df867d..15820fb0a9 100644
--- a/lib/std/c/openbsd.zig
+++ b/lib/std/c/openbsd.zig
@@ -45,3 +45,6 @@ pub extern "c" fn posix_memalign(memptr: *?*c_void, alignment: usize, size: usiz
pub extern "c" fn pledge(promises: ?[*:0]const u8, execpromises: ?[*:0]const u8) c_int;
pub extern "c" fn unveil(path: ?[*:0]const u8, permissions: ?[*:0]const u8) c_int;
+
+pub extern "c" fn pthread_set_name_np(thread: std.c.pthread_t, name: [*:0]const u8) void;
+pub extern "c" fn pthread_get_name_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) void;
From 0be1e74902e9bfb7dd35d2a3ba927db76f6d67c7 Mon Sep 17 00:00:00 2001
From: Vincent Rischmann
Date: Mon, 19 Apr 2021 23:14:33 +0200
Subject: [PATCH 26/96] windows/kernel32: add LocalFree, SetThreadDescription
and GetThreadDescription
---
lib/std/os/windows/kernel32.zig | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig
index 971273ef3a..a04314324d 100644
--- a/lib/std/os/windows/kernel32.zig
+++ b/lib/std/os/windows/kernel32.zig
@@ -192,6 +192,8 @@ pub extern "kernel32" fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*co
pub extern "kernel32" fn VirtualAlloc(lpAddress: ?LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD) callconv(WINAPI) ?LPVOID;
pub extern "kernel32" fn VirtualFree(lpAddress: ?LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) callconv(WINAPI) BOOL;
+pub extern "kernel32" fn LocalFree(hMem: HLOCAL) callconv(WINAPI) ?HLOCAL;
+
pub extern "kernel32" fn MoveFileExW(
lpExistingFileName: [*:0]const u16,
lpNewFileName: [*:0]const u16,
@@ -342,3 +344,6 @@ pub extern "kernel32" fn SleepConditionVariableSRW(
pub extern "kernel32" fn TryAcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) BOOLEAN;
pub extern "kernel32" fn AcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;
pub extern "kernel32" fn ReleaseSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;
+
+pub extern "kernel32" fn SetThreadDescription(hThread: HANDLE, lpThreadDescription: LPCWSTR) callconv(WINAPI) HRESULT;
+pub extern "kernel32" fn GetThreadDescription(hThread: HANDLE, ppszThreadDescription: *LPWSTR) callconv(WINAPI) HRESULT;
From accde7fe2d8966ed181af4e819dc73e4d11caef9 Mon Sep 17 00:00:00 2001
From: Vincent Rischmann
Date: Mon, 19 Apr 2021 23:14:55 +0200
Subject: [PATCH 27/96] windows: add wrappers for LocalFree,
SetThreadDescription and GetThreadDescription
---
lib/std/os/windows.zig | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index cbd4ce065b..04ce433758 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -1631,6 +1631,10 @@ pub fn HeapDestroy(hHeap: HANDLE) void {
assert(kernel32.HeapDestroy(hHeap) != 0);
}
+pub fn LocalFree(hMem: HLOCAL) void {
+ assert(kernel32.LocalFree(hMem) == null);
+}
+
pub const GetFileInformationByHandleError = error{Unexpected};
pub fn GetFileInformationByHandle(
@@ -2011,6 +2015,21 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
return error.Unexpected;
}
+pub fn SetThreadDescription(hThread: HANDLE, lpThreadDescription: LPCWSTR) !void {
+ if (kernel32.SetThreadDescription(hThread, lpThreadDescription) == 0) {
+ switch (kernel32.GetLastError()) {
+ else => |err| return unexpectedError(err),
+ }
+ }
+}
+pub fn GetThreadDescription(hThread: HANDLE, ppszThreadDescription: *LPWSTR) !void {
+ if (kernel32.GetThreadDescription(hThread, ppszThreadDescription) == 0) {
+ switch (kernel32.GetLastError()) {
+ else => |err| return unexpectedError(err),
+ }
+ }
+}
+
test "" {
if (builtin.os.tag == .windows) {
_ = @import("windows/test.zig");
From df4fe8716374e4cfdf1dee2bbcda7969eb6d057a Mon Sep 17 00:00:00 2001
From: Vincent Rischmann
Date: Wed, 21 Apr 2021 10:59:36 +0200
Subject: [PATCH 28/96] thread: implement setName/getName
---
lib/std/Thread.zig | 274 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 274 insertions(+)
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index 58a409c64e..2584b38072 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -38,6 +38,192 @@ else
impl: Impl,
+pub const max_name_len = switch (std.Target.current.os.tag) {
+ .linux => 15,
+ .windows => 31,
+ .macos, .ios, .watchos, .tvos => 63,
+ .netbsd => 31,
+ .freebsd => 15,
+ .openbsd => 31,
+ else => 0,
+};
+
+pub const SetNameError = error{
+ NameTooLong,
+ Unsupported,
+ Unexpected,
+} || os.PrctlError || os.WriteError || std.fs.File.OpenError || std.fmt.BufPrintError;
+
+pub fn setName(self: Thread, name: []const u8) SetNameError!void {
+ if (name.len > max_name_len) return error.NameTooLong;
+
+ const name_with_terminator = blk: {
+ var name_buf: [max_name_len:0]u8 = undefined;
+ std.mem.copy(u8, &name_buf, name);
+ name_buf[name.len] = 0;
+ break :blk name_buf[0..name.len :0];
+ };
+
+ switch (std.Target.current.os.tag) {
+ .linux => if (use_pthreads) {
+ const err = std.c.pthread_setname_np(self.getHandle(), name_with_terminator.ptr);
+ return switch (err) {
+ 0 => {},
+ os.ERANGE => unreachable,
+ else => return os.unexpectedErrno(err),
+ };
+ } else if (use_pthreads and self.getHandle() == std.c.pthread_self()) {
+ const err = try os.prctl(.SET_NAME, .{@ptrToInt(name_with_terminator.ptr)});
+ return switch (err) {
+ 0 => {},
+ else => return os.unexpectedErrno(err),
+ };
+ } else {
+ var buf: [32]u8 = undefined;
+ const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()});
+
+ const file = try std.fs.cwd().openFile(path, .{ .write = true });
+ defer file.close();
+
+ try file.writer().writeAll(name);
+ },
+ .windows => if (std.Target.current.os.isAtLeast(.windows, .win10_rs1)) |res| {
+ // SetThreadDescription is only available since version 1607, which is 10.0.14393.795
+ // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK
+ if (!res) {
+ return error.Unsupported;
+ }
+
+ var name_buf_w: [max_name_len:0]u16 = undefined;
+ const length = try std.unicode.utf8ToUtf16Le(&name_buf_w, name);
+ name_buf_w[length] = 0;
+
+ try os.windows.SetThreadDescription(
+ self.getHandle(),
+ @ptrCast(os.windows.LPWSTR, &name_buf_w),
+ );
+ } else {
+ return error.Unsupported;
+ },
+ .macos, .ios, .watchos, .tvos => if (use_pthreads) {
+ // There doesn't seem to be a way to set the name for an arbitrary thread, only the current one.
+ if (self.getHandle() != std.c.pthread_self()) return error.Unsupported;
+
+ const err = std.c.pthread_setname_np(name_with_terminator.ptr);
+ return switch (err) {
+ 0 => {},
+ else => return os.unexpectedErrno(err),
+ };
+ },
+ .netbsd => if (use_pthreads) {
+ const err = std.c.pthread_setname_np(self.getHandle(), name_with_terminator.ptr, null);
+ return switch (err) {
+ 0 => {},
+ os.EINVAL => unreachable,
+ os.ESRCH => unreachable,
+ os.ENOMEM => unreachable,
+ else => return os.unexpectedErrno(err),
+ };
+ },
+ .freebsd, .openbsd => if (use_pthreads) {
+ // Use pthread_set_name_np for FreeBSD because pthread_setname_np is FreeBSD 12.2+ only.
+ // TODO maybe revisit this if depending on FreeBSD 12.2+ is acceptable because pthread_setname_np can return an error.
+
+ std.c.pthread_set_name_np(self.getHandle(), name_with_terminator.ptr);
+ },
+ else => return error.Unsupported,
+ }
+}
+
+pub const GetNameError = error{
+ // For Windows, the name is converted from UTF16 to UTF8
+ CodepointTooLarge,
+ Utf8CannotEncodeSurrogateHalf,
+ DanglingSurrogateHalf,
+ ExpectedSecondSurrogateHalf,
+ UnexpectedSecondSurrogateHalf,
+
+ Unsupported,
+ Unexpected,
+} || os.PrctlError || os.ReadError || std.fs.File.OpenError || std.fmt.BufPrintError;
+
+pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]const u8 {
+ buffer_ptr[max_name_len] = 0;
+ var buffer = std.mem.span(buffer_ptr);
+
+ switch (std.Target.current.os.tag) {
+ .linux => if (use_pthreads and comptime std.Target.current.abi.isGnu()) {
+ const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
+ return switch (err) {
+ 0 => std.mem.sliceTo(buffer, 0),
+ os.ERANGE => unreachable,
+ else => return os.unexpectedErrno(err),
+ };
+ } else if (use_pthreads and self.getHandle() == std.c.pthread_self()) {
+ const err = try os.prctl(.GET_NAME, .{@ptrToInt(buffer.ptr)});
+ return switch (err) {
+ 0 => std.mem.sliceTo(buffer, 0),
+ else => return os.unexpectedErrno(err),
+ };
+ } else if (!use_pthreads) {
+ var buf: [32]u8 = undefined;
+ const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()});
+
+ const file = try std.fs.cwd().openFile(path, .{});
+ defer file.close();
+
+ const data_len = try file.reader().readAll(buffer_ptr[0 .. max_name_len + 1]);
+
+ return if (data_len >= 1) buffer[0 .. data_len - 1] else null;
+ } else {
+ // musl doesn't provide pthread_getname_np and there's no way to retrieve the thread id of an arbitrary thread.
+ return error.Unsupported;
+ },
+ .windows => if (std.Target.current.os.isAtLeast(.windows, .win10_rs1)) |res| {
+ // GetThreadDescription is only available since version 1607, which is 10.0.14393.795
+ // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK
+ if (!res) {
+ return error.Unsupported;
+ }
+
+ var name_w: os.windows.LPWSTR = undefined;
+ try os.windows.GetThreadDescription(self.getHandle(), &name_w);
+ defer os.windows.LocalFree(name_w);
+
+ const data_len = try std.unicode.utf16leToUtf8(buffer, std.mem.sliceTo(name_w, 0));
+
+ return if (data_len >= 1) buffer[0..data_len] else null;
+ } else {
+ return error.Unsupported;
+ },
+ .macos, .ios, .watchos, .tvos => if (use_pthreads) {
+ const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
+ return switch (err) {
+ 0 => std.mem.sliceTo(buffer, 0),
+ os.ESRCH => unreachable,
+ else => return os.unexpectedErrno(err),
+ };
+ },
+ .netbsd => if (use_pthreads) {
+ const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
+ return switch (err) {
+ 0 => std.mem.sliceTo(buffer, 0),
+ os.EINVAL => unreachable,
+ os.ESRCH => unreachable,
+ else => return os.unexpectedErrno(err),
+ };
+ },
+ .freebsd, .openbsd => if (use_pthreads) {
+ // Use pthread_get_name_np for FreeBSD because pthread_getname_np is FreeBSD 12.2+ only.
+ // TODO maybe revisit this if depending on FreeBSD 12.2+ is acceptable because pthread_getname_np can return an error.
+
+ std.c.pthread_get_name_np(self.getHandle(), buffer.ptr, max_name_len + 1);
+ return std.mem.sliceTo(buffer, 0);
+ },
+ else => return error.Unsupported,
+ }
+}
+
/// Represents a unique ID per thread.
pub const Id = u64;
@@ -779,6 +965,94 @@ const LinuxThreadImpl = struct {
}
};
+fn testThreadName(thread: *Thread) !void {
+ const testCases = &[_][]const u8{
+ "mythread",
+ "b" ** max_name_len,
+ };
+
+ inline for (testCases) |tc| {
+ try thread.setName(tc);
+
+ var name_buffer: [max_name_len:0]u8 = undefined;
+
+ const name = try thread.getName(&name_buffer);
+ if (name) |value| {
+ try std.testing.expectEqual(tc.len, value.len);
+ try std.testing.expectEqualStrings(tc, value);
+ }
+ }
+}
+
+test "setName, getName" {
+ if (std.builtin.single_threaded) return error.SkipZigTest;
+
+ const Context = struct {
+ start_wait_event: ResetEvent = undefined,
+ test_done_event: ResetEvent = undefined,
+
+ done: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(false),
+ thread: Thread = undefined,
+
+ fn init(self: *@This()) !void {
+ try self.start_wait_event.init();
+ try self.test_done_event.init();
+ }
+
+ pub fn run(ctx: *@This()) !void {
+ // Wait for the main thread to have set the thread field in the context.
+ ctx.start_wait_event.wait();
+
+ switch (std.Target.current.os.tag) {
+ .windows => testThreadName(&ctx.thread) catch |err| switch (err) {
+ error.Unsupported => return error.SkipZigTest,
+ else => return err,
+ },
+ else => try testThreadName(&ctx.thread),
+ }
+
+ // Signal our test is done
+ ctx.test_done_event.set();
+
+ while (!ctx.done.load(.SeqCst)) {
+ std.time.sleep(5 * std.time.ns_per_ms);
+ }
+ }
+ };
+
+ var context = Context{};
+ try context.init();
+
+ var thread = try spawn(.{}, Context.run, .{&context});
+ context.thread = thread;
+ context.start_wait_event.set();
+ context.test_done_event.wait();
+
+ switch (std.Target.current.os.tag) {
+ .macos, .ios, .watchos, .tvos => {
+ const res = thread.setName("foobar");
+ try std.testing.expectError(error.Unsupported, res);
+ },
+ .windows => testThreadName(&thread) catch |err| switch (err) {
+ error.Unsupported => return error.SkipZigTest,
+ else => return err,
+ },
+ else => |tag| if (tag == .linux and use_pthreads and comptime std.Target.current.abi.isMusl()) {
+ try thread.setName("foobar");
+
+ var name_buffer: [max_name_len:0]u8 = undefined;
+ const res = thread.getName(&name_buffer);
+
+ try std.testing.expectError(error.Unsupported, res);
+ } else {
+ try testThreadName(&thread);
+ },
+ }
+
+ context.done.store(true, .SeqCst);
+ thread.join();
+}
+
test "std.Thread" {
// Doesn't use testing.refAllDecls() since that would pull in the compileError spinLoopHint.
_ = AutoResetEvent;
From a5c6e51f03ab164e64b1a1d8370071dd1e670458 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 29 Jul 2021 15:59:51 -0700
Subject: [PATCH 29/96] stage2: more principled approach to comptime references
* AIR no longer has a `variables` array. Instead of the `varptr`
instruction, Sema emits a constant with a `decl_ref`.
* AIR no longer has a `ref` instruction. There is no longer any
instruction that takes a value and returns a pointer to it. If this
is desired, Sema must either create an anynomous Decl and return a
constant `decl_ref`, or in the case of a runtime value, emit an
`alloc` instruction, `store` the value to it, and then return the
`alloc`.
* The `ref_val` Value Tag is eliminated. `decl_ref` should be used
instead. Also added is `eu_payload_ptr` which points to the payload
of an error union, given an error union pointer.
In general, Sema should avoid calling `analyzeRef` if it can be helped.
For example in the case of field_val and elem_val, there should never be
a reason to create a temporary (alloc or decl). Recent previous commits
made progress along that front.
There is a new abstraction in Sema, which looks like this:
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
// here 'anon_decl.arena()` may be used
const decl = try anon_decl.finish(ty, val);
// decl is typically now used with `decl_ref`.
This pattern is used to upgrade `ref_val` usages to `decl_ref` usages.
Additional improvements:
* Sema: fix source location resolution for calling convention
expression.
* Sema: properly report "unable to resolve comptime value" for loads of
global variables. There is now a set of functions which can be
called if the callee wants to obtain the Value even if the tag is
`variable` (indicating comptime-known address but runtime-known value).
* Sema: `coerce` resolves builtin types before checking equality.
* Sema: fix `u1_type` missing from `addType`, making this type have a
slightly more efficient representation in AIR.
* LLVM backend: fix `genTypedValue` for tags `decl_ref` and `variable`
to properly do an LLVMConstBitCast.
* Remove unused parameter from `Value.toEnum`.
After this commit, some test cases are no longer passing. This is due to
the more principled approach to comptime references causing more
anonymous decls to get sent to the linker for codegen. However, in all
these cases the decls are not actually referenced by the runtime machine
code. A future commit in this branch will implement garbage collection
of decls so that unused decls do not get sent to the linker for codegen.
This will make the tests go back to passing.
---
src/Air.zig | 14 ---
src/Liveness.zig | 2 -
src/Module.zig | 47 ++++++++-
src/Sema.zig | 191 +++++++++++++++++++++++-----------
src/codegen.zig | 41 --------
src/codegen/c.zig | 41 +-------
src/codegen/llvm.zig | 35 +------
src/codegen/llvm/bindings.zig | 3 +
src/codegen/wasm.zig | 59 ++++++-----
src/link/Wasm.zig | 2 +-
src/print_air.zig | 13 +--
src/value.zig | 71 +++++--------
test/cases.zig | 5 +-
13 files changed, 246 insertions(+), 278 deletions(-)
diff --git a/src/Air.zig b/src/Air.zig
index bd7b3af733..fb95d60d00 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -15,7 +15,6 @@ instructions: std.MultiArrayList(Inst).Slice,
/// The first few indexes are reserved. See `ExtraIndex` for the values.
extra: []const u32,
values: []const Value,
-variables: []const *Module.Var,
pub const ExtraIndex = enum(u32) {
/// Payload index of the main `Block` in the `extra` array.
@@ -193,20 +192,10 @@ pub const Inst = struct {
/// Result type is always `u1`.
/// Uses the `un_op` field.
bool_to_int,
- /// Stores a value onto the stack and returns a pointer to it.
- /// TODO audit where this AIR instruction is emitted, maybe it should instead be emitting
- /// alloca instruction and storing to the alloca.
- /// Uses the `ty_op` field.
- ref,
/// Return a value from a function.
/// Result type is always noreturn; no instructions in a block follow this one.
/// Uses the `un_op` field.
ret,
- /// Returns a pointer to a global variable.
- /// Uses the `ty_pl` field. Index is into the `variables` array.
- /// TODO this can be modeled simply as a constant with a decl ref and then
- /// the variables array can be removed from Air.
- varptr,
/// Write a value to a pointer. LHS is pointer, RHS is value.
/// Result type is always void.
/// Uses the `bin_op` field.
@@ -454,7 +443,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.assembly,
.block,
.constant,
- .varptr,
.struct_field_ptr,
.struct_field_val,
=> return air.getRefType(datas[inst].ty_pl.ty),
@@ -462,7 +450,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.not,
.bitcast,
.load,
- .ref,
.floatcast,
.intcast,
.optional_payload,
@@ -550,7 +537,6 @@ pub fn deinit(air: *Air, gpa: *std.mem.Allocator) void {
air.instructions.deinit(gpa);
gpa.free(air.extra);
gpa.free(air.values);
- gpa.free(air.variables);
air.* = undefined;
}
diff --git a/src/Liveness.zig b/src/Liveness.zig
index a44b582424..7ba062fa31 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -256,14 +256,12 @@ fn analyzeInst(
.const_ty,
.breakpoint,
.dbg_stmt,
- .varptr,
.unreach,
=> return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),
.not,
.bitcast,
.load,
- .ref,
.floatcast,
.intcast,
.optional_payload,
diff --git a/src/Module.zig b/src/Module.zig
index 48c2eb8d0d..f89f72bc65 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -1324,6 +1324,42 @@ pub const Scope = struct {
block.instructions.appendAssumeCapacity(result_index);
return result_index;
}
+
+ pub fn startAnonDecl(block: *Block) !WipAnonDecl {
+ return WipAnonDecl{
+ .block = block,
+ .new_decl_arena = std.heap.ArenaAllocator.init(block.sema.gpa),
+ .finished = false,
+ };
+ }
+
+ pub const WipAnonDecl = struct {
+ block: *Scope.Block,
+ new_decl_arena: std.heap.ArenaAllocator,
+ finished: bool,
+
+ pub fn arena(wad: *WipAnonDecl) *Allocator {
+ return &wad.new_decl_arena.allocator;
+ }
+
+ pub fn deinit(wad: *WipAnonDecl) void {
+ if (!wad.finished) {
+ wad.new_decl_arena.deinit();
+ }
+ wad.* = undefined;
+ }
+
+ pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value) !*Decl {
+ const new_decl = try wad.block.sema.mod.createAnonymousDecl(&wad.block.base, .{
+ .ty = ty,
+ .val = val,
+ });
+ errdefer wad.block.sema.mod.deleteAnonDecl(&wad.block.base, new_decl);
+ try new_decl.finalizeNewArena(&wad.new_decl_arena);
+ wad.finished = true;
+ return new_decl;
+ }
+ };
};
};
@@ -1700,6 +1736,7 @@ pub const SrcLoc = struct {
.node_offset_fn_type_cc => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
+ const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
const node = src_loc.declRelativeToNodeIndex(node_off);
var params: [1]ast.Node.Index = undefined;
@@ -1708,6 +1745,13 @@ pub const SrcLoc = struct {
.fn_proto_multi => tree.fnProtoMulti(node),
.fn_proto_one => tree.fnProtoOne(¶ms, node),
.fn_proto => tree.fnProto(node),
+ .fn_decl => switch (node_tags[node_datas[node].lhs]) {
+ .fn_proto_simple => tree.fnProtoSimple(¶ms, node_datas[node].lhs),
+ .fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
+ .fn_proto_one => tree.fnProtoOne(¶ms, node_datas[node].lhs),
+ .fn_proto => tree.fnProto(node_datas[node].lhs),
+ else => unreachable,
+ },
else => unreachable,
};
const main_tokens = tree.nodes.items(.main_token);
@@ -2935,7 +2979,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
const break_index = try sema.analyzeBody(&block_scope, body);
const result_ref = zir_datas[break_index].@"break".operand;
const src: LazySrcLoc = .{ .node_offset = 0 };
- const decl_tv = try sema.resolveInstConst(&block_scope, src, result_ref);
+ const decl_tv = try sema.resolveInstValue(&block_scope, src, result_ref);
const align_val = blk: {
const align_ref = decl.zirAlignRef();
if (align_ref == .none) break :blk Value.initTag(.null_value);
@@ -3603,7 +3647,6 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air {
.instructions = sema.air_instructions.toOwnedSlice(),
.extra = sema.air_extra.toOwnedSlice(gpa),
.values = sema.air_values.toOwnedSlice(gpa),
- .variables = sema.air_variables.toOwnedSlice(gpa),
};
}
diff --git a/src/Sema.zig b/src/Sema.zig
index 88a83fd661..95baae7e92 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -14,7 +14,6 @@ code: Zir,
air_instructions: std.MultiArrayList(Air.Inst) = .{},
air_extra: std.ArrayListUnmanaged(u32) = .{},
air_values: std.ArrayListUnmanaged(Value) = .{},
-air_variables: std.ArrayListUnmanaged(*Module.Var) = .{},
/// Maps ZIR to AIR.
inst_map: InstMap = .{},
/// When analyzing an inline function call, owner_decl is the Decl of the caller
@@ -76,7 +75,6 @@ pub fn deinit(sema: *Sema) void {
sema.air_instructions.deinit(gpa);
sema.air_extra.deinit(gpa);
sema.air_values.deinit(gpa);
- sema.air_variables.deinit(gpa);
sema.inst_map.deinit(gpa);
sema.decl_val_table.deinit(gpa);
sema.* = undefined;
@@ -639,16 +637,40 @@ fn analyzeAsType(
return val.toType(sema.arena);
}
+/// May return Value Tags: `variable`, `undef`.
+/// See `resolveConstValue` for an alternative.
+fn resolveValue(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ air_ref: Air.Inst.Ref,
+) CompileError!Value {
+ if (try sema.resolveMaybeUndefValAllowVariables(block, src, air_ref)) |val| {
+ return val;
+ }
+ return sema.failWithNeededComptime(block, src);
+}
+
+/// Will not return Value Tags: `variable`, `undef`. Instead they will emit compile errors.
+/// See `resolveValue` for an alternative.
fn resolveConstValue(
sema: *Sema,
block: *Scope.Block,
src: LazySrcLoc,
air_ref: Air.Inst.Ref,
) CompileError!Value {
- return (try sema.resolveDefinedValue(block, src, air_ref)) orelse
- return sema.failWithNeededComptime(block, src);
+ if (try sema.resolveMaybeUndefValAllowVariables(block, src, air_ref)) |val| {
+ switch (val.tag()) {
+ .undef => return sema.failWithUseOfUndef(block, src),
+ .variable => return sema.failWithNeededComptime(block, src),
+ else => return val,
+ }
+ }
+ return sema.failWithNeededComptime(block, src);
}
+/// Value Tag `variable` causes this function to return `null`.
+/// Value Tag `undef` causes this function to return a compile error.
fn resolveDefinedValue(
sema: *Sema,
block: *Scope.Block,
@@ -664,11 +686,27 @@ fn resolveDefinedValue(
return null;
}
+/// Value Tag `variable` causes this function to return `null`.
+/// Value Tag `undef` causes this function to return the Value.
fn resolveMaybeUndefVal(
sema: *Sema,
block: *Scope.Block,
src: LazySrcLoc,
inst: Air.Inst.Ref,
+) CompileError!?Value {
+ const val = (try sema.resolveMaybeUndefValAllowVariables(block, src, inst)) orelse return null;
+ if (val.tag() == .variable) {
+ return sema.failWithNeededComptime(block, src);
+ }
+ return val;
+}
+
+/// Returns all Value tags including `variable` and `undef`.
+fn resolveMaybeUndefValAllowVariables(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ inst: Air.Inst.Ref,
) CompileError!?Value {
// First section of indexes correspond to a set number of constant values.
var i: usize = @enumToInt(inst);
@@ -734,6 +772,8 @@ fn resolveInt(
return val.toUnsignedInt();
}
+// Returns a compile error if the value has tag `variable`. See `resolveInstValue` for
+// a function that does not.
pub fn resolveInstConst(
sema: *Sema,
block: *Scope.Block,
@@ -748,6 +788,22 @@ pub fn resolveInstConst(
};
}
+// Value Tag may be `undef` or `variable`.
+// See `resolveInstConst` for an alternative.
+pub fn resolveInstValue(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ zir_ref: Zir.Inst.Ref,
+) CompileError!TypedValue {
+ const air_ref = sema.resolveInst(zir_ref);
+ const val = try sema.resolveValue(block, src, air_ref);
+ return TypedValue{
+ .ty = sema.typeOf(air_ref),
+ .val = val,
+ };
+}
+
fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
@@ -1707,7 +1763,7 @@ fn zirStr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A
});
errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
try new_decl.finalizeNewArena(&new_decl_arena);
- return sema.analyzeDeclRef(block, .unneeded, new_decl);
+ return sema.analyzeDeclRef(new_decl);
}
fn zirInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -2090,10 +2146,7 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro
const linkage_index = struct_obj.fields.getIndex("linkage").?;
const section_index = struct_obj.fields.getIndex("section").?;
const export_name = try fields[name_index].toAllocatedBytes(sema.arena);
- const linkage = fields[linkage_index].toEnum(
- struct_obj.fields.values()[linkage_index].ty,
- std.builtin.GlobalLinkage,
- );
+ const linkage = fields[linkage_index].toEnum(std.builtin.GlobalLinkage);
if (linkage != .Strong) {
return sema.mod.fail(&block.base, src, "TODO: implement exporting with non-strong linkage", .{});
@@ -2194,7 +2247,7 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
const src = inst_data.src();
const decl_name = inst_data.get(sema.code);
const decl = try sema.lookupIdentifier(block, src, decl_name);
- return sema.analyzeDeclRef(block, src, decl);
+ return sema.analyzeDeclRef(decl);
}
fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -2978,14 +3031,9 @@ fn zirErrUnionPayloadPtr(
if (val.getError()) |name| {
return sema.mod.fail(&block.base, src, "caught unexpected error '{s}'", .{name});
}
- const data = val.castTag(.error_union).?.data;
- // The same Value represents the pointer to the error union and the payload.
return sema.addConstant(
operand_pointer_ty,
- try Value.Tag.ref_val.create(
- sema.arena,
- data,
- ),
+ try Value.Tag.eu_payload_ptr.create(sema.arena, pointer_val),
);
}
@@ -6296,7 +6344,7 @@ fn zirFuncExtended(
const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);
- break :blk cc_tv.val.toEnum(cc_tv.ty, std.builtin.CallingConvention);
+ break :blk cc_tv.val.toEnum(std.builtin.CallingConvention);
} else .Unspecified;
const align_val: Value = if (small.has_align) blk: {
@@ -6554,7 +6602,7 @@ fn safetyPanic(
});
errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
try new_decl.finalizeNewArena(&new_decl_arena);
- break :msg_inst try sema.analyzeDeclRef(block, .unneeded, new_decl);
+ break :msg_inst try sema.analyzeDeclRef(new_decl);
};
const casted_msg_inst = try sema.coerce(block, Type.initTag(.const_slice_u8), msg_inst, src);
@@ -6761,11 +6809,16 @@ fn fieldPtr(
switch (object_ty.zigTypeTag()) {
.Array => {
if (mem.eql(u8, field_name, "len")) {
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
return sema.addConstant(
Type.initTag(.single_const_pointer_to_comptime_int),
- try Value.Tag.ref_val.create(
+ try Value.Tag.decl_ref.create(
arena,
- try Value.Tag.int_u64.create(arena, object_ty.arrayLen()),
+ try anon_decl.finish(
+ Type.initTag(.comptime_int),
+ try Value.Tag.int_u64.create(anon_decl.arena(), object_ty.arrayLen()),
+ ),
),
);
} else {
@@ -6780,18 +6833,25 @@ fn fieldPtr(
.Pointer => {
const ptr_child = object_ty.elemType();
if (ptr_child.isSlice()) {
+ // Here for the ptr and len fields what we need to do is the situation
+ // when a temporary has its address taken, e.g. `&a[c..d].len`.
+ // This value may be known at compile-time or runtime. In the former
+ // case, it should create an anonymous Decl and return a decl_ref to it.
+ // In the latter case, it should add an `alloc` instruction, store
+ // the runtime value to it, and then return the `alloc`.
+ // In both cases the pointer should be const.
if (mem.eql(u8, field_name, "ptr")) {
return mod.fail(
&block.base,
field_name_src,
- "cannot obtain reference to pointer field of slice '{}'",
+ "TODO: implement reference to 'ptr' field of slice '{}'",
.{object_ty},
);
} else if (mem.eql(u8, field_name, "len")) {
return mod.fail(
&block.base,
field_name_src,
- "cannot obtain reference to length field of slice '{}'",
+ "TODO: implement reference to 'len' field of slice '{}'",
.{object_ty},
);
} else {
@@ -6805,11 +6865,16 @@ fn fieldPtr(
} else switch (ptr_child.zigTypeTag()) {
.Array => {
if (mem.eql(u8, field_name, "len")) {
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
return sema.addConstant(
Type.initTag(.single_const_pointer_to_comptime_int),
- try Value.Tag.ref_val.create(
+ try Value.Tag.decl_ref.create(
arena,
- try Value.Tag.int_u64.create(arena, ptr_child.arrayLen()),
+ try anon_decl.finish(
+ Type.initTag(.comptime_int),
+ try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()),
+ ),
),
);
} else {
@@ -6848,13 +6913,16 @@ fn fieldPtr(
});
} else (try mod.getErrorValue(field_name)).key;
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
return sema.addConstant(
try Module.simplePtrType(arena, child_type, false, .One),
- try Value.Tag.ref_val.create(
+ try Value.Tag.decl_ref.create(
arena,
- try Value.Tag.@"error".create(arena, .{
- .name = name,
- }),
+ try anon_decl.finish(
+ child_type,
+ try Value.Tag.@"error".create(anon_decl.arena(), .{ .name = name }),
+ ),
),
);
},
@@ -6901,10 +6969,17 @@ fn fieldPtr(
return mod.failWithOwnedErrorMsg(&block.base, msg);
};
const field_index_u32 = @intCast(u32, field_index);
- const enum_val = try Value.Tag.enum_field_index.create(arena, field_index_u32);
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
return sema.addConstant(
try Module.simplePtrType(arena, child_type, false, .One),
- try Value.Tag.ref_val.create(arena, enum_val),
+ try Value.Tag.decl_ref.create(
+ arena,
+ try anon_decl.finish(
+ child_type,
+ try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),
+ ),
+ ),
);
},
else => return mod.fail(&block.base, src, "type '{}' has no members", .{child_type}),
@@ -6951,7 +7026,7 @@ fn namespaceLookupRef(
decl_name: []const u8,
) CompileError!?Air.Inst.Ref {
const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null;
- return try sema.analyzeDeclRef(block, src, decl);
+ return try sema.analyzeDeclRef(decl);
}
fn structFieldPtr(
@@ -7207,13 +7282,15 @@ fn elemPtrArray(
fn coerce(
sema: *Sema,
block: *Scope.Block,
- dest_type: Type,
+ dest_type_unresolved: Type,
inst: Air.Inst.Ref,
inst_src: LazySrcLoc,
) CompileError!Air.Inst.Ref {
- if (dest_type.tag() == .var_args_param) {
+ if (dest_type_unresolved.tag() == .var_args_param) {
return sema.coerceVarArgParam(block, inst, inst_src);
}
+ const dest_type_src = inst_src; // TODO better source location
+ const dest_type = try sema.resolveTypeFields(block, dest_type_src, dest_type_unresolved);
const inst_ty = sema.typeOf(inst);
// If the types are the same, we can return the operand.
@@ -7554,17 +7631,17 @@ fn analyzeDeclVal(
if (sema.decl_val_table.get(decl)) |result| {
return result;
}
- const decl_ref = try sema.analyzeDeclRef(block, src, decl);
+ const decl_ref = try sema.analyzeDeclRef(decl);
const result = try sema.analyzeLoad(block, src, decl_ref, src);
if (Air.refToIndex(result)) |index| {
if (sema.air_instructions.items(.tag)[index] == .constant) {
- sema.decl_val_table.put(sema.gpa, decl, result) catch {};
+ try sema.decl_val_table.put(sema.gpa, decl, result);
}
}
return result;
}
-fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) CompileError!Air.Inst.Ref {
+fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
try sema.mod.declareDeclDependency(sema.owner_decl, decl);
sema.mod.ensureDeclAnalyzed(decl) catch |err| {
if (sema.func) |func| {
@@ -7576,8 +7653,10 @@ fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl
};
const decl_tv = try decl.typedValue();
- if (decl_tv.val.tag() == .variable) {
- return sema.analyzeVarRef(block, src, decl_tv);
+ if (decl_tv.val.castTag(.variable)) |payload| {
+ const variable = payload.data;
+ const ty = try Module.simplePtrType(sema.arena, decl_tv.ty, variable.is_mutable, .One);
+ return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));
}
return sema.addConstant(
try Module.simplePtrType(sema.arena, decl_tv.ty, false, .One),
@@ -7585,26 +7664,6 @@ fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl
);
}
-fn analyzeVarRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, tv: TypedValue) CompileError!Air.Inst.Ref {
- const variable = tv.val.castTag(.variable).?.data;
-
- const ty = try Module.simplePtrType(sema.arena, tv.ty, variable.is_mutable, .One);
- if (!variable.is_mutable and !variable.is_extern) {
- return sema.addConstant(ty, try Value.Tag.ref_val.create(sema.arena, variable.init));
- }
-
- const gpa = sema.gpa;
- try sema.requireRuntimeBlock(block, src);
- try sema.air_variables.append(gpa, variable);
- return block.addInst(.{
- .tag = .varptr,
- .data = .{ .ty_pl = .{
- .ty = try sema.addType(ty),
- .payload = @intCast(u32, sema.air_variables.items.len - 1),
- } },
- });
-}
-
fn analyzeRef(
sema: *Sema,
block: *Scope.Block,
@@ -7615,11 +7674,21 @@ fn analyzeRef(
const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One);
if (try sema.resolveMaybeUndefVal(block, src, operand)) |val| {
- return sema.addConstant(ptr_type, try Value.Tag.ref_val.create(sema.arena, val));
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
+ return sema.addConstant(
+ ptr_type,
+ try Value.Tag.decl_ref.create(
+ sema.arena,
+ try anon_decl.finish(operand_ty, try val.copy(anon_decl.arena())),
+ ),
+ );
}
try sema.requireRuntimeBlock(block, src);
- return block.addTyOp(.ref, ptr_type, operand);
+ const alloc = try block.addTy(.alloc, ptr_type);
+ try sema.storePtr(block, src, alloc, operand);
+ return alloc;
}
fn analyzeLoad(
@@ -8447,12 +8516,12 @@ fn getTmpAir(sema: Sema) Air {
.instructions = sema.air_instructions.slice(),
.extra = sema.air_extra.items,
.values = sema.air_values.items,
- .variables = sema.air_variables.items,
};
}
pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
switch (ty.tag()) {
+ .u1 => return .u1_type,
.u8 => return .u8_type,
.i8 => return .i8_type,
.u16 => return .u16_type,
diff --git a/src/codegen.zig b/src/codegen.zig
index 3b822c0f88..b7ba367d54 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -848,13 +848,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.loop => try self.airLoop(inst),
.not => try self.airNot(inst),
.ptrtoint => try self.airPtrToInt(inst),
- .ref => try self.airRef(inst),
.ret => try self.airRet(inst),
.store => try self.airStore(inst),
.struct_field_ptr=> try self.airStructFieldPtr(inst),
.struct_field_val=> try self.airStructFieldVal(inst),
.switch_br => try self.airSwitch(inst),
- .varptr => try self.airVarPtr(inst),
.slice_ptr => try self.airSlicePtr(inst),
.slice_len => try self.airSliceLen(inst),
@@ -1340,13 +1338,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
- fn airVarPtr(self: *Self, inst: Air.Inst.Index) !void {
- const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
- else => return self.fail("TODO implement varptr for {}", .{self.target.cpu.arch}),
- };
- return self.finishAir(inst, result, .{ .none, .none, .none });
- }
-
fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
@@ -2833,38 +2824,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return bt.finishAir(result);
}
- fn airRef(self: *Self, inst: Air.Inst.Index) !void {
- const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
- const operand_ty = self.air.typeOf(ty_op.operand);
- const operand = try self.resolveInst(ty_op.operand);
- switch (operand) {
- .unreach => unreachable,
- .dead => unreachable,
- .none => break :result MCValue{ .none = {} },
-
- .immediate,
- .register,
- .ptr_stack_offset,
- .ptr_embedded_in_code,
- .compare_flags_unsigned,
- .compare_flags_signed,
- => {
- const stack_offset = try self.allocMemPtr(inst);
- try self.genSetStack(operand_ty, stack_offset, operand);
- break :result MCValue{ .ptr_stack_offset = stack_offset };
- },
-
- .stack_offset => |offset| break :result MCValue{ .ptr_stack_offset = offset },
- .embedded_in_code => |offset| break :result MCValue{ .ptr_embedded_in_code = offset },
- .memory => |vaddr| break :result MCValue{ .immediate = vaddr },
-
- .undef => return self.fail("TODO implement ref on an undefined value", .{}),
- }
- };
- return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
- }
-
fn ret(self: *Self, mcv: MCValue) !void {
const ret_ty = self.fn_type.fnReturnType();
try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 7299b21a61..a8ec677753 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -283,22 +283,7 @@ pub const DeclGen = struct {
},
else => switch (t.ptrSize()) {
.Slice => unreachable,
- .Many => {
- if (val.castTag(.ref_val)) |ref_val_payload| {
- const sub_val = ref_val_payload.data;
- if (sub_val.castTag(.bytes)) |bytes_payload| {
- const bytes = bytes_payload.data;
- try writer.writeByte('(');
- try dg.renderType(writer, t);
- // TODO: make our own C string escape instead of using std.zig.fmtEscapes
- try writer.print(")\"{}\"", .{std.zig.fmtEscapes(bytes)});
- } else {
- unreachable;
- }
- } else {
- unreachable;
- }
- },
+ .Many => unreachable,
.One => {
var arena = std.heap.ArenaAllocator.init(dg.module.gpa);
defer arena.deinit();
@@ -934,10 +919,8 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
.br => try airBr(o, inst),
.switch_br => try airSwitchBr(o, inst),
.wrap_optional => try airWrapOptional(o, inst),
- .ref => try airRef(o, inst),
.struct_field_ptr => try airStructFieldPtr(o, inst),
.struct_field_val => try airStructFieldVal(o, inst),
- .varptr => try airVarPtr(o, inst),
.slice_ptr => try airSliceField(o, inst, ".ptr;\n"),
.slice_len => try airSliceField(o, inst, ".len;\n"),
@@ -996,12 +979,6 @@ fn airSliceElemVal(o: *Object, inst: Air.Inst.Index, prefix: []const u8) !CValue
return local;
}
-fn airVarPtr(o: *Object, inst: Air.Inst.Index) !CValue {
- const ty_pl = o.air.instructions.items(.data)[inst].ty_pl;
- const variable = o.air.variables[ty_pl.payload];
- return CValue{ .decl_ref = variable.owner_decl };
-}
-
fn airAlloc(o: *Object, inst: Air.Inst.Index) !CValue {
const writer = o.writer();
const inst_ty = o.air.typeOfIndex(inst);
@@ -1653,22 +1630,6 @@ fn airOptionalPayload(o: *Object, inst: Air.Inst.Index) !CValue {
return local;
}
-fn airRef(o: *Object, inst: Air.Inst.Index) !CValue {
- if (o.liveness.isUnused(inst))
- return CValue.none;
-
- const ty_op = o.air.instructions.items(.data)[inst].ty_op;
- const writer = o.writer();
- const operand = try o.resolveInst(ty_op.operand);
-
- const inst_ty = o.air.typeOfIndex(inst);
- const local = try o.allocLocal(inst_ty, .Const);
- try writer.writeAll(" = ");
- try o.writeCValue(writer, operand);
- try writer.writeAll(";\n");
- return local;
-}
-
fn airStructFieldPtr(o: *Object, inst: Air.Inst.Index) !CValue {
if (o.liveness.isUnused(inst))
return CValue.none;
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 22f117aa1c..0e9a572bea 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -699,29 +699,12 @@ pub const DeclGen = struct {
.decl_ref => {
const decl = tv.val.castTag(.decl_ref).?.data;
const val = try self.resolveGlobalDecl(decl);
-
- const usize_type = try self.llvmType(Type.initTag(.usize));
-
- // TODO: second index should be the index into the memory!
- var indices: [2]*const llvm.Value = .{
- usize_type.constNull(),
- usize_type.constNull(),
- };
-
- return val.constInBoundsGEP(&indices, indices.len);
- },
- .ref_val => {
- //const elem_value = tv.val.castTag(.ref_val).?.data;
- //const elem_type = tv.ty.castPointer().?.data;
- //const alloca = fg.?.buildAlloca(try self.llvmType(elem_type));
- //_ = fg.?.builder.buildStore(try self.genTypedValue(.{ .ty = elem_type, .val = elem_value }, fg), alloca);
- //return alloca;
- // TODO eliminate the ref_val Value Tag
- return self.todo("implement const of pointer tag ref_val", .{});
+ return val.constBitCast(llvm_type);
},
.variable => {
const variable = tv.val.castTag(.variable).?.data;
- return self.resolveGlobalDecl(variable.owner_decl);
+ const val = try self.resolveGlobalDecl(variable.owner_decl);
+ return val.constBitCast(llvm_type);
},
.slice => {
const slice = tv.val.castTag(.slice).?.data;
@@ -977,7 +960,6 @@ pub const FuncGen = struct {
.ret => try self.airRet(inst),
.store => try self.airStore(inst),
.assembly => try self.airAssembly(inst),
- .varptr => try self.airVarPtr(inst),
.slice_ptr => try self.airSliceField(inst, 0),
.slice_len => try self.airSliceField(inst, 1),
@@ -1001,7 +983,6 @@ pub const FuncGen = struct {
.constant => unreachable,
.const_ty => unreachable,
- .ref => unreachable, // TODO eradicate this instruction
.unreach => self.airUnreach(inst),
.dbg_stmt => blk: {
// TODO: implement debug info
@@ -1180,16 +1161,6 @@ pub const FuncGen = struct {
return null;
}
- fn airVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
- if (self.liveness.isUnused(inst))
- return null;
-
- const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
- const variable = self.air.variables[ty_pl.payload];
- const decl_llvm_value = self.dg.resolveGlobalDecl(variable.owner_decl);
- return decl_llvm_value;
- }
-
fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index 6d09d69447..0977d6128d 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -112,6 +112,9 @@ pub const Value = opaque {
ConstantIndices: [*]const *const Value,
NumIndices: c_uint,
) *const Value;
+
+ pub const constBitCast = LLVMConstBitCast;
+ extern fn LLVMConstBitCast(ConstantVal: *const Value, ToType: *const Type) *const Value;
};
pub const Type = opaque {
diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig
index bf9010fbff..37cc6bc59c 100644
--- a/src/codegen/wasm.zig
+++ b/src/codegen/wasm.zig
@@ -754,22 +754,21 @@ pub const Context = struct {
}
/// Generates the wasm bytecode for the declaration belonging to `Context`
- pub fn gen(self: *Context, typed_value: TypedValue) InnerError!Result {
- switch (typed_value.ty.zigTypeTag()) {
+ pub fn gen(self: *Context, ty: Type, val: Value) InnerError!Result {
+ switch (ty.zigTypeTag()) {
.Fn => {
try self.genFunctype();
- if (typed_value.val.castTag(.extern_fn)) |_| return Result.appended; // don't need code body for extern functions
+ if (val.tag() == .extern_fn) {
+ return Result.appended; // don't need code body for extern functions
+ }
return self.fail("TODO implement wasm codegen for function pointers", .{});
},
.Array => {
- if (typed_value.val.castTag(.bytes)) |payload| {
- if (typed_value.ty.sentinel()) |sentinel| {
+ if (val.castTag(.bytes)) |payload| {
+ if (ty.sentinel()) |sentinel| {
try self.code.appendSlice(payload.data);
- switch (try self.gen(.{
- .ty = typed_value.ty.elemType(),
- .val = sentinel,
- })) {
+ switch (try self.gen(ty.elemType(), sentinel)) {
.appended => return Result.appended,
.externally_managed => |data| {
try self.code.appendSlice(data);
@@ -781,13 +780,17 @@ pub const Context = struct {
} else return self.fail("TODO implement gen for more kinds of arrays", .{});
},
.Int => {
- const info = typed_value.ty.intInfo(self.target);
+ const info = ty.intInfo(self.target);
if (info.bits == 8 and info.signedness == .unsigned) {
- const int_byte = typed_value.val.toUnsignedInt();
+ const int_byte = val.toUnsignedInt();
try self.code.append(@intCast(u8, int_byte));
return Result.appended;
}
- return self.fail("TODO: Implement codegen for int type: '{}'", .{typed_value.ty});
+ return self.fail("TODO: Implement codegen for int type: '{}'", .{ty});
+ },
+ .Enum => {
+ try self.emitConstant(val, ty);
+ return Result.appended;
},
else => |tag| return self.fail("TODO: Implement zig type codegen for type: '{s}'", .{tag}),
}
@@ -969,7 +972,7 @@ pub const Context = struct {
return WValue{ .code_offset = offset };
}
- fn emitConstant(self: *Context, value: Value, ty: Type) InnerError!void {
+ fn emitConstant(self: *Context, val: Value, ty: Type) InnerError!void {
const writer = self.code.writer();
switch (ty.zigTypeTag()) {
.Int => {
@@ -982,10 +985,10 @@ pub const Context = struct {
const int_info = ty.intInfo(self.target);
// write constant
switch (int_info.signedness) {
- .signed => try leb.writeILEB128(writer, value.toSignedInt()),
+ .signed => try leb.writeILEB128(writer, val.toSignedInt()),
.unsigned => switch (int_info.bits) {
- 0...32 => try leb.writeILEB128(writer, @bitCast(i32, @intCast(u32, value.toUnsignedInt()))),
- 33...64 => try leb.writeILEB128(writer, @bitCast(i64, value.toUnsignedInt())),
+ 0...32 => try leb.writeILEB128(writer, @bitCast(i32, @intCast(u32, val.toUnsignedInt()))),
+ 33...64 => try leb.writeILEB128(writer, @bitCast(i64, val.toUnsignedInt())),
else => |bits| return self.fail("Wasm TODO: emitConstant for integer with {d} bits", .{bits}),
},
}
@@ -994,7 +997,7 @@ pub const Context = struct {
// write opcode
try writer.writeByte(wasm.opcode(.i32_const));
// write constant
- try leb.writeILEB128(writer, value.toSignedInt());
+ try leb.writeILEB128(writer, val.toSignedInt());
},
.Float => {
// write opcode
@@ -1005,13 +1008,13 @@ pub const Context = struct {
try writer.writeByte(wasm.opcode(opcode));
// write constant
switch (ty.floatBits(self.target)) {
- 0...32 => try writer.writeIntLittle(u32, @bitCast(u32, value.toFloat(f32))),
- 64 => try writer.writeIntLittle(u64, @bitCast(u64, value.toFloat(f64))),
+ 0...32 => try writer.writeIntLittle(u32, @bitCast(u32, val.toFloat(f32))),
+ 64 => try writer.writeIntLittle(u64, @bitCast(u64, val.toFloat(f64))),
else => |bits| return self.fail("Wasm TODO: emitConstant for float with {d} bits", .{bits}),
}
},
.Pointer => {
- if (value.castTag(.decl_ref)) |payload| {
+ if (val.castTag(.decl_ref)) |payload| {
const decl = payload.data;
// offset into the offset table within the 'data' section
@@ -1024,11 +1027,11 @@ pub const Context = struct {
try writer.writeByte(wasm.opcode(.i32_load));
try leb.writeULEB128(writer, @as(u32, 0));
try leb.writeULEB128(writer, @as(u32, 0));
- } else return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{value.tag()});
+ } else return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{val.tag()});
},
.Void => {},
.Enum => {
- if (value.castTag(.enum_field_index)) |field_index| {
+ if (val.castTag(.enum_field_index)) |field_index| {
switch (ty.tag()) {
.enum_simple => {
try writer.writeByte(wasm.opcode(.i32_const));
@@ -1049,20 +1052,20 @@ pub const Context = struct {
} else {
var int_tag_buffer: Type.Payload.Bits = undefined;
const int_tag_ty = ty.intTagType(&int_tag_buffer);
- try self.emitConstant(value, int_tag_ty);
+ try self.emitConstant(val, int_tag_ty);
}
},
.ErrorSet => {
- const error_index = self.global_error_set.get(value.getError().?).?;
+ const error_index = self.global_error_set.get(val.getError().?).?;
try writer.writeByte(wasm.opcode(.i32_const));
try leb.writeULEB128(writer, error_index);
},
.ErrorUnion => {
- const data = value.castTag(.error_union).?.data;
+ const data = val.castTag(.error_union).?.data;
const error_type = ty.errorUnionSet();
const payload_type = ty.errorUnionPayload();
- if (value.getError()) |_| {
- // write the error value
+ if (val.getError()) |_| {
+ // write the error val
try self.emitConstant(data, error_type);
// no payload, so write a '0' const
@@ -1085,7 +1088,7 @@ pub const Context = struct {
}
/// Returns a `Value` as a signed 32 bit value.
- /// It's illegale to provide a value with a type that cannot be represented
+ /// It's illegal to provide a value with a type that cannot be represented
/// as an integer value.
fn valueAsI32(self: Context, val: Value, ty: Type) i32 {
switch (ty.zigTypeTag()) {
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index 23d0543494..3c3cd4eef3 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -275,7 +275,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
defer context.deinit();
// generate the 'code' section for the function declaration
- const result = context.gen(.{ .ty = decl.ty, .val = decl.val }) catch |err| switch (err) {
+ const result = context.gen(decl.ty, decl.val) catch |err| switch (err) {
error.CodegenFail => {
decl.analysis = .codegen_failure;
try module.failed_decls.put(module.gpa, decl, context.err_msg);
diff --git a/src/print_air.zig b/src/print_air.zig
index 2d5d6b588e..5d77c303bb 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -15,12 +15,11 @@ pub fn dump(gpa: *Allocator, air: Air, zir: Zir, liveness: Liveness) void {
(@sizeOf(Air.Inst.Tag) + 8);
const extra_bytes = air.extra.len * @sizeOf(u32);
const values_bytes = air.values.len * @sizeOf(Value);
- const variables_bytes = air.variables.len * @sizeOf(*Module.Var);
const tomb_bytes = liveness.tomb_bits.len * @sizeOf(usize);
const liveness_extra_bytes = liveness.extra.len * @sizeOf(u32);
const liveness_special_bytes = liveness.special.count() * 8;
const total_bytes = @sizeOf(Air) + instruction_bytes + extra_bytes +
- values_bytes * variables_bytes + @sizeOf(Liveness) + liveness_extra_bytes +
+ values_bytes + @sizeOf(Liveness) + liveness_extra_bytes +
liveness_special_bytes + tomb_bytes;
// zig fmt: off
@@ -29,7 +28,6 @@ pub fn dump(gpa: *Allocator, air: Air, zir: Zir, liveness: Liveness) void {
\\# AIR Instructions: {d} ({})
\\# AIR Extra Data: {d} ({})
\\# AIR Values Bytes: {d} ({})
- \\# AIR Variables Bytes: {d} ({})
\\# Liveness tomb_bits: {}
\\# Liveness Extra Data: {d} ({})
\\# Liveness special table: {d} ({})
@@ -39,7 +37,6 @@ pub fn dump(gpa: *Allocator, air: Air, zir: Zir, liveness: Liveness) void {
air.instructions.len, fmtIntSizeBin(instruction_bytes),
air.extra.len, fmtIntSizeBin(extra_bytes),
air.values.len, fmtIntSizeBin(values_bytes),
- air.variables.len, fmtIntSizeBin(variables_bytes),
fmtIntSizeBin(tomb_bytes),
liveness.extra.len, fmtIntSizeBin(liveness_extra_bytes),
liveness.special.count(), fmtIntSizeBin(liveness_special_bytes),
@@ -152,7 +149,6 @@ const Writer = struct {
.not,
.bitcast,
.load,
- .ref,
.floatcast,
.intcast,
.optional_payload,
@@ -174,7 +170,6 @@ const Writer = struct {
.struct_field_ptr => try w.writeStructField(s, inst),
.struct_field_val => try w.writeStructField(s, inst),
- .varptr => try w.writeVarPtr(s, inst),
.constant => try w.writeConstant(s, inst),
.assembly => try w.writeAssembly(s, inst),
.dbg_stmt => try w.writeDbgStmt(s, inst),
@@ -243,12 +238,6 @@ const Writer = struct {
try s.print(", {d}", .{extra.data.field_index});
}
- fn writeVarPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
- _ = w;
- _ = inst;
- try s.writeAll("TODO");
- }
-
fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
const val = w.air.values[ty_pl.payload];
diff --git a/src/value.zig b/src/value.zig
index 5d9fd27414..d3317ef31d 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -100,8 +100,6 @@ pub const Value = extern union {
function,
extern_fn,
variable,
- /// Represents a pointer to another immutable value.
- ref_val,
/// Represents a comptime variables storage.
comptime_alloc,
/// Represents a pointer to a decl, not the value of the decl.
@@ -126,6 +124,8 @@ pub const Value = extern union {
enum_field_index,
@"error",
error_union,
+ /// A pointer to the payload of an error union, based on a pointer to an error union.
+ eu_payload_ptr,
/// An instance of a struct.
@"struct",
/// An instance of a union.
@@ -214,9 +214,9 @@ pub const Value = extern union {
.decl_ref,
=> Payload.Decl,
- .ref_val,
.repeated,
.error_union,
+ .eu_payload_ptr,
=> Payload.SubValue,
.bytes,
@@ -407,15 +407,6 @@ pub const Value = extern union {
.function => return self.copyPayloadShallow(allocator, Payload.Function),
.extern_fn => return self.copyPayloadShallow(allocator, Payload.Decl),
.variable => return self.copyPayloadShallow(allocator, Payload.Variable),
- .ref_val => {
- const payload = self.castTag(.ref_val).?;
- const new_payload = try allocator.create(Payload.SubValue);
- new_payload.* = .{
- .base = payload.base,
- .data = try payload.data.copy(allocator),
- };
- return Value{ .ptr_otherwise = &new_payload.base };
- },
.comptime_alloc => return self.copyPayloadShallow(allocator, Payload.ComptimeAlloc),
.decl_ref => return self.copyPayloadShallow(allocator, Payload.Decl),
.elem_ptr => {
@@ -443,8 +434,8 @@ pub const Value = extern union {
return Value{ .ptr_otherwise = &new_payload.base };
},
.bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
- .repeated => {
- const payload = self.castTag(.repeated).?;
+ .repeated, .error_union, .eu_payload_ptr => {
+ const payload = self.cast(Payload.SubValue).?;
const new_payload = try allocator.create(Payload.SubValue);
new_payload.* = .{
.base = payload.base,
@@ -489,15 +480,6 @@ pub const Value = extern union {
},
.enum_field_index => return self.copyPayloadShallow(allocator, Payload.U32),
.@"error" => return self.copyPayloadShallow(allocator, Payload.Error),
- .error_union => {
- const payload = self.castTag(.error_union).?;
- const new_payload = try allocator.create(Payload.SubValue);
- new_payload.* = .{
- .base = payload.base,
- .data = try payload.data.copy(allocator),
- };
- return Value{ .ptr_otherwise = &new_payload.base };
- },
.@"struct" => @panic("TODO can't copy struct value without knowing the type"),
.@"union" => @panic("TODO can't copy union value without knowing the type"),
@@ -609,11 +591,6 @@ pub const Value = extern union {
.function => return out_stream.print("(function '{s}')", .{val.castTag(.function).?.data.owner_decl.name}),
.extern_fn => return out_stream.writeAll("(extern function)"),
.variable => return out_stream.writeAll("(variable)"),
- .ref_val => {
- const ref_val = val.castTag(.ref_val).?.data;
- try out_stream.writeAll("&const ");
- val = ref_val;
- },
.comptime_alloc => {
const ref_val = val.castTag(.comptime_alloc).?.data.val;
try out_stream.writeAll("&");
@@ -648,6 +625,10 @@ pub const Value = extern union {
// TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that
.error_union => return out_stream.print("error_union_val({})", .{val.castTag(.error_union).?.data}),
.inferred_alloc => return out_stream.writeAll("(inferred allocation value)"),
+ .eu_payload_ptr => {
+ try out_stream.writeAll("(eu_payload_ptr)");
+ val = val.castTag(.eu_payload_ptr).?.data;
+ },
};
}
@@ -758,7 +739,6 @@ pub const Value = extern union {
.function,
.extern_fn,
.variable,
- .ref_val,
.comptime_alloc,
.decl_ref,
.elem_ptr,
@@ -780,18 +760,21 @@ pub const Value = extern union {
.@"union",
.inferred_alloc,
.abi_align_default,
+ .eu_payload_ptr,
=> unreachable,
};
}
/// Asserts the type is an enum type.
- pub fn toEnum(val: Value, enum_ty: Type, comptime E: type) E {
- _ = enum_ty;
- // TODO this needs to resolve other kinds of Value tags rather than
- // assuming the tag will be .enum_field_index.
- const field_index = val.castTag(.enum_field_index).?.data;
- // TODO should `@intToEnum` do this `@intCast` for you?
- return @intToEnum(E, @intCast(@typeInfo(E).Enum.tag_type, field_index));
+ pub fn toEnum(val: Value, comptime E: type) E {
+ switch (val.tag()) {
+ .enum_field_index => {
+ const field_index = val.castTag(.enum_field_index).?.data;
+ // TODO should `@intToEnum` do this `@intCast` for you?
+ return @intToEnum(E, @intCast(@typeInfo(E).Enum.tag_type, field_index));
+ },
+ else => unreachable,
+ }
}
/// Asserts the value is an integer.
@@ -1255,6 +1238,9 @@ pub const Value = extern union {
.slice => {
@panic("TODO Value.hash for slice");
},
+ .eu_payload_ptr => {
+ @panic("TODO Value.hash for eu_payload_ptr");
+ },
.int_u64 => {
const payload = self.castTag(.int_u64).?;
std.hash.autoHash(&hasher, payload.data);
@@ -1263,10 +1249,6 @@ pub const Value = extern union {
const payload = self.castTag(.int_i64).?;
std.hash.autoHash(&hasher, payload.data);
},
- .ref_val => {
- const payload = self.castTag(.ref_val).?;
- std.hash.autoHash(&hasher, payload.data.hash());
- },
.comptime_alloc => {
const payload = self.castTag(.comptime_alloc).?;
std.hash.autoHash(&hasher, payload.data.val.hash());
@@ -1367,7 +1349,6 @@ pub const Value = extern union {
pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value {
return switch (self.tag()) {
.comptime_alloc => self.castTag(.comptime_alloc).?.data.val,
- .ref_val => self.castTag(.ref_val).?.data,
.decl_ref => self.castTag(.decl_ref).?.data.value(),
.elem_ptr => {
const elem_ptr = self.castTag(.elem_ptr).?.data;
@@ -1379,6 +1360,11 @@ pub const Value = extern union {
const container_val = try field_ptr.container_ptr.pointerDeref(allocator);
return container_val.fieldValue(allocator, field_ptr.field_index);
},
+ .eu_payload_ptr => {
+ const err_union_ptr = self.castTag(.eu_payload_ptr).?.data;
+ const err_union_val = try err_union_ptr.pointerDeref(allocator);
+ return err_union_val.castTag(.error_union).?.data;
+ },
else => unreachable,
};
@@ -1390,7 +1376,6 @@ pub const Value = extern union {
.bytes => val.castTag(.bytes).?.data.len,
.array => val.castTag(.array).?.data.len,
.slice => val.castTag(.slice).?.data.len.toUnsignedInt(),
- .ref_val => sliceLen(val.castTag(.ref_val).?.data),
.decl_ref => {
const decl = val.castTag(.decl_ref).?.data;
if (decl.ty.zigTypeTag() == .Array) {
@@ -1576,7 +1561,6 @@ pub const Value = extern union {
.int_i64,
.int_big_positive,
.int_big_negative,
- .ref_val,
.comptime_alloc,
.decl_ref,
.elem_ptr,
@@ -1599,6 +1583,7 @@ pub const Value = extern union {
.@"union",
.null_value,
.abi_align_default,
+ .eu_payload_ptr,
=> false,
.undef => unreachable,
diff --git a/test/cases.zig b/test/cases.zig
index f235992f71..840ee7a4ac 100644
--- a/test/cases.zig
+++ b/test/cases.zig
@@ -1182,10 +1182,11 @@ pub fn addCases(ctx: *TestContext) !void {
var case = ctx.obj("extern variable has no type", linux_x64);
case.addError(
\\comptime {
- \\ _ = foo;
+ \\ const x = foo + foo;
+ \\ _ = x;
\\}
\\extern var foo: i32;
- , &[_][]const u8{":2:9: error: unable to resolve comptime value"});
+ , &[_][]const u8{":2:15: error: unable to resolve comptime value"});
case.addError(
\\export fn entry() void {
\\ _ = foo;
From 040c6eaaa03bbcfcdeadbe835c1c2f209e9f401e Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 29 Jul 2021 19:30:37 -0700
Subject: [PATCH 30/96] stage2: garbage collect unused anon decls
After this change, the frontend and backend cooperate to keep track of
which Decls are actually emitted into the machine code. When any backend
sees a `decl_ref` Value, it must mark the corresponding Decl `alive`
field to true.
This prevents unused comptime data from spilling into the output object
files. For example, if you do an `inline for` loop, previously, any
intermediate value calculations would have gone into the object file.
Now they are garbage collected immediately after the owner Decl has its
machine code generated.
In the frontend, when it is time to send a Decl to the linker, if it has
not been marked "alive" then it is deleted instead.
Additional improvements:
* Resolve type ABI layouts after successful semantic analysis of a
Decl. This is needed so that the backend has access to struct fields.
* Sema: fix incorrect logic in resolveMaybeUndefVal. It should return
"not comptime known" instead of a compile error for global variables.
* `Value.pointerDeref` now returns `null` in the case that the pointer
deref cannot happen at compile-time. This is true for global
variables, for example. Another example is if a comptime known
pointer has a hard coded address value.
* Binary arithmetic sets the requireRuntimeBlock source location to the
lhs_src or rhs_src as appropriate instead of on the operator node.
* Fix LLVM codegen for slice_elem_val which had the wrong logic for
when the operand was not a pointer.
As noted in the comment in the implementation of deleteUnusedDecl, a
future improvement will be to rework the frontend/linker interface to
remove the frontend's responsibility of calling allocateDeclIndexes.
I discovered some issues with the plan9 linker backend that are related
to this, and worked around them for now.
---
src/Compilation.zig | 10 ++-
src/Module.zig | 60 ++++++++++++++---
src/Sema.zig | 154 ++++++++++++++++++++++---------------------
src/codegen.zig | 7 +-
src/codegen/c.zig | 24 ++-----
src/codegen/llvm.zig | 51 +++++++++-----
src/codegen/wasm.zig | 1 +
src/link/Plan9.zig | 19 ++++--
src/value.zig | 45 +++++++++----
test/stage2/cbe.zig | 2 +-
10 files changed, 234 insertions(+), 139 deletions(-)
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 8672a346c3..f8f8cea328 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -2061,11 +2061,19 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
.complete, .codegen_failure_retryable => {
if (build_options.omit_stage2)
@panic("sadly stage2 is omitted from this build to save memory on the CI server");
+
const module = self.bin_file.options.module.?;
assert(decl.has_tv);
assert(decl.ty.hasCodeGenBits());
- try module.linkerUpdateDecl(decl);
+ if (decl.alive) {
+ try module.linkerUpdateDecl(decl);
+ continue;
+ }
+
+ // Instead of sending this decl to the linker, we actually will delete it
+ // because we found out that it in fact was never referenced.
+ module.deleteUnusedDecl(decl);
},
},
.codegen_func => |func| switch (func.owner_decl.analysis) {
diff --git a/src/Module.zig b/src/Module.zig
index f89f72bc65..909e54ffa2 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -255,6 +255,15 @@ pub const Decl = struct {
has_align: bool,
/// Whether the ZIR code provides a linksection instruction.
has_linksection: bool,
+ /// Flag used by garbage collection to mark and sweep.
+ /// Decls which correspond to an AST node always have this field set to `true`.
+ /// Anonymous Decls are initialized with this field set to `false` and then it
+ /// is the responsibility of machine code backends to mark it `true` whenever
+ /// a `decl_ref` Value is encountered that points to this Decl.
+ /// When the `codegen_decl` job is encountered in the main work queue, if the
+ /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it
+ /// deletes the Decl on the spot.
+ alive: bool,
/// Represents the position of the code in the output file.
/// This is populated regardless of semantic analysis and code generation.
@@ -2869,6 +2878,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void {
new_decl.val = struct_val;
new_decl.has_tv = true;
new_decl.owns_tv = true;
+ new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive.
new_decl.analysis = .in_progress;
new_decl.generation = mod.generation;
@@ -2990,6 +3000,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
if (linksection_ref == .none) break :blk Value.initTag(.null_value);
break :blk (try sema.resolveInstConst(&block_scope, src, linksection_ref)).val;
};
+ try sema.resolveTypeLayout(&block_scope, src, decl_tv.ty);
// We need the memory for the Type to go into the arena for the Decl
var decl_arena = std.heap.ArenaAllocator.init(gpa);
@@ -3027,8 +3038,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
const is_inline = decl_tv.ty.fnCallingConvention() == .Inline;
if (!is_inline and decl_tv.ty.hasCodeGenBits()) {
// We don't fully codegen the decl until later, but we do need to reserve a global
- // offset table index for it. This allows us to codegen decls out of dependency order,
- // increasing how many computations can be done in parallel.
+ // offset table index for it. This allows us to codegen decls out of dependency
+ // order, increasing how many computations can be done in parallel.
try mod.comp.bin_file.allocateDeclIndexes(decl);
try mod.comp.work_queue.writeItem(.{ .codegen_func = func });
if (type_changed and mod.emit_h != null) {
@@ -3387,6 +3398,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi
new_decl.has_align = has_align;
new_decl.has_linksection = has_linksection;
new_decl.zir_decl_index = @intCast(u32, decl_sub_index);
+ new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive.
return;
}
gpa.free(decl_name);
@@ -3526,6 +3538,43 @@ pub fn clearDecl(
decl.analysis = .unreferenced;
}
+pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void {
+ log.debug("deleteUnusedDecl {*} ({s})", .{ decl, decl.name });
+
+ // TODO: remove `allocateDeclIndexes` and make the API that the linker backends
+ // are required to notice the first time `updateDecl` happens and keep track
+ // of it themselves. However they can rely on getting a `freeDecl` call if any
+ // `updateDecl` or `updateFunc` calls happen. This will allow us to avoid any call
+ // into the linker backend here, since the linker backend will never have been told
+ // about the Decl in the first place.
+ // Until then, we did call `allocateDeclIndexes` on this anonymous Decl and so we
+ // must call `freeDecl` in the linker backend now.
+ if (decl.has_tv) {
+ if (decl.ty.hasCodeGenBits()) {
+ mod.comp.bin_file.freeDecl(decl);
+ }
+ }
+
+ const dependants = decl.dependants.keys();
+ assert(dependants[0].namespace.anon_decls.swapRemove(decl));
+
+ for (dependants) |dep| {
+ dep.removeDependency(decl);
+ }
+
+ for (decl.dependencies.keys()) |dep| {
+ dep.removeDependant(decl);
+ }
+ decl.destroy(mod);
+}
+
+pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void {
+ log.debug("deleteAnonDecl {*} ({s})", .{ decl, decl.name });
+ const scope_decl = scope.ownerDecl().?;
+ assert(scope_decl.namespace.anon_decls.swapRemove(decl));
+ decl.destroy(mod);
+}
+
/// Delete all the Export objects that are caused by this Decl. Re-analysis of
/// this Decl will cause them to be re-created (or not).
fn deleteDeclExports(mod: *Module, decl: *Decl) void {
@@ -3713,6 +3762,7 @@ fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node
.is_exported = false,
.has_linksection = false,
.has_align = false,
+ .alive = false,
};
return new_decl;
}
@@ -3802,12 +3852,6 @@ pub fn analyzeExport(
errdefer de_gop.value_ptr.* = mod.gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1);
}
-pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void {
- const scope_decl = scope.ownerDecl().?;
- assert(scope_decl.namespace.anon_decls.swapRemove(decl));
- decl.destroy(mod);
-}
-
/// Takes ownership of `name` even if it returns an error.
pub fn createAnonymousDeclNamed(
mod: *Module,
diff --git a/src/Sema.zig b/src/Sema.zig
index 95baae7e92..0da38d9a76 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -696,7 +696,7 @@ fn resolveMaybeUndefVal(
) CompileError!?Value {
const val = (try sema.resolveMaybeUndefValAllowVariables(block, src, inst)) orelse return null;
if (val.tag() == .variable) {
- return sema.failWithNeededComptime(block, src);
+ return null;
}
return val;
}
@@ -2917,12 +2917,13 @@ fn zirOptionalPayloadPtr(
const child_pointer = try Module.simplePtrType(sema.arena, child_type, !optional_ptr_ty.isConstPtr(), .One);
if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| {
- const val = try pointer_val.pointerDeref(sema.arena);
- if (val.isNull()) {
- return sema.mod.fail(&block.base, src, "unable to unwrap null", .{});
+ if (try pointer_val.pointerDeref(sema.arena)) |val| {
+ if (val.isNull()) {
+ return sema.mod.fail(&block.base, src, "unable to unwrap null", .{});
+ }
+ // The same Value represents the pointer to the optional and the payload.
+ return sema.addConstant(child_pointer, pointer_val);
}
- // The same Value represents the pointer to the optional and the payload.
- return sema.addConstant(child_pointer, pointer_val);
}
try sema.requireRuntimeBlock(block, src);
@@ -3027,14 +3028,15 @@ fn zirErrUnionPayloadPtr(
const operand_pointer_ty = try Module.simplePtrType(sema.arena, payload_ty, !operand_ty.isConstPtr(), .One);
if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
- const val = try pointer_val.pointerDeref(sema.arena);
- if (val.getError()) |name| {
- return sema.mod.fail(&block.base, src, "caught unexpected error '{s}'", .{name});
+ if (try pointer_val.pointerDeref(sema.arena)) |val| {
+ if (val.getError()) |name| {
+ return sema.mod.fail(&block.base, src, "caught unexpected error '{s}'", .{name});
+ }
+ return sema.addConstant(
+ operand_pointer_ty,
+ try Value.Tag.eu_payload_ptr.create(sema.arena, pointer_val),
+ );
}
- return sema.addConstant(
- operand_pointer_ty,
- try Value.Tag.eu_payload_ptr.create(sema.arena, pointer_val),
- );
}
try sema.requireRuntimeBlock(block, src);
@@ -3086,10 +3088,11 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
const result_ty = operand_ty.elemType().errorUnionSet();
if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
- const val = try pointer_val.pointerDeref(sema.arena);
- assert(val.getError() != null);
- const data = val.castTag(.error_union).?.data;
- return sema.addConstant(result_ty, data);
+ if (try pointer_val.pointerDeref(sema.arena)) |val| {
+ assert(val.getError() != null);
+ const data = val.castTag(.error_union).?.data;
+ return sema.addConstant(result_ty, data);
+ }
}
try sema.requireRuntimeBlock(block, src);
@@ -4920,10 +4923,13 @@ fn analyzeArithmetic(
log.debug("{s}({}, {}) result: {}", .{ @tagName(zir_tag), lhs_val, rhs_val, value });
return sema.addConstant(scalar_type, value);
+ } else {
+ try sema.requireRuntimeBlock(block, rhs_src);
}
+ } else {
+ try sema.requireRuntimeBlock(block, lhs_src);
}
- try sema.requireRuntimeBlock(block, src);
const air_tag: Air.Inst.Tag = switch (zir_tag) {
.add => .add,
.addwrap => .addwrap,
@@ -6811,16 +6817,10 @@ fn fieldPtr(
if (mem.eql(u8, field_name, "len")) {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- return sema.addConstant(
- Type.initTag(.single_const_pointer_to_comptime_int),
- try Value.Tag.decl_ref.create(
- arena,
- try anon_decl.finish(
- Type.initTag(.comptime_int),
- try Value.Tag.int_u64.create(anon_decl.arena(), object_ty.arrayLen()),
- ),
- ),
- );
+ return sema.analyzeDeclRef(try anon_decl.finish(
+ Type.initTag(.comptime_int),
+ try Value.Tag.int_u64.create(anon_decl.arena(), object_ty.arrayLen()),
+ ));
} else {
return mod.fail(
&block.base,
@@ -6867,16 +6867,10 @@ fn fieldPtr(
if (mem.eql(u8, field_name, "len")) {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- return sema.addConstant(
- Type.initTag(.single_const_pointer_to_comptime_int),
- try Value.Tag.decl_ref.create(
- arena,
- try anon_decl.finish(
- Type.initTag(.comptime_int),
- try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()),
- ),
- ),
- );
+ return sema.analyzeDeclRef(try anon_decl.finish(
+ Type.initTag(.comptime_int),
+ try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()),
+ ));
} else {
return mod.fail(
&block.base,
@@ -6915,16 +6909,10 @@ fn fieldPtr(
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- return sema.addConstant(
- try Module.simplePtrType(arena, child_type, false, .One),
- try Value.Tag.decl_ref.create(
- arena,
- try anon_decl.finish(
- child_type,
- try Value.Tag.@"error".create(anon_decl.arena(), .{ .name = name }),
- ),
- ),
- );
+ return sema.analyzeDeclRef(try anon_decl.finish(
+ child_type,
+ try Value.Tag.@"error".create(anon_decl.arena(), .{ .name = name }),
+ ));
},
.Struct, .Opaque, .Union => {
if (child_type.getNamespace()) |namespace| {
@@ -6971,16 +6959,10 @@ fn fieldPtr(
const field_index_u32 = @intCast(u32, field_index);
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- return sema.addConstant(
- try Module.simplePtrType(arena, child_type, false, .One),
- try Value.Tag.decl_ref.create(
- arena,
- try anon_decl.finish(
- child_type,
- try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),
- ),
- ),
- );
+ return sema.analyzeDeclRef(try anon_decl.finish(
+ child_type,
+ try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),
+ ));
},
else => return mod.fail(&block.base, src, "type '{}' has no members", .{child_type}),
}
@@ -7671,21 +7653,18 @@ fn analyzeRef(
operand: Air.Inst.Ref,
) CompileError!Air.Inst.Ref {
const operand_ty = sema.typeOf(operand);
- const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One);
if (try sema.resolveMaybeUndefVal(block, src, operand)) |val| {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- return sema.addConstant(
- ptr_type,
- try Value.Tag.decl_ref.create(
- sema.arena,
- try anon_decl.finish(operand_ty, try val.copy(anon_decl.arena())),
- ),
- );
+ return sema.analyzeDeclRef(try anon_decl.finish(
+ operand_ty,
+ try val.copy(anon_decl.arena()),
+ ));
}
try sema.requireRuntimeBlock(block, src);
+ const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One);
const alloc = try block.addTy(.alloc, ptr_type);
try sema.storePtr(block, src, alloc, operand);
return alloc;
@@ -7703,11 +7682,10 @@ fn analyzeLoad(
.Pointer => ptr_ty.elemType(),
else => return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr_ty}),
};
- if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| blk: {
- if (ptr_val.tag() == .int_u64)
- break :blk; // do it at runtime
-
- return sema.addConstant(elem_ty, try ptr_val.pointerDeref(sema.arena));
+ if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
+ if (try ptr_val.pointerDeref(sema.arena)) |elem_val| {
+ return sema.addConstant(elem_ty, elem_val);
+ }
}
try sema.requireRuntimeBlock(block, src);
@@ -8215,6 +8193,36 @@ fn resolvePeerTypes(
return sema.typeOf(chosen);
}
+pub fn resolveTypeLayout(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ ty: Type,
+) CompileError!void {
+ switch (ty.zigTypeTag()) {
+ .Pointer => {
+ return sema.resolveTypeLayout(block, src, ty.elemType());
+ },
+ .Struct => {
+ const resolved_ty = try sema.resolveTypeFields(block, src, ty);
+ const struct_obj = resolved_ty.castTag(.@"struct").?.data;
+ switch (struct_obj.status) {
+ .none, .have_field_types => {},
+ .field_types_wip, .layout_wip => {
+ return sema.mod.fail(&block.base, src, "struct {} depends on itself", .{ty});
+ },
+ .have_layout => return,
+ }
+ struct_obj.status = .layout_wip;
+ for (struct_obj.fields.values()) |field| {
+ try sema.resolveTypeLayout(block, src, field.ty);
+ }
+ struct_obj.status = .have_layout;
+ },
+ else => {},
+ }
+}
+
fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) CompileError!Type {
switch (ty.tag()) {
.@"struct" => {
@@ -8222,9 +8230,7 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type
switch (struct_obj.status) {
.none => {},
.field_types_wip => {
- return sema.mod.fail(&block.base, src, "struct {} depends on itself", .{
- ty,
- });
+ return sema.mod.fail(&block.base, src, "struct {} depends on itself", .{ty});
},
.have_field_types, .have_layout, .layout_wip => return ty,
}
diff --git a/src/codegen.zig b/src/codegen.zig
index b7ba367d54..d16a87adca 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -184,6 +184,7 @@ pub fn generateSymbol(
if (typed_value.val.castTag(.decl_ref)) |payload| {
const decl = payload.data;
if (decl.analysis != .complete) return error.AnalysisFail;
+ decl.alive = true;
// TODO handle the dependency of this symbol on the decl's vaddr.
// If the decl changes vaddr, then this symbol needs to get regenerated.
const vaddr = bin_file.getDeclVAddr(decl);
@@ -4680,13 +4681,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
},
else => {
if (typed_value.val.castTag(.decl_ref)) |payload| {
+ const decl = payload.data;
+ decl.alive = true;
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
- const decl = payload.data;
const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
return MCValue{ .memory = got_addr };
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
- const decl = payload.data;
const got_addr = blk: {
const seg = macho_file.load_commands.items[macho_file.data_const_segment_cmd_index.?].Segment;
const got = seg.sections.items[macho_file.got_section_index.?];
@@ -4698,11 +4699,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
};
return MCValue{ .memory = got_addr };
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
- const decl = payload.data;
const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
return MCValue{ .memory = got_addr };
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
- const decl = payload.data;
const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
return MCValue{ .memory = got_addr };
} else {
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index a8ec677753..826b73317c 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -262,6 +262,7 @@ pub const DeclGen = struct {
.one => try writer.writeAll("1"),
.decl_ref => {
const decl = val.castTag(.decl_ref).?.data;
+ decl.alive = true;
// Determine if we must pointer cast.
assert(decl.has_tv);
@@ -281,21 +282,7 @@ pub const DeclGen = struct {
const decl = val.castTag(.extern_fn).?.data;
try writer.print("{s}", .{decl.name});
},
- else => switch (t.ptrSize()) {
- .Slice => unreachable,
- .Many => unreachable,
- .One => {
- var arena = std.heap.ArenaAllocator.init(dg.module.gpa);
- defer arena.deinit();
-
- const elem_ty = t.elemType();
- const elem_val = try val.pointerDeref(&arena.allocator);
-
- try writer.writeAll("&");
- try dg.renderValue(writer, elem_ty, elem_val);
- },
- .C => unreachable,
- },
+ else => unreachable,
},
},
.Array => {
@@ -421,6 +408,7 @@ pub const DeclGen = struct {
.one => try writer.writeAll("1"),
.decl_ref => {
const decl = val.castTag(.decl_ref).?.data;
+ decl.alive = true;
// Determine if we must pointer cast.
assert(decl.has_tv);
@@ -433,11 +421,13 @@ pub const DeclGen = struct {
}
},
.function => {
- const func = val.castTag(.function).?.data;
- try writer.print("{s}", .{func.owner_decl.name});
+ const decl = val.castTag(.function).?.data.owner_decl;
+ decl.alive = true;
+ try writer.print("{s}", .{decl.name});
},
.extern_fn => {
const decl = val.castTag(.extern_fn).?.data;
+ decl.alive = true;
try writer.print("{s}", .{decl.name});
},
else => unreachable,
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 0e9a572bea..961ed7ee99 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -673,17 +673,21 @@ pub const DeclGen = struct {
}
fn genTypedValue(self: *DeclGen, tv: TypedValue) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
- const llvm_type = try self.llvmType(tv.ty);
-
- if (tv.val.isUndef())
+ if (tv.val.isUndef()) {
+ const llvm_type = try self.llvmType(tv.ty);
return llvm_type.getUndef();
+ }
switch (tv.ty.zigTypeTag()) {
- .Bool => return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(),
+ .Bool => {
+ const llvm_type = try self.llvmType(tv.ty);
+ return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();
+ },
.Int => {
var bigint_space: Value.BigIntSpace = undefined;
const bigint = tv.val.toBigInt(&bigint_space);
+ const llvm_type = try self.llvmType(tv.ty);
if (bigint.eqZero()) return llvm_type.constNull();
if (bigint.limbs.len != 1) {
@@ -698,12 +702,17 @@ pub const DeclGen = struct {
.Pointer => switch (tv.val.tag()) {
.decl_ref => {
const decl = tv.val.castTag(.decl_ref).?.data;
+ decl.alive = true;
const val = try self.resolveGlobalDecl(decl);
+ const llvm_type = try self.llvmType(tv.ty);
return val.constBitCast(llvm_type);
},
.variable => {
- const variable = tv.val.castTag(.variable).?.data;
- const val = try self.resolveGlobalDecl(variable.owner_decl);
+ const decl = tv.val.castTag(.variable).?.data.owner_decl;
+ decl.alive = true;
+ const val = try self.resolveGlobalDecl(decl);
+ const llvm_var_type = try self.llvmType(tv.ty);
+ const llvm_type = llvm_var_type.pointerType(0);
return val.constBitCast(llvm_type);
},
.slice => {
@@ -783,6 +792,7 @@ pub const DeclGen = struct {
.decl_ref => tv.val.castTag(.decl_ref).?.data,
else => unreachable,
};
+ fn_decl.alive = true;
return self.resolveLlvmFunction(fn_decl);
},
.ErrorSet => {
@@ -903,9 +913,7 @@ pub const FuncGen = struct {
return self.dg.genTypedValue(.{ .ty = self.air.typeOf(inst), .val = val });
}
const inst_index = Air.refToIndex(inst).?;
- if (self.func_inst_table.get(inst_index)) |value| return value;
-
- return self.todo("implement global llvm values (or the value is not in the func_inst_table table)", .{});
+ return self.func_inst_table.get(inst_index).?;
}
fn genBody(self: *FuncGen, body: []const Air.Inst.Index) error{ OutOfMemory, CodegenFail }!void {
@@ -966,8 +974,8 @@ pub const FuncGen = struct {
.struct_field_ptr => try self.airStructFieldPtr(inst),
.struct_field_val => try self.airStructFieldVal(inst),
- .slice_elem_val => try self.airSliceElemVal(inst, false),
- .ptr_slice_elem_val => try self.airSliceElemVal(inst, true),
+ .slice_elem_val => try self.airSliceElemVal(inst),
+ .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst),
.optional_payload => try self.airOptionalPayload(inst, false),
.optional_payload_ptr => try self.airOptionalPayload(inst, true),
@@ -1170,11 +1178,20 @@ pub const FuncGen = struct {
return self.builder.buildExtractValue(operand, index, "");
}
- fn airSliceElemVal(
- self: *FuncGen,
- inst: Air.Inst.Index,
- operand_is_ptr: bool,
- ) !?*const llvm.Value {
+ fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
+ const base_ptr = self.builder.buildExtractValue(lhs, 0, "");
+ const indices: [1]*const llvm.Value = .{rhs};
+ const ptr = self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, "");
+ return self.builder.buildLoad(ptr, "");
+ }
+
+ fn airPtrSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
@@ -1182,7 +1199,7 @@ pub const FuncGen = struct {
const lhs = try self.resolveInst(bin_op.lhs);
const rhs = try self.resolveInst(bin_op.rhs);
- const base_ptr = if (!operand_is_ptr) lhs else ptr: {
+ const base_ptr = ptr: {
const index_type = self.context.intType(32);
const indices: [2]*const llvm.Value = .{
index_type.constNull(),
diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig
index 37cc6bc59c..2f1632e0fc 100644
--- a/src/codegen/wasm.zig
+++ b/src/codegen/wasm.zig
@@ -1016,6 +1016,7 @@ pub const Context = struct {
.Pointer => {
if (val.castTag(.decl_ref)) |payload| {
const decl = payload.data;
+ decl.alive = true;
// offset into the offset table within the 'data' section
const ptr_width = self.target.cpu.arch.ptrBitWidth() / 8;
diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig
index 135b59f82b..3b2aae85bc 100644
--- a/src/link/Plan9.zig
+++ b/src/link/Plan9.zig
@@ -224,7 +224,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {
const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
- assert(self.got_len == self.fn_decl_table.count() + self.data_decl_table.count());
+ // TODO I changed this assert from == to >= but this code all needs to be audited; see
+ // the comment in `freeDecl`.
+ assert(self.got_len >= self.fn_decl_table.count() + self.data_decl_table.count());
const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8;
var got_table = try self.base.allocator.alloc(u8, got_size);
defer self.base.allocator.free(got_table);
@@ -358,11 +360,18 @@ fn addDeclExports(
}
pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void {
+ // TODO this is not the correct check for being function body,
+ // it could just be a function pointer.
+ // TODO audit the lifetimes of decls table entries. It's possible to get
+ // allocateDeclIndexes and then freeDecl without any updateDecl in between.
+ // However that is planned to change, see the TODO comment in Module.zig
+ // in the deleteUnusedDecl function.
const is_fn = (decl.ty.zigTypeTag() == .Fn);
- if (is_fn)
- assert(self.fn_decl_table.swapRemove(decl))
- else
- assert(self.data_decl_table.swapRemove(decl));
+ if (is_fn) {
+ _ = self.fn_decl_table.swapRemove(decl);
+ } else {
+ _ = self.data_decl_table.swapRemove(decl);
+ }
}
pub fn updateDeclExports(
diff --git a/src/value.zig b/src/value.zig
index d3317ef31d..32be34ee2c 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -103,6 +103,7 @@ pub const Value = extern union {
/// Represents a comptime variables storage.
comptime_alloc,
/// Represents a pointer to a decl, not the value of the decl.
+ /// When machine codegen backend sees this, it must set the Decl's `alive` field to true.
decl_ref,
elem_ptr,
field_ptr,
@@ -1346,28 +1347,48 @@ pub const Value = extern union {
/// Asserts the value is a pointer and dereferences it.
/// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis.
- pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value {
- return switch (self.tag()) {
+ pub fn pointerDeref(
+ self: Value,
+ allocator: *Allocator,
+ ) error{ AnalysisFail, OutOfMemory }!?Value {
+ const sub_val: Value = switch (self.tag()) {
.comptime_alloc => self.castTag(.comptime_alloc).?.data.val,
- .decl_ref => self.castTag(.decl_ref).?.data.value(),
- .elem_ptr => {
+ .decl_ref => try self.castTag(.decl_ref).?.data.value(),
+ .elem_ptr => blk: {
const elem_ptr = self.castTag(.elem_ptr).?.data;
- const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);
- return array_val.elemValue(allocator, elem_ptr.index);
+ const array_val = (try elem_ptr.array_ptr.pointerDeref(allocator)) orelse return null;
+ break :blk try array_val.elemValue(allocator, elem_ptr.index);
},
- .field_ptr => {
+ .field_ptr => blk: {
const field_ptr = self.castTag(.field_ptr).?.data;
- const container_val = try field_ptr.container_ptr.pointerDeref(allocator);
- return container_val.fieldValue(allocator, field_ptr.field_index);
+ const container_val = (try field_ptr.container_ptr.pointerDeref(allocator)) orelse return null;
+ break :blk try container_val.fieldValue(allocator, field_ptr.field_index);
},
- .eu_payload_ptr => {
+ .eu_payload_ptr => blk: {
const err_union_ptr = self.castTag(.eu_payload_ptr).?.data;
- const err_union_val = try err_union_ptr.pointerDeref(allocator);
- return err_union_val.castTag(.error_union).?.data;
+ const err_union_val = (try err_union_ptr.pointerDeref(allocator)) orelse return null;
+ break :blk err_union_val.castTag(.error_union).?.data;
},
+ .zero,
+ .one,
+ .int_u64,
+ .int_i64,
+ .int_big_positive,
+ .int_big_negative,
+ .variable,
+ .extern_fn,
+ .function,
+ => return null,
+
else => unreachable,
};
+ if (sub_val.tag() == .variable) {
+ // This would be loading a runtime value at compile-time so we return
+ // the indicator that this pointer dereference requires being done at runtime.
+ return null;
+ }
+ return sub_val;
}
pub fn sliceLen(val: Value) u64 {
diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig
index 6427e2e3b8..4f7d80d1fa 100644
--- a/test/stage2/cbe.zig
+++ b/test/stage2/cbe.zig
@@ -49,7 +49,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\export fn foo() callconv(y) c_int {
\\ return 0;
\\}
- \\var y: i32 = 1234;
+ \\var y: @import("std").builtin.CallingConvention = .C;
, &.{
":2:22: error: unable to resolve comptime value",
":5:26: error: unable to resolve comptime value",
From f6b1fa9e29ccab77a54e92dc13a7eb8e407bdbbc Mon Sep 17 00:00:00 2001
From: joachimschmidt557
Date: Fri, 30 Jul 2021 11:43:17 +0200
Subject: [PATCH 31/96] stage2 codegen: genTypedValue for error unions and
error sets
---
src/codegen.zig | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/src/codegen.zig b/src/codegen.zig
index d16a87adca..0917f2c847 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -19,7 +19,6 @@ const DW = std.dwarf;
const leb128 = std.leb;
const log = std.log.scoped(.codegen);
const build_options = @import("build_options");
-const LazySrcLoc = Module.LazySrcLoc;
const RegisterManager = @import("register_manager.zig").RegisterManager;
const X8664Encoder = @import("codegen/x86_64.zig").Encoder;
@@ -4741,6 +4740,33 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
}
return self.fail("TODO non pointer optionals", .{});
},
+ .ErrorSet => {
+ switch (typed_value.val.tag()) {
+ .@"error" => {
+ const err_name = typed_value.val.castTag(.@"error").?.data.name;
+ const module = self.bin_file.options.module.?;
+ const global_error_set = module.global_error_set;
+ const error_index = global_error_set.get(err_name).?;
+ return MCValue{ .immediate = error_index };
+ },
+ else => {
+ // In this case we are rendering an error union which has a 0 bits payload.
+ return MCValue{ .immediate = 0 };
+ },
+ }
+ },
+ .ErrorUnion => {
+ const error_type = typed_value.ty.errorUnionSet();
+ const payload_type = typed_value.ty.errorUnionPayload();
+ const sub_val = typed_value.val.castTag(.error_union).?.data;
+
+ if (!payload_type.hasCodeGenBits()) {
+ // We use the error type directly as the type.
+ return self.genTypedValue(.{ .ty = error_type, .val = sub_val });
+ }
+
+ return self.fail("TODO implement error union const of type '{}'", .{typed_value.ty});
+ },
else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty}),
}
}
From 7aaea20e7e5e98bc5b2c4c8ddcf8f6aaa4a9c55d Mon Sep 17 00:00:00 2001
From: Koakuma
Date: Fri, 30 Jul 2021 21:45:28 +0700
Subject: [PATCH 32/96] Add freeAndExit() implementation for Linux/SPARCv9
---
lib/std/Thread.zig | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index 2584b38072..e10e67c250 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -798,6 +798,32 @@ const LinuxThreadImpl = struct {
[len] "r" (self.mapped.len)
: "memory"
),
+ .sparcv9 => asm volatile (
+ \\ # SPARCs really don't like it when active stack frames
+ \\ # is unmapped (it will result in a segfault), so we
+ \\ # force-deactivate it by running `restore` until
+ \\ # all frames are cleared.
+ \\ 1:
+ \\ cmp %%sp, 0
+ \\ beq 2f
+ \\ restore
+ \\ ba 1f
+ \\ 2:
+ \\ mov 73, %%g1
+ \\ mov %[ptr], %%o0
+ \\ mov %[len], %%o1
+ \\ # Flush register window contents to prevent background
+ \\ # memory access before unmapping the stack.
+ \\ flushw
+ \\ t 0x6d
+ \\ mov 1, %%g1
+ \\ mov 1, %%o0
+ \\ t 0x6d
+ :
+ : [ptr] "r" (@ptrToInt(self.mapped.ptr)),
+ [len] "r" (self.mapped.len)
+ : "memory"
+ ),
else => |cpu_arch| @compileError("Unsupported linux arch: " ++ @tagName(cpu_arch)),
}
unreachable;
From 84039a57e4684e8df10e657bb76c6acb3fb89238 Mon Sep 17 00:00:00 2001
From: joachimschmidt557
Date: Fri, 30 Jul 2021 22:48:20 +0200
Subject: [PATCH 33/96] stage2 codegen: Implement genTypedValue for enums
---
src/codegen.zig | 23 +++++++++++++++++++++++
test/stage2/arm.zig | 22 ++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/src/codegen.zig b/src/codegen.zig
index 0917f2c847..bc3ff6257c 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -4740,6 +4740,29 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
}
return self.fail("TODO non pointer optionals", .{});
},
+ .Enum => {
+ if (typed_value.val.castTag(.enum_field_index)) |field_index| {
+ switch (typed_value.ty.tag()) {
+ .enum_simple => {
+ return MCValue{ .immediate = field_index.data };
+ },
+ .enum_full, .enum_nonexhaustive => {
+ const enum_full = typed_value.ty.cast(Type.Payload.EnumFull).?.data;
+ if (enum_full.values.count() != 0) {
+ const tag_val = enum_full.values.keys()[field_index.data];
+ return self.genTypedValue(.{ .ty = enum_full.tag_ty, .val = tag_val });
+ } else {
+ return MCValue{ .immediate = field_index.data };
+ }
+ },
+ else => unreachable,
+ }
+ } else {
+ var int_tag_buffer: Type.Payload.Bits = undefined;
+ const int_tag_ty = typed_value.ty.intTagType(&int_tag_buffer);
+ return self.genTypedValue(.{ .ty = int_tag_ty, .val = typed_value.val });
+ }
+ },
.ErrorSet => {
switch (typed_value.val.tag()) {
.@"error" => {
diff --git a/test/stage2/arm.zig b/test/stage2/arm.zig
index 6b4f569757..103b058a54 100644
--- a/test/stage2/arm.zig
+++ b/test/stage2/arm.zig
@@ -299,6 +299,28 @@ pub fn addCases(ctx: *TestContext) !void {
);
}
+ {
+ var case = ctx.exe("enums", linux_arm);
+ case.addCompareOutput(
+ \\const Number = enum { one, two, three };
+ \\
+ \\pub fn main() void {
+ \\ var x: Number = .one;
+ \\ var y = Number.two;
+ \\ var z = @intToEnum(Number, 2);
+ \\ assert(@enumToInt(x) == 0);
+ \\ assert(@enumToInt(y) == 1);
+ \\ assert(@enumToInt(z) == 2);
+ \\}
+ \\
+ \\fn assert(ok: bool) void {
+ \\ if (!ok) unreachable; // assertion failure
+ \\}
+ ,
+ "",
+ );
+ }
+
{
var case = ctx.exe("recursive fibonacci", linux_arm);
case.addCompareOutput(
From 507dc1f2e7fac212e79f152e557cbec98a3c30e9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 30 Jul 2021 16:05:46 -0700
Subject: [PATCH 34/96] stage2: fix hashing and comparison design flaw with
Value
* `Value.toType` accepts a buffer parameter instead of an allocator
parameter and can no longer fail.
* Module: remove the unused `mod: *Module` parameter from various
functions.
* `Value.compare` now accepts a `Type` parameter which indicates the
type of both operands. There is also a `Value.compareHetero` which
accepts only Value parameters and supports comparing mixed types.
Likewise, `Value.eql` requires a `Type` parameter.
* `Value.hash` is removed; instead the hash map context structs now
have a `ty: Type` field, and the hash function lives there, where it
has access to a Value's Type when it computes a hash.
- This allowed the hash function to be greatly simplified and sound
in the sense that the same Values, even with different
representations, always hash to the same thing.
* Sema: Fix source location of zirCmp when an operand is runtime known
but needs to be comptime known.
* Remove unused target parameter from `Value.floatCast`.
---
src/Air.zig | 3 +-
src/Module.zig | 11 +-
src/RangeSet.zig | 23 ++-
src/Sema.zig | 134 ++++++++------
src/type.zig | 43 +++--
src/value.zig | 459 +++++++++++------------------------------------
6 files changed, 230 insertions(+), 443 deletions(-)
diff --git a/src/Air.zig b/src/Air.zig
index fb95d60d00..d202c079bc 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -503,7 +503,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type {
const ref_int = @enumToInt(ref);
if (ref_int < Air.Inst.Ref.typed_value_map.len) {
- return Air.Inst.Ref.typed_value_map[ref_int].val.toType(undefined) catch unreachable;
+ var buffer: Value.ToTypeBuffer = undefined;
+ return Air.Inst.Ref.typed_value_map[ref_int].val.toType(&buffer);
}
const inst_index = ref_int - Air.Inst.Ref.typed_value_map.len;
const air_tags = air.instructions.items(.tag);
diff --git a/src/Module.zig b/src/Module.zig
index 909e54ffa2..d87f20621c 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -4299,7 +4299,6 @@ pub fn simplePtrType(
}
pub fn ptrType(
- mod: *Module,
arena: *Allocator,
elem_ty: Type,
sentinel: ?Value,
@@ -4311,7 +4310,6 @@ pub fn ptrType(
@"volatile": bool,
size: std.builtin.TypeInfo.Pointer.Size,
) Allocator.Error!Type {
- _ = mod;
assert(host_size == 0 or bit_offset < host_size * 8);
// TODO check if type can be represented by simplePtrType
@@ -4328,8 +4326,7 @@ pub fn ptrType(
});
}
-pub fn optionalType(mod: *Module, arena: *Allocator, child_type: Type) Allocator.Error!Type {
- _ = mod;
+pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type {
switch (child_type.tag()) {
.single_const_pointer => return Type.Tag.optional_single_const_pointer.create(
arena,
@@ -4344,16 +4341,14 @@ pub fn optionalType(mod: *Module, arena: *Allocator, child_type: Type) Allocator
}
pub fn arrayType(
- mod: *Module,
arena: *Allocator,
len: u64,
sentinel: ?Value,
elem_type: Type,
) Allocator.Error!Type {
- _ = mod;
if (elem_type.eql(Type.initTag(.u8))) {
if (sentinel) |some| {
- if (some.eql(Value.initTag(.zero))) {
+ if (some.eql(Value.initTag(.zero), elem_type)) {
return Type.Tag.array_u8_sentinel_0.create(arena, len);
}
} else {
@@ -4376,12 +4371,10 @@ pub fn arrayType(
}
pub fn errorUnionType(
- mod: *Module,
arena: *Allocator,
error_set: Type,
payload: Type,
) Allocator.Error!Type {
- _ = mod;
assert(error_set.zigTypeTag() == .ErrorSet);
if (error_set.eql(Type.initTag(.anyerror)) and payload.eql(Type.initTag(.void))) {
return Type.initTag(.anyerror_void_error_union);
diff --git a/src/RangeSet.zig b/src/RangeSet.zig
index fd258d55b0..2a8a55a077 100644
--- a/src/RangeSet.zig
+++ b/src/RangeSet.zig
@@ -1,5 +1,6 @@
const std = @import("std");
const Order = std.math.Order;
+const Type = @import("type.zig").Type;
const Value = @import("value.zig").Value;
const RangeSet = @This();
const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
@@ -22,9 +23,15 @@ pub fn deinit(self: *RangeSet) void {
self.ranges.deinit();
}
-pub fn add(self: *RangeSet, first: Value, last: Value, src: SwitchProngSrc) !?SwitchProngSrc {
+pub fn add(
+ self: *RangeSet,
+ first: Value,
+ last: Value,
+ ty: Type,
+ src: SwitchProngSrc,
+) !?SwitchProngSrc {
for (self.ranges.items) |range| {
- if (last.compare(.gte, range.first) and first.compare(.lte, range.last)) {
+ if (last.compare(.gte, range.first, ty) and first.compare(.lte, range.last, ty)) {
return range.src; // They overlap.
}
}
@@ -37,18 +44,18 @@ pub fn add(self: *RangeSet, first: Value, last: Value, src: SwitchProngSrc) !?Sw
}
/// Assumes a and b do not overlap
-fn lessThan(_: void, a: Range, b: Range) bool {
- return a.first.compare(.lt, b.first);
+fn lessThan(ty: Type, a: Range, b: Range) bool {
+ return a.first.compare(.lt, b.first, ty);
}
-pub fn spans(self: *RangeSet, first: Value, last: Value) !bool {
+pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {
if (self.ranges.items.len == 0)
return false;
- std.sort.sort(Range, self.ranges.items, {}, lessThan);
+ std.sort.sort(Range, self.ranges.items, ty, lessThan);
- if (!self.ranges.items[0].first.eql(first) or
- !self.ranges.items[self.ranges.items.len - 1].last.eql(last))
+ if (!self.ranges.items[0].first.eql(first, ty) or
+ !self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty))
{
return false;
}
diff --git a/src/Sema.zig b/src/Sema.zig
index 0da38d9a76..97a6f8323e 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -634,7 +634,9 @@ fn analyzeAsType(
const wanted_type = Type.initTag(.@"type");
const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
const val = try sema.resolveConstValue(block, src, coerced_inst);
- return val.toType(sema.arena);
+ var buffer: Value.ToTypeBuffer = undefined;
+ const ty = val.toType(&buffer);
+ return ty.copy(sema.arena);
}
/// May return Value Tags: `variable`, `undef`.
@@ -1022,7 +1024,9 @@ fn zirEnumDecl(
if (bag != 0) break true;
} else false;
if (any_values) {
- try enum_obj.values.ensureCapacity(&new_decl_arena.allocator, fields_len);
+ try enum_obj.values.ensureTotalCapacityContext(&new_decl_arena.allocator, fields_len, .{
+ .ty = tag_ty,
+ });
}
{
@@ -1100,10 +1104,10 @@ fn zirEnumDecl(
// that points to this default value expression rather than the struct.
// But only resolve the source location if we need to emit a compile error.
const tag_val = (try sema.resolveInstConst(block, src, tag_val_ref)).val;
- enum_obj.values.putAssumeCapacityNoClobber(tag_val, {});
+ enum_obj.values.putAssumeCapacityNoClobberContext(tag_val, {}, .{ .ty = tag_ty });
} else if (any_values) {
const tag_val = try Value.Tag.int_u64.create(&new_decl_arena.allocator, field_i);
- enum_obj.values.putAssumeCapacityNoClobber(tag_val, {});
+ enum_obj.values.putAssumeCapacityNoClobberContext(tag_val, {}, .{ .ty = tag_ty });
}
}
@@ -2516,7 +2520,7 @@ fn zirOptionalType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compi
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
const child_type = try sema.resolveType(block, src, inst_data.operand);
- const opt_type = try sema.mod.optionalType(sema.arena, child_type);
+ const opt_type = try Module.optionalType(sema.arena, child_type);
return sema.addType(opt_type);
}
@@ -2547,11 +2551,10 @@ fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE
const tracy = trace(@src());
defer tracy.end();
- // TODO these should be lazily evaluated
const bin_inst = sema.code.instructions.items(.data)[inst].bin;
const len = try sema.resolveInstConst(block, .unneeded, bin_inst.lhs);
const elem_type = try sema.resolveType(block, .unneeded, bin_inst.rhs);
- const array_ty = try sema.mod.arrayType(sema.arena, len.val.toUnsignedInt(), null, elem_type);
+ const array_ty = try Module.arrayType(sema.arena, len.val.toUnsignedInt(), null, elem_type);
return sema.addType(array_ty);
}
@@ -2560,13 +2563,12 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
const tracy = trace(@src());
defer tracy.end();
- // TODO these should be lazily evaluated
const inst_data = sema.code.instructions.items(.data)[inst].array_type_sentinel;
const len = try sema.resolveInstConst(block, .unneeded, inst_data.len);
const extra = sema.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;
const sentinel = try sema.resolveInstConst(block, .unneeded, extra.sentinel);
const elem_type = try sema.resolveType(block, .unneeded, extra.elem_type);
- const array_ty = try sema.mod.arrayType(sema.arena, len.val.toUnsignedInt(), sentinel.val, elem_type);
+ const array_ty = try Module.arrayType(sema.arena, len.val.toUnsignedInt(), sentinel.val, elem_type);
return sema.addType(array_ty);
}
@@ -2599,7 +2601,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Com
error_union.elemType(),
});
}
- const err_union_ty = try sema.mod.errorUnionType(sema.arena, error_union, payload);
+ const err_union_ty = try Module.errorUnionType(sema.arena, error_union, payload);
return sema.addType(err_union_ty);
}
@@ -3890,6 +3892,7 @@ fn analyzeSwitch(
block,
&range_set,
item_ref,
+ operand_ty,
src_node_offset,
.{ .scalar = scalar_i },
);
@@ -3912,6 +3915,7 @@ fn analyzeSwitch(
block,
&range_set,
item_ref,
+ operand_ty,
src_node_offset,
.{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
);
@@ -3929,6 +3933,7 @@ fn analyzeSwitch(
&range_set,
item_first,
item_last,
+ operand_ty,
src_node_offset,
.{ .range = .{ .prong = multi_i, .item = range_i } },
);
@@ -3945,7 +3950,7 @@ fn analyzeSwitch(
const min_int = try operand_ty.minInt(&arena, mod.getTarget());
const max_int = try operand_ty.maxInt(&arena, mod.getTarget());
- if (try range_set.spans(min_int, max_int)) {
+ if (try range_set.spans(min_int, max_int, operand_ty)) {
if (special_prong == .@"else") {
return mod.fail(
&block.base,
@@ -4050,7 +4055,7 @@ fn analyzeSwitch(
);
}
- var seen_values = ValueSrcMap.init(gpa);
+ var seen_values = ValueSrcMap.initContext(gpa, .{ .ty = operand_ty });
defer seen_values.deinit();
var extra_index: usize = special.end;
@@ -4161,7 +4166,7 @@ fn analyzeSwitch(
const item = sema.resolveInst(item_ref);
// Validation above ensured these will succeed.
const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;
- if (operand_val.eql(item_val)) {
+ if (operand_val.eql(item_val, operand_ty)) {
return sema.resolveBlockBody(block, src, &child_block, body, merges);
}
}
@@ -4183,7 +4188,7 @@ fn analyzeSwitch(
const item = sema.resolveInst(item_ref);
// Validation above ensured these will succeed.
const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;
- if (operand_val.eql(item_val)) {
+ if (operand_val.eql(item_val, operand_ty)) {
return sema.resolveBlockBody(block, src, &child_block, body, merges);
}
}
@@ -4198,8 +4203,8 @@ fn analyzeSwitch(
// Validation above ensured these will succeed.
const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first) catch unreachable;
const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last) catch unreachable;
- if (Value.compare(operand_val, .gte, first_tv.val) and
- Value.compare(operand_val, .lte, last_tv.val))
+ if (Value.compare(operand_val, .gte, first_tv.val, operand_ty) and
+ Value.compare(operand_val, .lte, last_tv.val, operand_ty))
{
return sema.resolveBlockBody(block, src, &child_block, body, merges);
}
@@ -4450,12 +4455,13 @@ fn validateSwitchRange(
range_set: *RangeSet,
first_ref: Zir.Inst.Ref,
last_ref: Zir.Inst.Ref,
+ operand_ty: Type,
src_node_offset: i32,
switch_prong_src: Module.SwitchProngSrc,
) CompileError!void {
const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;
const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;
- const maybe_prev_src = try range_set.add(first_val, last_val, switch_prong_src);
+ const maybe_prev_src = try range_set.add(first_val, last_val, operand_ty, switch_prong_src);
return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
}
@@ -4464,11 +4470,12 @@ fn validateSwitchItem(
block: *Scope.Block,
range_set: *RangeSet,
item_ref: Zir.Inst.Ref,
+ operand_ty: Type,
src_node_offset: i32,
switch_prong_src: Module.SwitchProngSrc,
) CompileError!void {
const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
- const maybe_prev_src = try range_set.add(item_val, item_val, switch_prong_src);
+ const maybe_prev_src = try range_set.add(item_val, item_val, operand_ty, switch_prong_src);
return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
}
@@ -5137,20 +5144,26 @@ fn zirCmp(
const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
- if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| {
- if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
- if (lhs_val.isUndef() or rhs_val.isUndef()) {
- return sema.addConstUndef(resolved_type);
- }
- if (lhs_val.compare(op, rhs_val)) {
- return Air.Inst.Ref.bool_true;
+ const runtime_src: LazySrcLoc = src: {
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
+ if (lhs_val.isUndef() or rhs_val.isUndef()) {
+ return sema.addConstUndef(resolved_type);
+ }
+ if (lhs_val.compare(op, rhs_val, resolved_type)) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
} else {
- return Air.Inst.Ref.bool_false;
+ break :src rhs_src;
}
+ } else {
+ break :src lhs_src;
}
- }
+ };
+ try sema.requireRuntimeBlock(block, runtime_src);
- try sema.requireRuntimeBlock(block, src);
const tag: Air.Inst.Tag = switch (op) {
.lt => .cmp_lt,
.lte => .cmp_lte,
@@ -5626,7 +5639,7 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp
const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple;
const elem_type = try sema.resolveType(block, .unneeded, inst_data.elem_type);
- const ty = try sema.mod.ptrType(
+ const ty = try Module.ptrType(
sema.arena,
elem_type,
null,
@@ -5680,7 +5693,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
const elem_type = try sema.resolveType(block, .unneeded, extra.data.elem_type);
- const ty = try sema.mod.ptrType(
+ const ty = try Module.ptrType(
sema.arena,
elem_type,
sentinel,
@@ -6569,7 +6582,7 @@ fn panicWithMsg(
const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
const ptr_stack_trace_ty = try Module.simplePtrType(arena, stack_trace_ty, true, .One);
const null_stack_trace = try sema.addConstant(
- try mod.optionalType(arena, ptr_stack_trace_ty),
+ try Module.optionalType(arena, ptr_stack_trace_ty),
Value.initTag(.null_value),
);
const args = try arena.create([2]Air.Inst.Ref);
@@ -6713,7 +6726,8 @@ fn fieldVal(
},
.Type => {
const val = (try sema.resolveDefinedValue(block, object_src, object)).?;
- const child_type = try val.toType(arena);
+ var to_type_buffer: Value.ToTypeBuffer = undefined;
+ const child_type = val.toType(&to_type_buffer);
switch (child_type.zigTypeTag()) {
.ErrorSet => {
// TODO resolve inferred error sets
@@ -6733,7 +6747,7 @@ fn fieldVal(
} else (try mod.getErrorValue(field_name)).key;
return sema.addConstant(
- child_type,
+ try child_type.copy(arena),
try Value.Tag.@"error".create(arena, .{ .name = name }),
);
},
@@ -6781,7 +6795,7 @@ fn fieldVal(
};
const field_index_u32 = @intCast(u32, field_index);
const enum_val = try Value.Tag.enum_field_index.create(arena, field_index_u32);
- return sema.addConstant(child_type, enum_val);
+ return sema.addConstant(try child_type.copy(arena), enum_val);
},
else => return mod.fail(&block.base, src, "type '{}' has no members", .{child_type}),
}
@@ -6805,7 +6819,6 @@ fn fieldPtr(
// in `fieldVal`. This function takes a pointer and returns a pointer.
const mod = sema.mod;
- const arena = sema.arena;
const object_ptr_src = src; // TODO better source location
const object_ptr_ty = sema.typeOf(object_ptr);
const object_ty = switch (object_ptr_ty.zigTypeTag()) {
@@ -6887,7 +6900,8 @@ fn fieldPtr(
_ = try sema.resolveConstValue(block, object_ptr_src, object_ptr);
const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src);
const val = (sema.resolveDefinedValue(block, src, result) catch unreachable).?;
- const child_type = try val.toType(arena);
+ var to_type_buffer: Value.ToTypeBuffer = undefined;
+ const child_type = val.toType(&to_type_buffer);
switch (child_type.zigTypeTag()) {
.ErrorSet => {
// TODO resolve inferred error sets
@@ -6902,15 +6916,14 @@ fn fieldPtr(
}
}
return mod.fail(&block.base, src, "no error named '{s}' in '{}'", .{
- field_name,
- child_type,
+ field_name, child_type,
});
} else (try mod.getErrorValue(field_name)).key;
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
return sema.analyzeDeclRef(try anon_decl.finish(
- child_type,
+ try child_type.copy(anon_decl.arena()),
try Value.Tag.@"error".create(anon_decl.arena(), .{ .name = name }),
));
},
@@ -6960,7 +6973,7 @@ fn fieldPtr(
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
return sema.analyzeDeclRef(try anon_decl.finish(
- child_type,
+ try child_type.copy(anon_decl.arena()),
try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),
));
},
@@ -7352,7 +7365,7 @@ fn coerce(
if (src_sentinel) |src_s| {
if (dst_sentinel) |dst_s| {
- if (src_s.eql(dst_s)) {
+ if (src_s.eql(dst_s, dst_elem_type)) {
return sema.coerceArrayPtrToMany(block, dest_type, inst, inst_src);
}
}
@@ -7474,7 +7487,7 @@ fn coerceNum(
}
} else if (dst_zig_tag == .ComptimeFloat or dst_zig_tag == .Float) {
if (src_zig_tag == .Float or src_zig_tag == .ComptimeFloat) {
- const res = val.floatCast(sema.arena, dest_type, target) catch |err| switch (err) {
+ const res = val.floatCast(sema.arena, dest_type) catch |err| switch (err) {
error.Overflow => return sema.mod.fail(
&block.base,
inst_src,
@@ -7813,12 +7826,12 @@ fn analyzeSlice(
array_type.sentinel()
else
slice_sentinel;
- return_elem_type = try sema.mod.arrayType(sema.arena, len, array_sentinel, elem_type);
+ return_elem_type = try Module.arrayType(sema.arena, len, array_sentinel, elem_type);
return_ptr_size = .One;
}
}
}
- const return_type = try sema.mod.ptrType(
+ const return_type = try Module.ptrType(
sema.arena,
return_elem_type,
if (end_opt == .none) slice_sentinel else null,
@@ -7858,39 +7871,42 @@ fn cmpNumeric(
if (lhs_ty_tag == .Vector and rhs_ty_tag == .Vector) {
if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) {
return sema.mod.fail(&block.base, src, "vector length mismatch: {d} and {d}", .{
- lhs_ty.arrayLen(),
- rhs_ty.arrayLen(),
+ lhs_ty.arrayLen(), rhs_ty.arrayLen(),
});
}
return sema.mod.fail(&block.base, src, "TODO implement support for vectors in cmpNumeric", .{});
} else if (lhs_ty_tag == .Vector or rhs_ty_tag == .Vector) {
return sema.mod.fail(&block.base, src, "mixed scalar and vector operands to comparison operator: '{}' and '{}'", .{
- lhs_ty,
- rhs_ty,
+ lhs_ty, rhs_ty,
});
}
- if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
- if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
- if (lhs_val.isUndef() or rhs_val.isUndef()) {
- return sema.addConstUndef(Type.initTag(.bool));
- }
- if (Value.compare(lhs_val, op, rhs_val)) {
- return Air.Inst.Ref.bool_true;
+ const runtime_src: LazySrcLoc = src: {
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
+ if (lhs_val.isUndef() or rhs_val.isUndef()) {
+ return sema.addConstUndef(Type.initTag(.bool));
+ }
+ if (Value.compareHetero(lhs_val, op, rhs_val)) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
} else {
- return Air.Inst.Ref.bool_false;
+ break :src rhs_src;
}
+ } else {
+ break :src lhs_src;
}
- }
+ };
// TODO handle comparisons against lazy zero values
// Some values can be compared against zero without being runtime known or without forcing
// a full resolution of their value, for example `@sizeOf(@Frame(function))` is known to
// always be nonzero, and we benefit from not forcing the full evaluation and stack frame layout
// of this function if we don't need to.
+ try sema.requireRuntimeBlock(block, runtime_src);
- // It must be a runtime comparison.
- try sema.requireRuntimeBlock(block, src);
// For floats, emit a float comparison instruction.
const lhs_is_float = switch (lhs_ty_tag) {
.Float, .ComptimeFloat => true,
diff --git a/src/type.zig b/src/type.zig
index d828df550b..82c28ef398 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -426,7 +426,7 @@ pub const Type = extern union {
const sentinel_b = info_b.sentinel;
if (sentinel_a) |sa| {
if (sentinel_b) |sb| {
- if (!sa.eql(sb))
+ if (!sa.eql(sb, info_a.pointee_type))
return false;
} else {
return false;
@@ -455,13 +455,14 @@ pub const Type = extern union {
.Array, .Vector => {
if (a.arrayLen() != b.arrayLen())
return false;
- if (!a.elemType().eql(b.elemType()))
+ const elem_ty = a.elemType();
+ if (!elem_ty.eql(b.elemType()))
return false;
const sentinel_a = a.sentinel();
const sentinel_b = b.sentinel();
if (sentinel_a) |sa| {
if (sentinel_b) |sb| {
- return sa.eql(sb);
+ return sa.eql(sb, elem_ty);
} else {
return false;
}
@@ -2744,29 +2745,37 @@ pub const Type = extern union {
return @as(usize, payload.data);
}
const S = struct {
- fn fieldWithRange(int_val: Value, end: usize) ?usize {
+ fn fieldWithRange(int_ty: Type, int_val: Value, end: usize) ?usize {
if (int_val.compareWithZero(.lt)) return null;
var end_payload: Value.Payload.U64 = .{
.base = .{ .tag = .int_u64 },
.data = end,
};
const end_val = Value.initPayload(&end_payload.base);
- if (int_val.compare(.gte, end_val)) return null;
+ if (int_val.compare(.gte, end_val, int_ty)) return null;
return @intCast(usize, int_val.toUnsignedInt());
}
};
switch (ty.tag()) {
.enum_full, .enum_nonexhaustive => {
const enum_full = ty.cast(Payload.EnumFull).?.data;
+ const tag_ty = enum_full.tag_ty;
if (enum_full.values.count() == 0) {
- return S.fieldWithRange(enum_tag, enum_full.fields.count());
+ return S.fieldWithRange(tag_ty, enum_tag, enum_full.fields.count());
} else {
- return enum_full.values.getIndex(enum_tag);
+ return enum_full.values.getIndexContext(enum_tag, .{ .ty = tag_ty });
}
},
.enum_simple => {
const enum_simple = ty.castTag(.enum_simple).?.data;
- return S.fieldWithRange(enum_tag, enum_simple.fields.count());
+ const fields_len = enum_simple.fields.count();
+ const bits = std.math.log2_int_ceil(usize, fields_len);
+ var buffer: Payload.Bits = .{
+ .base = .{ .tag = .int_unsigned },
+ .data = bits,
+ };
+ const tag_ty = Type.initPayload(&buffer.base);
+ return S.fieldWithRange(tag_ty, enum_tag, fields_len);
},
.atomic_ordering,
.atomic_rmw_op,
@@ -2875,14 +2884,14 @@ pub const Type = extern union {
/// Asserts the type is an enum.
pub fn enumHasInt(ty: Type, int: Value, target: Target) bool {
const S = struct {
- fn intInRange(int_val: Value, end: usize) bool {
+ fn intInRange(tag_ty: Type, int_val: Value, end: usize) bool {
if (int_val.compareWithZero(.lt)) return false;
var end_payload: Value.Payload.U64 = .{
.base = .{ .tag = .int_u64 },
.data = end,
};
const end_val = Value.initPayload(&end_payload.base);
- if (int_val.compare(.gte, end_val)) return false;
+ if (int_val.compare(.gte, end_val, tag_ty)) return false;
return true;
}
};
@@ -2890,15 +2899,23 @@ pub const Type = extern union {
.enum_nonexhaustive => return int.intFitsInType(ty, target),
.enum_full => {
const enum_full = ty.castTag(.enum_full).?.data;
+ const tag_ty = enum_full.tag_ty;
if (enum_full.values.count() == 0) {
- return S.intInRange(int, enum_full.fields.count());
+ return S.intInRange(tag_ty, int, enum_full.fields.count());
} else {
- return enum_full.values.contains(int);
+ return enum_full.values.containsContext(int, .{ .ty = tag_ty });
}
},
.enum_simple => {
const enum_simple = ty.castTag(.enum_simple).?.data;
- return S.intInRange(int, enum_simple.fields.count());
+ const fields_len = enum_simple.fields.count();
+ const bits = std.math.log2_int_ceil(usize, fields_len);
+ var buffer: Payload.Bits = .{
+ .base = .{ .tag = .int_unsigned },
+ .data = bits,
+ };
+ const tag_ty = Type.initPayload(&buffer.base);
+ return S.intInRange(tag_ty, int, fields_len);
},
.atomic_ordering,
.atomic_rmw_op,
diff --git a/src/value.zig b/src/value.zig
index 32be34ee2c..93d6625e7c 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -653,8 +653,10 @@ pub const Value = extern union {
unreachable;
}
+ pub const ToTypeBuffer = Type.Payload.Bits;
+
/// Asserts that the value is representable as a type.
- pub fn toType(self: Value, allocator: *Allocator) !Type {
+ pub fn toType(self: Value, buffer: *ToTypeBuffer) Type {
return switch (self.tag()) {
.ty => self.castTag(.ty).?.data,
.u1_type => Type.initTag(.u1),
@@ -714,14 +716,13 @@ pub const Value = extern union {
.int_type => {
const payload = self.castTag(.int_type).?.data;
- const new = try allocator.create(Type.Payload.Bits);
- new.* = .{
+ buffer.* = .{
.base = .{
.tag = if (payload.signed) .int_signed else .int_unsigned,
},
.data = payload.bits,
};
- return Type.initPayload(&new.base);
+ return Type.initPayload(&buffer.base);
},
.undef,
@@ -958,9 +959,8 @@ pub const Value = extern union {
/// Converts an integer or a float to a float.
/// Returns `error.Overflow` if the value does not fit in the new type.
- pub fn floatCast(self: Value, allocator: *Allocator, ty: Type, target: Target) !Value {
- _ = target;
- switch (ty.tag()) {
+ pub fn floatCast(self: Value, allocator: *Allocator, dest_ty: Type) !Value {
+ switch (dest_ty.tag()) {
.f16 => {
@panic("TODO add __trunctfhf2 to compiler-rt");
//const res = try Value.Tag.float_16.create(allocator, self.toFloat(f16));
@@ -970,13 +970,13 @@ pub const Value = extern union {
},
.f32 => {
const res = try Value.Tag.float_32.create(allocator, self.toFloat(f32));
- if (!self.eql(res))
+ if (!self.eql(res, dest_ty))
return error.Overflow;
return res;
},
.f64 => {
const res = try Value.Tag.float_64.create(allocator, self.toFloat(f64));
- if (!self.eql(res))
+ if (!self.eql(res, dest_ty))
return error.Overflow;
return res;
},
@@ -1083,12 +1083,18 @@ pub const Value = extern union {
return lhs_bigint.order(rhs_bigint);
}
- /// Asserts the value is comparable.
- pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value) bool {
+ /// Asserts the value is comparable. Does not take a type parameter because it supports
+ /// comparisons between heterogeneous types.
+ pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value) bool {
+ return order(lhs, rhs).compare(op);
+ }
+
+ /// Asserts the value is comparable. Both operands have type `ty`.
+ pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type) bool {
return switch (op) {
- .eq => lhs.eql(rhs),
- .neq => !lhs.eql(rhs),
- else => order(lhs, rhs).compare(op),
+ .eq => lhs.eql(rhs, ty),
+ .neq => !lhs.eql(rhs, ty),
+ else => compareHetero(lhs, op, rhs),
};
}
@@ -1097,11 +1103,11 @@ pub const Value = extern union {
return orderAgainstZero(lhs).compare(op);
}
- /// TODO we can't compare value equality without also knowing the type to treat
- /// the values as
- pub fn eql(a: Value, b: Value) bool {
+ pub fn eql(a: Value, b: Value, ty: Type) bool {
const a_tag = a.tag();
const b_tag = b.tag();
+ assert(a_tag != .undef);
+ assert(b_tag != .undef);
if (a_tag == b_tag) {
switch (a_tag) {
.void_value, .null_value => return true,
@@ -1118,230 +1124,106 @@ pub const Value = extern union {
else => {},
}
}
- if (a.isType() and b.isType()) {
- // 128 bytes should be enough to hold both types
- var buf: [128]u8 = undefined;
- var fib = std.heap.FixedBufferAllocator.init(&buf);
- const a_type = a.toType(&fib.allocator) catch unreachable;
- const b_type = b.toType(&fib.allocator) catch unreachable;
+ if (ty.zigTypeTag() == .Type) {
+ var buf_a: ToTypeBuffer = undefined;
+ var buf_b: ToTypeBuffer = undefined;
+ const a_type = a.toType(&buf_a);
+ const b_type = b.toType(&buf_b);
return a_type.eql(b_type);
}
return order(a, b).compare(.eq);
}
- pub fn hash_u32(self: Value) u32 {
- return @truncate(u32, self.hash());
- }
+ pub const ArrayHashContext = struct {
+ ty: Type,
- /// TODO we can't hash without also knowing the type of the value.
- /// we have to hash as if there were a canonical value memory layout.
- pub fn hash(self: Value) u64 {
- var hasher = std.hash.Wyhash.init(0);
+ pub fn hash(self: @This(), v: Value) u32 {
+ const other_context: HashContext = .{ .ty = self.ty };
+ return @truncate(u32, other_context.hash(v));
+ }
+ pub fn eql(self: @This(), a: Value, b: Value) bool {
+ return a.eql(b, self.ty);
+ }
+ };
- switch (self.tag()) {
- .u1_type,
- .u8_type,
- .i8_type,
- .u16_type,
- .i16_type,
- .u32_type,
- .i32_type,
- .u64_type,
- .i64_type,
- .u128_type,
- .i128_type,
- .usize_type,
- .isize_type,
- .c_short_type,
- .c_ushort_type,
- .c_int_type,
- .c_uint_type,
- .c_long_type,
- .c_ulong_type,
- .c_longlong_type,
- .c_ulonglong_type,
- .c_longdouble_type,
- .f16_type,
- .f32_type,
- .f64_type,
- .f128_type,
- .c_void_type,
- .bool_type,
- .void_type,
- .type_type,
- .anyerror_type,
- .comptime_int_type,
- .comptime_float_type,
- .noreturn_type,
- .null_type,
- .undefined_type,
- .fn_noreturn_no_args_type,
- .fn_void_no_args_type,
- .fn_naked_noreturn_no_args_type,
- .fn_ccc_void_no_args_type,
- .single_const_pointer_to_comptime_int_type,
- .anyframe_type,
- .const_slice_u8_type,
- .enum_literal_type,
- .ty,
- .abi_align_default,
- => {
- // Directly return Type.hash, toType can only fail for .int_type.
- var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{});
- return (self.toType(&allocator.allocator) catch unreachable).hash();
- },
- .int_type => {
- const payload = self.castTag(.int_type).?.data;
- var int_payload = Type.Payload.Bits{
- .base = .{
- .tag = if (payload.signed) .int_signed else .int_unsigned,
- },
- .data = payload.bits,
- };
- return Type.initPayload(&int_payload.base).hash();
- },
+ pub const HashContext = struct {
+ ty: Type,
- .empty_struct_value,
- .empty_array,
- => {},
+ pub fn hash(self: @This(), v: Value) u64 {
+ var hasher = std.hash.Wyhash.init(0);
- .undef,
- .null_value,
- .void_value,
- .unreachable_value,
- => std.hash.autoHash(&hasher, self.tag()),
+ switch (self.ty.zigTypeTag()) {
+ .BoundFn => unreachable, // TODO remove this from the language
- .zero, .bool_false => std.hash.autoHash(&hasher, @as(u64, 0)),
- .one, .bool_true => std.hash.autoHash(&hasher, @as(u64, 1)),
+ .Void,
+ .NoReturn,
+ .Undefined,
+ .Null,
+ => {},
- .float_16, .float_32, .float_64, .float_128 => {
- @panic("TODO implement Value.hash for floats");
- },
-
- .enum_literal => {
- const payload = self.castTag(.enum_literal).?;
- hasher.update(payload.data);
- },
- .enum_field_index => {
- const payload = self.castTag(.enum_field_index).?;
- std.hash.autoHash(&hasher, payload.data);
- },
- .bytes => {
- const payload = self.castTag(.bytes).?;
- hasher.update(payload.data);
- },
- .repeated => {
- @panic("TODO Value.hash for repeated");
- },
- .array => {
- @panic("TODO Value.hash for array");
- },
- .slice => {
- @panic("TODO Value.hash for slice");
- },
- .eu_payload_ptr => {
- @panic("TODO Value.hash for eu_payload_ptr");
- },
- .int_u64 => {
- const payload = self.castTag(.int_u64).?;
- std.hash.autoHash(&hasher, payload.data);
- },
- .int_i64 => {
- const payload = self.castTag(.int_i64).?;
- std.hash.autoHash(&hasher, payload.data);
- },
- .comptime_alloc => {
- const payload = self.castTag(.comptime_alloc).?;
- std.hash.autoHash(&hasher, payload.data.val.hash());
- },
- .int_big_positive, .int_big_negative => {
- var space: BigIntSpace = undefined;
- const big = self.toBigInt(&space);
- if (big.limbs.len == 1) {
- // handle like {u,i}64 to ensure same hash as with Int{i,u}64
- if (big.positive) {
- std.hash.autoHash(&hasher, @as(u64, big.limbs[0]));
- } else {
- std.hash.autoHash(&hasher, @as(u64, @bitCast(usize, -@bitCast(isize, big.limbs[0]))));
- }
- } else {
+ .Type => {
+ var buf: ToTypeBuffer = undefined;
+ return v.toType(&buf).hash();
+ },
+ .Bool => {
+ std.hash.autoHash(&hasher, v.toBool());
+ },
+ .Int, .ComptimeInt => {
+ var space: BigIntSpace = undefined;
+ const big = v.toBigInt(&space);
std.hash.autoHash(&hasher, big.positive);
for (big.limbs) |limb| {
std.hash.autoHash(&hasher, limb);
}
- }
- },
- .elem_ptr => {
- const payload = self.castTag(.elem_ptr).?.data;
- std.hash.autoHash(&hasher, payload.array_ptr.hash());
- std.hash.autoHash(&hasher, payload.index);
- },
- .field_ptr => {
- const payload = self.castTag(.field_ptr).?.data;
- std.hash.autoHash(&hasher, payload.container_ptr.hash());
- std.hash.autoHash(&hasher, payload.field_index);
- },
- .decl_ref => {
- const decl = self.castTag(.decl_ref).?.data;
- std.hash.autoHash(&hasher, decl);
- },
- .function => {
- const func = self.castTag(.function).?.data;
- std.hash.autoHash(&hasher, func);
- },
- .extern_fn => {
- const decl = self.castTag(.extern_fn).?.data;
- std.hash.autoHash(&hasher, decl);
- },
- .variable => {
- const variable = self.castTag(.variable).?.data;
- std.hash.autoHash(&hasher, variable);
- },
- .@"error" => {
- const payload = self.castTag(.@"error").?.data;
- hasher.update(payload.name);
- },
- .error_union => {
- const payload = self.castTag(.error_union).?.data;
- std.hash.autoHash(&hasher, payload.hash());
- },
- .inferred_alloc => unreachable,
+ },
+ .Float, .ComptimeFloat => {
+ @panic("TODO implement hashing float values");
+ },
+ .Pointer => {
+ @panic("TODO implement hashing pointer values");
+ },
+ .Array, .Vector => {
+ @panic("TODO implement hashing array/vector values");
+ },
+ .Struct => {
+ @panic("TODO implement hashing struct values");
+ },
+ .Optional => {
+ @panic("TODO implement hashing optional values");
+ },
+ .ErrorUnion => {
+ @panic("TODO implement hashing error union values");
+ },
+ .ErrorSet => {
+ @panic("TODO implement hashing error set values");
+ },
+ .Enum => {
+ @panic("TODO implement hashing enum values");
+ },
+ .Union => {
+ @panic("TODO implement hashing union values");
+ },
+ .Fn => {
+ @panic("TODO implement hashing function values");
+ },
+ .Opaque => {
+ @panic("TODO implement hashing opaque values");
+ },
+ .Frame => {
+ @panic("TODO implement hashing frame values");
+ },
+ .AnyFrame => {
+ @panic("TODO implement hashing anyframe values");
+ },
+ .EnumLiteral => {
+ @panic("TODO implement hashing enum literal values");
+ },
+ }
+ return hasher.final();
+ }
- .manyptr_u8_type,
- .manyptr_const_u8_type,
- .atomic_ordering_type,
- .atomic_rmw_op_type,
- .calling_convention_type,
- .float_mode_type,
- .reduce_op_type,
- .call_options_type,
- .export_options_type,
- .extern_options_type,
- .@"struct",
- .@"union",
- => @panic("TODO this hash function looks pretty broken. audit it"),
- }
- return hasher.final();
- }
-
- pub const ArrayHashContext = struct {
- pub fn hash(self: @This(), v: Value) u32 {
- _ = self;
- return v.hash_u32();
- }
pub fn eql(self: @This(), a: Value, b: Value) bool {
- _ = self;
- return a.eql(b);
- }
- };
- pub const HashContext = struct {
- pub fn hash(self: @This(), v: Value) u64 {
- _ = self;
- return v.hash();
- }
- pub fn eql(self: @This(), a: Value, b: Value) bool {
- _ = self;
- return a.eql(b);
+ return a.eql(b, self.ty);
}
};
@@ -1508,111 +1390,6 @@ pub const Value = extern union {
};
}
- /// Valid for all types. Asserts the value is not undefined.
- /// TODO this function is a code smell and should be deleted
- fn isType(self: Value) bool {
- return switch (self.tag()) {
- .ty,
- .int_type,
- .u1_type,
- .u8_type,
- .i8_type,
- .u16_type,
- .i16_type,
- .u32_type,
- .i32_type,
- .u64_type,
- .i64_type,
- .u128_type,
- .i128_type,
- .usize_type,
- .isize_type,
- .c_short_type,
- .c_ushort_type,
- .c_int_type,
- .c_uint_type,
- .c_long_type,
- .c_ulong_type,
- .c_longlong_type,
- .c_ulonglong_type,
- .c_longdouble_type,
- .f16_type,
- .f32_type,
- .f64_type,
- .f128_type,
- .c_void_type,
- .bool_type,
- .void_type,
- .type_type,
- .anyerror_type,
- .comptime_int_type,
- .comptime_float_type,
- .noreturn_type,
- .null_type,
- .undefined_type,
- .fn_noreturn_no_args_type,
- .fn_void_no_args_type,
- .fn_naked_noreturn_no_args_type,
- .fn_ccc_void_no_args_type,
- .single_const_pointer_to_comptime_int_type,
- .anyframe_type,
- .const_slice_u8_type,
- .enum_literal_type,
- .manyptr_u8_type,
- .manyptr_const_u8_type,
- .atomic_ordering_type,
- .atomic_rmw_op_type,
- .calling_convention_type,
- .float_mode_type,
- .reduce_op_type,
- .call_options_type,
- .export_options_type,
- .extern_options_type,
- => true,
-
- .zero,
- .one,
- .empty_array,
- .bool_true,
- .bool_false,
- .function,
- .extern_fn,
- .variable,
- .int_u64,
- .int_i64,
- .int_big_positive,
- .int_big_negative,
- .comptime_alloc,
- .decl_ref,
- .elem_ptr,
- .field_ptr,
- .bytes,
- .repeated,
- .array,
- .slice,
- .float_16,
- .float_32,
- .float_64,
- .float_128,
- .void_value,
- .enum_literal,
- .enum_field_index,
- .@"error",
- .error_union,
- .empty_struct_value,
- .@"struct",
- .@"union",
- .null_value,
- .abi_align_default,
- .eu_payload_ptr,
- => false,
-
- .undef => unreachable,
- .unreachable_value => unreachable,
- .inferred_alloc => unreachable,
- };
- }
-
/// This type is not copyable since it may contain pointers to its inner data.
pub const Payload = struct {
tag: Tag,
@@ -1806,27 +1583,3 @@ pub const Value = extern union {
limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb,
};
};
-
-test "hash same value different representation" {
- const zero_1 = Value.initTag(.zero);
- var payload_1 = Value.Payload.U64{
- .base = .{ .tag = .int_u64 },
- .data = 0,
- };
- const zero_2 = Value.initPayload(&payload_1.base);
- try std.testing.expectEqual(zero_1.hash(), zero_2.hash());
-
- var payload_2 = Value.Payload.I64{
- .base = .{ .tag = .int_i64 },
- .data = 0,
- };
- const zero_3 = Value.initPayload(&payload_2.base);
- try std.testing.expectEqual(zero_2.hash(), zero_3.hash());
-
- var payload_3 = Value.Payload.BigInt{
- .base = .{ .tag = .int_big_negative },
- .data = &[_]std.math.big.Limb{0},
- };
- const zero_4 = Value.initPayload(&payload_3.base);
- try std.testing.expectEqual(zero_3.hash(), zero_4.hash());
-}
From 6e78c007dff96de98c44c52da890cdae3d6e1389 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 30 Jul 2021 17:40:30 -0700
Subject: [PATCH 35/96] Sema: improved AIR when one operand of bool cmp is
known
When doing `x == true` or `x == false` it is now lowered as either a
no-op or a not, respectively, rather than a cmp instruction.
This commit also extracts a zirCmpEq function out from zirCmp, reducing
the amount of branching (on is_equality_cmp) in both functions.
---
src/Sema.zig | 226 +++++++++++++++++++++++++++++++++------------------
1 file changed, 147 insertions(+), 79 deletions(-)
diff --git a/src/Sema.zig b/src/Sema.zig
index 97a6f8323e..4fa59c4744 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -193,12 +193,12 @@ pub fn analyzeBody(
.call_compile_time => try sema.zirCall(block, inst, .compile_time, false),
.call_nosuspend => try sema.zirCall(block, inst, .no_async, false),
.call_async => try sema.zirCall(block, inst, .async_kw, false),
- .cmp_eq => try sema.zirCmp(block, inst, .eq),
- .cmp_gt => try sema.zirCmp(block, inst, .gt),
- .cmp_gte => try sema.zirCmp(block, inst, .gte),
.cmp_lt => try sema.zirCmp(block, inst, .lt),
.cmp_lte => try sema.zirCmp(block, inst, .lte),
- .cmp_neq => try sema.zirCmp(block, inst, .neq),
+ .cmp_eq => try sema.zirCmpEq(block, inst, .eq, .cmp_eq),
+ .cmp_gte => try sema.zirCmp(block, inst, .gte),
+ .cmp_gt => try sema.zirCmp(block, inst, .gt),
+ .cmp_neq => try sema.zirCmpEq(block, inst, .neq, .cmp_neq),
.coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
.decl_ref => try sema.zirDeclRef(block, inst),
.decl_val => try sema.zirDeclVal(block, inst),
@@ -5040,6 +5040,97 @@ fn zirAsm(
return asm_air;
}
+/// Only called for equality operators. See also `zirCmp`.
+fn zirCmpEq(
+ sema: *Sema,
+ block: *Scope.Block,
+ inst: Zir.Inst.Index,
+ op: std.math.CompareOperator,
+ air_tag: Air.Inst.Tag,
+) CompileError!Air.Inst.Ref {
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ const mod = sema.mod;
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+ const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
+ const src: LazySrcLoc = inst_data.src();
+ const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
+ const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
+ const lhs = sema.resolveInst(extra.lhs);
+ const rhs = sema.resolveInst(extra.rhs);
+
+ const lhs_ty = sema.typeOf(lhs);
+ const rhs_ty = sema.typeOf(rhs);
+ const lhs_ty_tag = lhs_ty.zigTypeTag();
+ const rhs_ty_tag = rhs_ty.zigTypeTag();
+ if (lhs_ty_tag == .Null and rhs_ty_tag == .Null) {
+ // null == null, null != null
+ if (op == .eq) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
+ }
+ if (((lhs_ty_tag == .Null and rhs_ty_tag == .Optional) or
+ rhs_ty_tag == .Null and lhs_ty_tag == .Optional))
+ {
+ // comparing null with optionals
+ const opt_operand = if (lhs_ty_tag == .Optional) lhs else rhs;
+ return sema.analyzeIsNull(block, src, opt_operand, op == .neq);
+ }
+ if (((lhs_ty_tag == .Null and rhs_ty.isCPtr()) or (rhs_ty_tag == .Null and lhs_ty.isCPtr()))) {
+ return mod.fail(&block.base, src, "TODO implement C pointer cmp", .{});
+ }
+ if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) {
+ const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty;
+ return mod.fail(&block.base, src, "comparison of '{}' with null", .{non_null_type});
+ }
+ if (((lhs_ty_tag == .EnumLiteral and rhs_ty_tag == .Union) or
+ (rhs_ty_tag == .EnumLiteral and lhs_ty_tag == .Union)))
+ {
+ return mod.fail(&block.base, src, "TODO implement equality comparison between a union's tag value and an enum literal", .{});
+ }
+ if (lhs_ty_tag == .ErrorSet and rhs_ty_tag == .ErrorSet) {
+ const runtime_src: LazySrcLoc = src: {
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lval| {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rval| {
+ if (lval.isUndef() or rval.isUndef()) {
+ return sema.addConstUndef(Type.initTag(.bool));
+ }
+ // TODO optimisation opportunity: evaluate if mem.eql is faster with the names,
+ // or calling to Module.getErrorValue to get the values and then compare them is
+ // faster.
+ const lhs_name = lval.castTag(.@"error").?.data.name;
+ const rhs_name = rval.castTag(.@"error").?.data.name;
+ if (mem.eql(u8, lhs_name, rhs_name) == (op == .eq)) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
+ } else {
+ break :src rhs_src;
+ }
+ } else {
+ break :src lhs_src;
+ }
+ };
+ try sema.requireRuntimeBlock(block, runtime_src);
+ return block.addBinOp(air_tag, lhs, rhs);
+ }
+ if (lhs_ty_tag == .Type and rhs_ty_tag == .Type) {
+ const lhs_as_type = try sema.analyzeAsType(block, lhs_src, lhs);
+ const rhs_as_type = try sema.analyzeAsType(block, rhs_src, rhs);
+ if (lhs_as_type.eql(rhs_as_type) == (op == .eq)) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
+ }
+ return sema.analyzeCmp(block, src, lhs, rhs, op, lhs_src, rhs_src, true);
+}
+
+/// Only called for non-equality operators. See also `zirCmpEq`.
fn zirCmp(
sema: *Sema,
block: *Scope.Block,
@@ -5049,8 +5140,6 @@ fn zirCmp(
const tracy = trace(@src());
defer tracy.end();
- const mod = sema.mod;
-
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
const src: LazySrcLoc = inst_data.src();
@@ -5058,87 +5147,34 @@ fn zirCmp(
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
const lhs = sema.resolveInst(extra.lhs);
const rhs = sema.resolveInst(extra.rhs);
+ return sema.analyzeCmp(block, src, lhs, rhs, op, lhs_src, rhs_src, false);
+}
- const is_equality_cmp = switch (op) {
- .eq, .neq => true,
- else => false,
- };
+fn analyzeCmp(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ lhs: Air.Inst.Ref,
+ rhs: Air.Inst.Ref,
+ op: std.math.CompareOperator,
+ lhs_src: LazySrcLoc,
+ rhs_src: LazySrcLoc,
+ is_equality_cmp: bool,
+) CompileError!Air.Inst.Ref {
const lhs_ty = sema.typeOf(lhs);
const rhs_ty = sema.typeOf(rhs);
- const lhs_ty_tag = lhs_ty.zigTypeTag();
- const rhs_ty_tag = rhs_ty.zigTypeTag();
- if (is_equality_cmp and lhs_ty_tag == .Null and rhs_ty_tag == .Null) {
- // null == null, null != null
- if (op == .eq) {
- return Air.Inst.Ref.bool_true;
- } else {
- return Air.Inst.Ref.bool_false;
- }
- } else if (is_equality_cmp and
- ((lhs_ty_tag == .Null and rhs_ty_tag == .Optional) or
- rhs_ty_tag == .Null and lhs_ty_tag == .Optional))
- {
- // comparing null with optionals
- const opt_operand = if (lhs_ty_tag == .Optional) lhs else rhs;
- return sema.analyzeIsNull(block, src, opt_operand, op == .neq);
- } else if (is_equality_cmp and
- ((lhs_ty_tag == .Null and rhs_ty.isCPtr()) or (rhs_ty_tag == .Null and lhs_ty.isCPtr())))
- {
- return mod.fail(&block.base, src, "TODO implement C pointer cmp", .{});
- } else if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) {
- const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty;
- return mod.fail(&block.base, src, "comparison of '{}' with null", .{non_null_type});
- } else if (is_equality_cmp and
- ((lhs_ty_tag == .EnumLiteral and rhs_ty_tag == .Union) or
- (rhs_ty_tag == .EnumLiteral and lhs_ty_tag == .Union)))
- {
- return mod.fail(&block.base, src, "TODO implement equality comparison between a union's tag value and an enum literal", .{});
- } else if (lhs_ty_tag == .ErrorSet and rhs_ty_tag == .ErrorSet) {
- if (!is_equality_cmp) {
- return mod.fail(&block.base, src, "{s} operator not allowed for errors", .{@tagName(op)});
- }
- if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lval| {
- if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rval| {
- if (lval.isUndef() or rval.isUndef()) {
- return sema.addConstUndef(Type.initTag(.bool));
- }
- // TODO optimisation opportunity: evaluate if mem.eql is faster with the names,
- // or calling to Module.getErrorValue to get the values and then compare them is
- // faster.
- const lhs_name = lval.castTag(.@"error").?.data.name;
- const rhs_name = rval.castTag(.@"error").?.data.name;
- if (mem.eql(u8, lhs_name, rhs_name) == (op == .eq)) {
- return Air.Inst.Ref.bool_true;
- } else {
- return Air.Inst.Ref.bool_false;
- }
- }
- }
- try sema.requireRuntimeBlock(block, src);
- const tag: Air.Inst.Tag = if (op == .eq) .cmp_eq else .cmp_neq;
- return block.addBinOp(tag, lhs, rhs);
- } else if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) {
+ if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) {
// This operation allows any combination of integer and float types, regardless of the
// signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for
// numeric types.
return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
- } else if (lhs_ty_tag == .Type and rhs_ty_tag == .Type) {
- if (!is_equality_cmp) {
- return mod.fail(&block.base, src, "{s} operator not allowed for types", .{@tagName(op)});
- }
- const lhs_as_type = try sema.analyzeAsType(block, lhs_src, lhs);
- const rhs_as_type = try sema.analyzeAsType(block, rhs_src, rhs);
- if (lhs_as_type.eql(rhs_as_type) == (op == .eq)) {
- return Air.Inst.Ref.bool_true;
- } else {
- return Air.Inst.Ref.bool_false;
- }
}
-
const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
const resolved_type = try sema.resolvePeerTypes(block, src, instructions);
if (!resolved_type.isSelfComparable(is_equality_cmp)) {
- return mod.fail(&block.base, src, "operator not allowed for type '{}'", .{resolved_type});
+ return sema.mod.fail(&block.base, src, "{s} operator not allowed for type '{}'", .{
+ @tagName(op), resolved_type,
+ });
}
const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
@@ -5146,19 +5182,31 @@ fn zirCmp(
const runtime_src: LazySrcLoc = src: {
if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| {
+ if (lhs_val.isUndef()) return sema.addConstUndef(resolved_type);
if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
- if (lhs_val.isUndef() or rhs_val.isUndef()) {
- return sema.addConstUndef(resolved_type);
- }
+ if (rhs_val.isUndef()) return sema.addConstUndef(resolved_type);
+
if (lhs_val.compare(op, rhs_val, resolved_type)) {
return Air.Inst.Ref.bool_true;
} else {
return Air.Inst.Ref.bool_false;
}
} else {
+ if (resolved_type.zigTypeTag() == .Bool) {
+ // We can lower bool eq/neq more efficiently.
+ return sema.runtimeBoolCmp(block, op, casted_rhs, lhs_val.toBool(), rhs_src);
+ }
break :src rhs_src;
}
} else {
+ // For bools, we still check the other operand, because we can lower
+ // bool eq/neq more efficiently.
+ if (resolved_type.zigTypeTag() == .Bool) {
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
+ if (rhs_val.isUndef()) return sema.addConstUndef(resolved_type);
+ return sema.runtimeBoolCmp(block, op, casted_lhs, rhs_val.toBool(), lhs_src);
+ }
+ }
break :src lhs_src;
}
};
@@ -5176,6 +5224,26 @@ fn zirCmp(
return block.addBinOp(tag, casted_lhs, casted_rhs);
}
+/// cmp_eq (x, false) => not(x)
+/// cmp_eq (x, true ) => x
+/// cmp_neq(x, false) => x
+/// cmp_neq(x, true ) => not(x)
+fn runtimeBoolCmp(
+ sema: *Sema,
+ block: *Scope.Block,
+ op: std.math.CompareOperator,
+ lhs: Air.Inst.Ref,
+ rhs: bool,
+ runtime_src: LazySrcLoc,
+) CompileError!Air.Inst.Ref {
+ if ((op == .neq) == rhs) {
+ try sema.requireRuntimeBlock(block, runtime_src);
+ return block.addTyOp(.not, Type.initTag(.bool), lhs);
+ } else {
+ return lhs;
+ }
+}
+
fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
From 1f95c50d9a0c4c057780d387d57ac2ac40df1720 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 30 Jul 2021 17:48:24 -0700
Subject: [PATCH 36/96] codegen: cmp lowering treats bools the same as unsigned
int
fixes a crash when lowering `a == b` and they are of type bool.
I'm not worried about floats; I think we will probably add separate AIR
instructions for floats.
---
src/codegen.zig | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/src/codegen.zig b/src/codegen.zig
index bc3ff6257c..77672e82b0 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -2889,10 +2889,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const src_mcv = try self.limitImmediateType(bin_op.rhs, i32);
try self.genX8664BinMathCode(Type.initTag(.bool), dst_mcv, src_mcv, 7, 0x38);
- const info = ty.intInfo(self.target.*);
- break :result switch (info.signedness) {
- .signed => MCValue{ .compare_flags_signed = op },
- .unsigned => MCValue{ .compare_flags_unsigned = op },
+ break :result switch (ty.isSignedInt()) {
+ true => MCValue{ .compare_flags_signed = op },
+ false => MCValue{ .compare_flags_unsigned = op },
};
},
.arm, .armeb => result: {
@@ -2934,10 +2933,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
// The destination register is not present in the cmp instruction
try self.genArmBinOpCode(undefined, lhs_mcv, rhs_mcv, false, .cmp_eq);
- const info = ty.intInfo(self.target.*);
- break :result switch (info.signedness) {
- .signed => MCValue{ .compare_flags_signed = op },
- .unsigned => MCValue{ .compare_flags_unsigned = op },
+ break :result switch (ty.isSignedInt()) {
+ true => MCValue{ .compare_flags_signed = op },
+ false => MCValue{ .compare_flags_unsigned = op },
};
},
else => return self.fail("TODO implement cmp for {}", .{self.target.cpu.arch}),
From c30cc4dbbfe3e1494160ffac18ce6a9f9a5e5224 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 10:26:21 +0200
Subject: [PATCH 37/96] macho: don't store allocator in Object
instead, pass it in functions that require it. Also, when parsing
relocs, make Object part of the context struct where we pass in
additional goodies such as `*MachO` or `*Allocator`.
---
src/link/MachO.zig | 22 +--
src/link/MachO/Archive.zig | 4 +-
src/link/MachO/Object.zig | 278 +++++++++++++++++------------------
src/link/MachO/TextBlock.zig | 133 ++++++++---------
4 files changed, 215 insertions(+), 222 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 1f2e0616ba..78c926f5f1 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -2004,21 +2004,21 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
if (symbolIsStab(sym)) {
log.err("unhandled symbol type: stab", .{});
log.err(" symbol '{s}'", .{sym_name});
- log.err(" first definition in '{s}'", .{object.name.?});
+ log.err(" first definition in '{s}'", .{object.name});
return error.UnhandledSymbolType;
}
if (symbolIsIndr(sym)) {
log.err("unhandled symbol type: indirect", .{});
log.err(" symbol '{s}'", .{sym_name});
- log.err(" first definition in '{s}'", .{object.name.?});
+ log.err(" first definition in '{s}'", .{object.name});
return error.UnhandledSymbolType;
}
if (symbolIsAbs(sym)) {
log.err("unhandled symbol type: absolute", .{});
log.err(" symbol '{s}'", .{sym_name});
- log.err(" first definition in '{s}'", .{object.name.?});
+ log.err(" first definition in '{s}'", .{object.name});
return error.UnhandledSymbolType;
}
@@ -2068,8 +2068,8 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
!(symbolIsWeakDef(global.*) or symbolIsPext(global.*)))
{
log.err("symbol '{s}' defined multiple times", .{sym_name});
- log.err(" first definition in '{s}'", .{self.objects.items[resolv.file].name.?});
- log.err(" next definition in '{s}'", .{object.name.?});
+ log.err(" first definition in '{s}'", .{self.objects.items[resolv.file].name});
+ log.err(" next definition in '{s}'", .{object.name});
return error.MultipleSymbolDefinitions;
}
@@ -2448,7 +2448,7 @@ fn resolveSymbols(self: *MachO) !void {
const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;
log.err("undefined reference to symbol '{s}'", .{sym_name});
- log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name.?});
+ log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});
has_undefined = true;
}
@@ -2457,7 +2457,7 @@ fn resolveSymbols(self: *MachO) !void {
fn parseTextBlocks(self: *MachO) !void {
for (self.objects.items) |object| {
- try object.parseTextBlocks(self);
+ try object.parseTextBlocks(self.base.allocator, self);
}
}
@@ -3190,7 +3190,7 @@ fn writeSymbolTable(self: *MachO) !void {
.n_value = 0,
});
locals.appendAssumeCapacity(.{
- .n_strx = try self.makeString(object.name.?),
+ .n_strx = try self.makeString(object.name),
.n_type = macho.N_OSO,
.n_sect = 0,
.n_desc = 1,
@@ -3334,7 +3334,7 @@ pub fn deinit(self: *MachO) void {
self.symbol_resolver.deinit(self.base.allocator);
for (self.objects.items) |object| {
- object.deinit();
+ object.deinit(self.base.allocator);
self.base.allocator.destroy(object);
}
self.objects.deinit(self.base.allocator);
@@ -3372,7 +3372,7 @@ pub fn deinit(self: *MachO) void {
pub fn closeFiles(self: MachO) void {
for (self.objects.items) |object| {
- object.closeFile();
+ object.file.close();
}
for (self.archives.items) |archive| {
archive.closeFile();
@@ -5913,7 +5913,7 @@ fn printSymtabAndTextBlock(self: *MachO) void {
log.debug("mappings", .{});
for (self.objects.items) |object| {
- log.debug(" in object {s}", .{object.name.?});
+ log.debug(" in object {s}", .{object.name});
for (object.symtab.items) |sym, sym_id| {
if (object.symbol_mapping.get(@intCast(u32, sym_id))) |local_id| {
log.debug(" | {d} => {d}", .{ sym_id, local_id });
diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig
index 4004cdaefc..c5fab6a1d7 100644
--- a/src/link/MachO/Archive.zig
+++ b/src/link/MachO/Archive.zig
@@ -264,14 +264,12 @@ pub fn parseObject(self: Archive, offset: u32) !*Object {
errdefer self.allocator.destroy(object);
object.* = .{
- .allocator = self.allocator,
- .arch = self.arch.?,
.file = try fs.cwd().openFile(self.name.?, .{}),
.name = name,
.file_offset = @intCast(u32, try reader.context.getPos()),
.mtime = try self.header.?.date(),
};
- try object.parse();
+ try object.parse(self.allocator, self.arch.?);
try reader.context.seekTo(0);
return object;
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index fc17669e04..1250f015ed 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -10,20 +10,22 @@ const macho = std.macho;
const math = std.math;
const mem = std.mem;
const sort = std.sort;
+const commands = @import("commands.zig");
+const segmentName = commands.segmentName;
+const sectionName = commands.sectionName;
const Allocator = mem.Allocator;
const Arch = std.Target.Cpu.Arch;
+const LoadCommand = commands.LoadCommand;
const MachO = @import("../MachO.zig");
const TextBlock = @import("TextBlock.zig");
-usingnamespace @import("commands.zig");
+file: fs.File,
+name: []const u8,
-allocator: *Allocator,
-arch: ?Arch = null,
-header: ?macho.mach_header_64 = null,
-file: ?fs.File = null,
file_offset: ?u32 = null,
-name: ?[]const u8 = null,
+
+header: ?macho.mach_header_64 = null,
load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
@@ -139,15 +141,13 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u
errdefer allocator.free(name);
object.* = .{
- .allocator = allocator,
- .arch = arch,
.name = name,
.file = file,
};
- object.parse() catch |err| switch (err) {
+ object.parse(allocator, arch) catch |err| switch (err) {
error.EndOfStream, error.NotObject => {
- object.deinit();
+ object.deinit(allocator);
allocator.destroy(object);
return null;
},
@@ -157,44 +157,35 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u
return object;
}
-pub fn deinit(self: *Object) void {
+pub fn deinit(self: *Object, allocator: *Allocator) void {
for (self.load_commands.items) |*lc| {
- lc.deinit(self.allocator);
+ lc.deinit(allocator);
}
- self.load_commands.deinit(self.allocator);
- self.data_in_code_entries.deinit(self.allocator);
- self.symtab.deinit(self.allocator);
- self.strtab.deinit(self.allocator);
- self.text_blocks.deinit(self.allocator);
- self.sections_as_symbols.deinit(self.allocator);
- self.symbol_mapping.deinit(self.allocator);
- self.reverse_symbol_mapping.deinit(self.allocator);
+ self.load_commands.deinit(allocator);
+ self.data_in_code_entries.deinit(allocator);
+ self.symtab.deinit(allocator);
+ self.strtab.deinit(allocator);
+ self.text_blocks.deinit(allocator);
+ self.sections_as_symbols.deinit(allocator);
+ self.symbol_mapping.deinit(allocator);
+ self.reverse_symbol_mapping.deinit(allocator);
+ allocator.free(self.name);
if (self.debug_info) |*db| {
- db.deinit(self.allocator);
+ db.deinit(allocator);
}
if (self.tu_name) |n| {
- self.allocator.free(n);
+ allocator.free(n);
}
if (self.tu_comp_dir) |n| {
- self.allocator.free(n);
- }
-
- if (self.name) |n| {
- self.allocator.free(n);
+ allocator.free(n);
}
}
-pub fn closeFile(self: Object) void {
- if (self.file) |f| {
- f.close();
- }
-}
-
-pub fn parse(self: *Object) !void {
- var reader = self.file.?.reader();
+pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
+ var reader = self.file.reader();
if (self.file_offset) |offset| {
try reader.context.seekTo(offset);
}
@@ -214,26 +205,28 @@ pub fn parse(self: *Object) !void {
return error.UnsupportedCpuArchitecture;
},
};
- if (this_arch != self.arch.?) {
- log.err("mismatched cpu architecture: expected {s}, found {s}", .{ self.arch.?, this_arch });
+ if (this_arch != arch) {
+ log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch });
return error.MismatchedCpuArchitecture;
}
self.header = header;
- try self.readLoadCommands(reader);
- try self.parseSymtab();
- try self.parseDataInCode();
- try self.parseDebugInfo();
+ try self.readLoadCommands(allocator, reader);
+ try self.parseSymtab(allocator);
+ try self.parseDataInCode(allocator);
+ try self.parseDebugInfo(allocator);
}
-pub fn readLoadCommands(self: *Object, reader: anytype) !void {
+pub fn readLoadCommands(self: *Object, allocator: *Allocator, reader: anytype) !void {
+ const header = self.header orelse unreachable; // Unreachable here signifies a fatal unexplored condition.
const offset = self.file_offset orelse 0;
- try self.load_commands.ensureCapacity(self.allocator, self.header.?.ncmds);
+
+ try self.load_commands.ensureCapacity(allocator, header.ncmds);
var i: u16 = 0;
- while (i < self.header.?.ncmds) : (i += 1) {
- var cmd = try LoadCommand.read(self.allocator, reader);
+ while (i < header.ncmds) : (i += 1) {
+ var cmd = try LoadCommand.read(allocator, reader);
switch (cmd.cmd()) {
macho.LC_SEGMENT_64 => {
self.segment_cmd_index = i;
@@ -347,26 +340,25 @@ fn filterDice(dices: []macho.data_in_code_entry, start_addr: u64, end_addr: u64)
return dices[start..end];
}
-const TextBlockParser = struct {
+const Context = struct {
allocator: *Allocator,
+ object: *Object,
+ macho_file: *MachO,
+ match: MachO.MatchingSection,
+};
+
+const TextBlockParser = struct {
section: macho.section_64,
code: []u8,
relocs: []macho.relocation_info,
- object: *Object,
- macho_file: *MachO,
nlists: []NlistWithIndex,
index: u32 = 0,
- match: MachO.MatchingSection,
- fn peek(self: *TextBlockParser) ?NlistWithIndex {
+ fn peek(self: TextBlockParser) ?NlistWithIndex {
return if (self.index + 1 < self.nlists.len) self.nlists[self.index + 1] else null;
}
- const SeniorityContext = struct {
- object: *Object,
- };
-
- fn lessThanBySeniority(context: SeniorityContext, lhs: NlistWithIndex, rhs: NlistWithIndex) bool {
+ fn lessThanBySeniority(context: Context, lhs: NlistWithIndex, rhs: NlistWithIndex) bool {
if (!MachO.symbolIsExt(rhs.nlist)) {
return MachO.symbolIsTemp(lhs.nlist, context.object.getString(lhs.nlist.n_strx));
} else if (MachO.symbolIsPext(rhs.nlist) or MachO.symbolIsWeakDef(rhs.nlist)) {
@@ -376,10 +368,10 @@ const TextBlockParser = struct {
}
}
- pub fn next(self: *TextBlockParser) !?*TextBlock {
+ pub fn next(self: *TextBlockParser, context: Context) !?*TextBlock {
if (self.index == self.nlists.len) return null;
- var aliases = std.ArrayList(NlistWithIndex).init(self.allocator);
+ var aliases = std.ArrayList(NlistWithIndex).init(context.allocator);
defer aliases.deinit();
const next_nlist: ?NlistWithIndex = blk: while (true) {
@@ -397,7 +389,7 @@ const TextBlockParser = struct {
} else null;
for (aliases.items) |*nlist_with_index| {
- nlist_with_index.index = self.object.symbol_mapping.get(nlist_with_index.index) orelse unreachable;
+ nlist_with_index.index = context.object.symbol_mapping.get(nlist_with_index.index) orelse unreachable;
}
if (aliases.items.len > 1) {
@@ -405,14 +397,14 @@ const TextBlockParser = struct {
sort.sort(
NlistWithIndex,
aliases.items,
- SeniorityContext{ .object = self.object },
+ context,
TextBlockParser.lessThanBySeniority,
);
}
const senior_nlist = aliases.pop();
- const senior_sym = &self.macho_file.locals.items[senior_nlist.index];
- senior_sym.n_sect = self.macho_file.section_to_ordinal.get(self.match) orelse unreachable;
+ const senior_sym = &context.macho_file.locals.items[senior_nlist.index];
+ senior_sym.n_sect = context.macho_file.section_to_ordinal.get(context.match) orelse unreachable;
const start_addr = senior_nlist.nlist.n_value - self.section.addr;
const end_addr = if (next_nlist) |n| n.nlist.n_value - self.section.addr else self.section.size;
@@ -426,7 +418,7 @@ const TextBlockParser = struct {
else
max_align;
- const stab: ?TextBlock.Stab = if (self.object.debug_info) |di| blk: {
+ const stab: ?TextBlock.Stab = if (context.object.debug_info) |di| blk: {
// TODO there has to be a better to handle this.
for (di.inner.func_list.items) |func| {
if (func.pc_range) |range| {
@@ -442,35 +434,37 @@ const TextBlockParser = struct {
break :blk .static;
} else null;
- const block = try self.macho_file.base.allocator.create(TextBlock);
+ const block = try context.allocator.create(TextBlock);
block.* = TextBlock.empty;
block.local_sym_index = senior_nlist.index;
block.stab = stab;
block.size = size;
block.alignment = actual_align;
- try self.macho_file.managed_blocks.append(self.macho_file.base.allocator, block);
+ try context.macho_file.managed_blocks.append(context.allocator, block);
- try block.code.appendSlice(self.macho_file.base.allocator, code);
+ try block.code.appendSlice(context.allocator, code);
- try block.aliases.ensureTotalCapacity(self.macho_file.base.allocator, aliases.items.len);
+ try block.aliases.ensureTotalCapacity(context.allocator, aliases.items.len);
for (aliases.items) |alias| {
block.aliases.appendAssumeCapacity(alias.index);
- const sym = &self.macho_file.locals.items[alias.index];
- sym.n_sect = self.macho_file.section_to_ordinal.get(self.match) orelse unreachable;
+ const sym = &context.macho_file.locals.items[alias.index];
+ sym.n_sect = context.macho_file.section_to_ordinal.get(context.match) orelse unreachable;
}
- try block.parseRelocsFromObject(self.macho_file.base.allocator, self.relocs, self.object, .{
+ try block.parseRelocs(self.relocs, .{
.base_addr = start_addr,
- .macho_file = self.macho_file,
+ .allocator = context.allocator,
+ .object = context.object,
+ .macho_file = context.macho_file,
});
- if (self.macho_file.has_dices) {
+ if (context.macho_file.has_dices) {
const dices = filterDice(
- self.object.data_in_code_entries.items,
+ context.object.data_in_code_entries.items,
senior_nlist.nlist.n_value,
senior_nlist.nlist.n_value + size,
);
- try block.dices.ensureTotalCapacity(self.macho_file.base.allocator, dices.len);
+ try block.dices.ensureTotalCapacity(context.allocator, dices.len);
for (dices) |dice| {
block.dices.appendAssumeCapacity(.{
@@ -487,16 +481,16 @@ const TextBlockParser = struct {
}
};
-pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
+pub fn parseTextBlocks(self: *Object, allocator: *Allocator, macho_file: *MachO) !void {
const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
- log.debug("analysing {s}", .{self.name.?});
+ log.debug("analysing {s}", .{self.name});
// You would expect that the symbol table is at least pre-sorted based on symbol's type:
// local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance,
// the GO compiler does not necessarily respect that therefore we sort immediately by type
// and address within.
- var sorted_all_nlists = std.ArrayList(NlistWithIndex).init(self.allocator);
+ var sorted_all_nlists = std.ArrayList(NlistWithIndex).init(allocator);
defer sorted_all_nlists.deinit();
try sorted_all_nlists.ensureTotalCapacity(self.symtab.items.len);
@@ -540,14 +534,14 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
};
// Read section's code
- var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));
- defer self.allocator.free(code);
- _ = try self.file.?.preadAll(code, sect.offset);
+ var code = try allocator.alloc(u8, @intCast(usize, sect.size));
+ defer allocator.free(code);
+ _ = try self.file.preadAll(code, sect.offset);
// Read section's list of relocations
- var raw_relocs = try self.allocator.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info));
- defer self.allocator.free(raw_relocs);
- _ = try self.file.?.preadAll(raw_relocs, sect.reloff);
+ var raw_relocs = try allocator.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info));
+ defer allocator.free(raw_relocs);
+ _ = try self.file.preadAll(raw_relocs, sect.reloff);
const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);
// Symbols within this section only.
@@ -579,46 +573,48 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
// as a temporary symbol and insert the matching TextBlock.
const first_nlist = filtered_nlists[0].nlist;
if (first_nlist.n_value > sect.addr) {
- const sym_name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{
- self.name.?,
+ const sym_name = try std.fmt.allocPrint(allocator, "l_{s}_{s}_{s}", .{
+ self.name,
segmentName(sect),
sectionName(sect),
});
- defer self.allocator.free(sym_name);
+ defer allocator.free(sym_name);
const block_local_sym_index = self.sections_as_symbols.get(sect_id) orelse blk: {
const block_local_sym_index = @intCast(u32, macho_file.locals.items.len);
- try macho_file.locals.append(macho_file.base.allocator, .{
+ try macho_file.locals.append(allocator, .{
.n_strx = try macho_file.makeString(sym_name),
.n_type = macho.N_SECT,
.n_sect = macho_file.section_to_ordinal.get(match) orelse unreachable,
.n_desc = 0,
.n_value = sect.addr,
});
- try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, block_local_sym_index);
+ try self.sections_as_symbols.putNoClobber(allocator, sect_id, block_local_sym_index);
break :blk block_local_sym_index;
};
const block_code = code[0 .. first_nlist.n_value - sect.addr];
const block_size = block_code.len;
- const block = try macho_file.base.allocator.create(TextBlock);
+ const block = try allocator.create(TextBlock);
block.* = TextBlock.empty;
block.local_sym_index = block_local_sym_index;
block.size = block_size;
block.alignment = sect.@"align";
- try macho_file.managed_blocks.append(macho_file.base.allocator, block);
+ try macho_file.managed_blocks.append(allocator, block);
- try block.code.appendSlice(macho_file.base.allocator, block_code);
+ try block.code.appendSlice(allocator, block_code);
- try block.parseRelocsFromObject(self.allocator, relocs, self, .{
+ try block.parseRelocs(relocs, .{
.base_addr = 0,
+ .allocator = allocator,
+ .object = self,
.macho_file = macho_file,
});
if (macho_file.has_dices) {
const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + block_size);
- try block.dices.ensureTotalCapacity(macho_file.base.allocator, dices.len);
+ try block.dices.ensureTotalCapacity(allocator, dices.len);
for (dices) |dice| {
block.dices.appendAssumeCapacity(.{
@@ -645,24 +641,25 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
block.prev = last.*;
last.* = block;
} else {
- try macho_file.blocks.putNoClobber(macho_file.base.allocator, match, block);
+ try macho_file.blocks.putNoClobber(allocator, match, block);
}
- try self.text_blocks.append(self.allocator, block);
+ try self.text_blocks.append(allocator, block);
}
var parser = TextBlockParser{
- .allocator = self.allocator,
.section = sect,
.code = code,
.relocs = relocs,
- .object = self,
- .macho_file = macho_file,
.nlists = filtered_nlists,
- .match = match,
};
- while (try parser.next()) |block| {
+ while (try parser.next(.{
+ .allocator = allocator,
+ .object = self,
+ .macho_file = macho_file,
+ .match = match,
+ })) |block| {
const sym = macho_file.locals.items[block.local_sym_index];
const is_ext = blk: {
const orig_sym_id = self.reverse_symbol_mapping.get(block.local_sym_index) orelse unreachable;
@@ -675,9 +672,9 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
if (global_object != self) {
log.debug("deduping definition of {s} in {s}", .{
macho_file.getString(sym.n_strx),
- self.name.?,
+ self.name,
});
- log.debug(" already defined in {s}", .{global_object.name.?});
+ log.debug(" already defined in {s}", .{global_object.name});
continue;
}
}
@@ -688,7 +685,7 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
// In x86_64 relocs, it can so happen that the compiler refers to the same
// atom by both the actual assigned symbol and the start of the section. In this
// case, we need to link the two together so add an alias.
- try block.aliases.append(macho_file.base.allocator, alias);
+ try block.aliases.append(allocator, alias);
}
}
@@ -708,10 +705,10 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
block.prev = last.*;
last.* = block;
} else {
- try macho_file.blocks.putNoClobber(macho_file.base.allocator, match, block);
+ try macho_file.blocks.putNoClobber(allocator, match, block);
}
- try self.text_blocks.append(self.allocator, block);
+ try self.text_blocks.append(allocator, block);
}
break :next;
@@ -720,43 +717,45 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
// Since there is no symbol to refer to this block, we create
// a temp one, unless we already did that when working out the relocations
// of other text blocks.
- const sym_name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{
- self.name.?,
+ const sym_name = try std.fmt.allocPrint(allocator, "l_{s}_{s}_{s}", .{
+ self.name,
segmentName(sect),
sectionName(sect),
});
- defer self.allocator.free(sym_name);
+ defer allocator.free(sym_name);
const block_local_sym_index = self.sections_as_symbols.get(sect_id) orelse blk: {
const block_local_sym_index = @intCast(u32, macho_file.locals.items.len);
- try macho_file.locals.append(macho_file.base.allocator, .{
+ try macho_file.locals.append(allocator, .{
.n_strx = try macho_file.makeString(sym_name),
.n_type = macho.N_SECT,
.n_sect = macho_file.section_to_ordinal.get(match) orelse unreachable,
.n_desc = 0,
.n_value = sect.addr,
});
- try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, block_local_sym_index);
+ try self.sections_as_symbols.putNoClobber(allocator, sect_id, block_local_sym_index);
break :blk block_local_sym_index;
};
- const block = try macho_file.base.allocator.create(TextBlock);
+ const block = try allocator.create(TextBlock);
block.* = TextBlock.empty;
block.local_sym_index = block_local_sym_index;
block.size = sect.size;
block.alignment = sect.@"align";
- try macho_file.managed_blocks.append(macho_file.base.allocator, block);
+ try macho_file.managed_blocks.append(allocator, block);
- try block.code.appendSlice(macho_file.base.allocator, code);
+ try block.code.appendSlice(allocator, code);
- try block.parseRelocsFromObject(self.allocator, relocs, self, .{
+ try block.parseRelocs(relocs, .{
.base_addr = 0,
+ .allocator = allocator,
+ .object = self,
.macho_file = macho_file,
});
if (macho_file.has_dices) {
const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + sect.size);
- try block.dices.ensureTotalCapacity(macho_file.base.allocator, dices.len);
+ try block.dices.ensureTotalCapacity(allocator, dices.len);
for (dices) |dice| {
block.dices.appendAssumeCapacity(.{
@@ -772,7 +771,7 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
// the filtered symbols and note which symbol is contained within so that
// we can properly allocate addresses down the line.
// While we're at it, we need to update segment,section mapping of each symbol too.
- try block.contained.ensureTotalCapacity(self.allocator, filtered_nlists.len);
+ try block.contained.ensureTotalCapacity(allocator, filtered_nlists.len);
for (filtered_nlists) |nlist_with_index| {
const nlist = nlist_with_index.nlist;
@@ -819,35 +818,35 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
block.prev = last.*;
last.* = block;
} else {
- try macho_file.blocks.putNoClobber(macho_file.base.allocator, match, block);
+ try macho_file.blocks.putNoClobber(allocator, match, block);
}
- try self.text_blocks.append(self.allocator, block);
+ try self.text_blocks.append(allocator, block);
}
}
}
-fn parseSymtab(self: *Object) !void {
+fn parseSymtab(self: *Object, allocator: *Allocator) !void {
const index = self.symtab_cmd_index orelse return;
const symtab_cmd = self.load_commands.items[index].Symtab;
- var symtab = try self.allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms);
- defer self.allocator.free(symtab);
- _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff);
+ var symtab = try allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms);
+ defer allocator.free(symtab);
+ _ = try self.file.preadAll(symtab, symtab_cmd.symoff);
const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab));
- try self.symtab.appendSlice(self.allocator, slice);
+ try self.symtab.appendSlice(allocator, slice);
- var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize);
- defer self.allocator.free(strtab);
- _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff);
- try self.strtab.appendSlice(self.allocator, strtab);
+ var strtab = try allocator.alloc(u8, symtab_cmd.strsize);
+ defer allocator.free(strtab);
+ _ = try self.file.preadAll(strtab, symtab_cmd.stroff);
+ try self.strtab.appendSlice(allocator, strtab);
}
-pub fn parseDebugInfo(self: *Object) !void {
- log.debug("parsing debug info in '{s}'", .{self.name.?});
+pub fn parseDebugInfo(self: *Object, allocator: *Allocator) !void {
+ log.debug("parsing debug info in '{s}'", .{self.name});
var debug_info = blk: {
- var di = try DebugInfo.parseFromObject(self.allocator, self);
+ var di = try DebugInfo.parseFromObject(allocator, self);
break :blk di orelse return;
};
@@ -855,7 +854,7 @@ pub fn parseDebugInfo(self: *Object) !void {
const compile_unit = debug_info.inner.findCompileUnit(0x0) catch |err| switch (err) {
error.MissingDebugInfo => {
// TODO audit cases with missing debug info and audit our dwarf.zig module.
- log.debug("invalid or missing debug info in {s}; skipping", .{self.name.?});
+ log.debug("invalid or missing debug info in {s}; skipping", .{self.name});
return;
},
else => |e| return e,
@@ -864,26 +863,25 @@ pub fn parseDebugInfo(self: *Object) !void {
const comp_dir = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT_comp_dir);
self.debug_info = debug_info;
- self.tu_name = try self.allocator.dupe(u8, name);
- self.tu_comp_dir = try self.allocator.dupe(u8, comp_dir);
+ self.tu_name = try allocator.dupe(u8, name);
+ self.tu_comp_dir = try allocator.dupe(u8, comp_dir);
if (self.mtime == null) {
self.mtime = mtime: {
- const file = self.file orelse break :mtime 0;
- const stat = file.stat() catch break :mtime 0;
+ const stat = self.file.stat() catch break :mtime 0;
break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000));
};
}
}
-pub fn parseDataInCode(self: *Object) !void {
+pub fn parseDataInCode(self: *Object, allocator: *Allocator) !void {
const index = self.data_in_code_cmd_index orelse return;
const data_in_code = self.load_commands.items[index].LinkeditData;
- var buffer = try self.allocator.alloc(u8, data_in_code.datasize);
- defer self.allocator.free(buffer);
+ var buffer = try allocator.alloc(u8, data_in_code.datasize);
+ defer allocator.free(buffer);
- _ = try self.file.?.preadAll(buffer, data_in_code.dataoff);
+ _ = try self.file.preadAll(buffer, data_in_code.dataoff);
var stream = io.fixedBufferStream(buffer);
var reader = stream.reader();
@@ -892,7 +890,7 @@ pub fn parseDataInCode(self: *Object) !void {
error.EndOfStream => break,
else => |e| return e,
};
- try self.data_in_code_entries.append(self.allocator, dice);
+ try self.data_in_code_entries.append(allocator, dice);
}
}
@@ -900,7 +898,7 @@ fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 {
const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
const sect = seg.sections.items[index];
var buffer = try allocator.alloc(u8, @intCast(usize, sect.size));
- _ = try self.file.?.preadAll(buffer, sect.offset);
+ _ = try self.file.preadAll(buffer, sect.offset);
return buffer;
}
diff --git a/src/link/MachO/TextBlock.zig b/src/link/MachO/TextBlock.zig
index 8dca7bc37b..ef10d3fe09 100644
--- a/src/link/MachO/TextBlock.zig
+++ b/src/link/MachO/TextBlock.zig
@@ -606,12 +606,14 @@ pub fn freeListEligible(self: TextBlock, macho_file: MachO) bool {
const RelocContext = struct {
base_addr: u64 = 0,
+ allocator: *Allocator,
+ object: *Object,
macho_file: *MachO,
};
-fn initRelocFromObject(rel: macho.relocation_info, object: *Object, ctx: RelocContext) !Relocation {
+fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Relocation {
var parsed_rel = Relocation{
- .offset = @intCast(u32, @intCast(u64, rel.r_address) - ctx.base_addr),
+ .offset = @intCast(u32, @intCast(u64, rel.r_address) - context.base_addr),
.where = undefined,
.where_index = undefined,
.payload = undefined,
@@ -620,44 +622,44 @@ fn initRelocFromObject(rel: macho.relocation_info, object: *Object, ctx: RelocCo
if (rel.r_extern == 0) {
const sect_id = @intCast(u16, rel.r_symbolnum - 1);
- const local_sym_index = object.sections_as_symbols.get(sect_id) orelse blk: {
- const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
+ const local_sym_index = context.object.sections_as_symbols.get(sect_id) orelse blk: {
+ const seg = context.object.load_commands.items[context.object.segment_cmd_index.?].Segment;
const sect = seg.sections.items[sect_id];
- const match = (try ctx.macho_file.getMatchingSection(sect)) orelse unreachable;
- const local_sym_index = @intCast(u32, ctx.macho_file.locals.items.len);
- const sym_name = try std.fmt.allocPrint(ctx.macho_file.base.allocator, "l_{s}_{s}_{s}", .{
- object.name.?,
+ const match = (try context.macho_file.getMatchingSection(sect)) orelse unreachable;
+ const local_sym_index = @intCast(u32, context.macho_file.locals.items.len);
+ const sym_name = try std.fmt.allocPrint(context.allocator, "l_{s}_{s}_{s}", .{
+ context.object.name,
commands.segmentName(sect),
commands.sectionName(sect),
});
- defer ctx.macho_file.base.allocator.free(sym_name);
+ defer context.allocator.free(sym_name);
- try ctx.macho_file.locals.append(ctx.macho_file.base.allocator, .{
- .n_strx = try ctx.macho_file.makeString(sym_name),
+ try context.macho_file.locals.append(context.allocator, .{
+ .n_strx = try context.macho_file.makeString(sym_name),
.n_type = macho.N_SECT,
- .n_sect = ctx.macho_file.section_to_ordinal.get(match) orelse unreachable,
+ .n_sect = context.macho_file.section_to_ordinal.get(match) orelse unreachable,
.n_desc = 0,
.n_value = sect.addr,
});
- try object.sections_as_symbols.putNoClobber(object.allocator, sect_id, local_sym_index);
+ try context.object.sections_as_symbols.putNoClobber(context.allocator, sect_id, local_sym_index);
break :blk local_sym_index;
};
parsed_rel.where = .local;
parsed_rel.where_index = local_sym_index;
} else {
- const sym = object.symtab.items[rel.r_symbolnum];
- const sym_name = object.getString(sym.n_strx);
+ const sym = context.object.symtab.items[rel.r_symbolnum];
+ const sym_name = context.object.getString(sym.n_strx);
if (MachO.symbolIsSect(sym) and !MachO.symbolIsExt(sym)) {
- const where_index = object.symbol_mapping.get(rel.r_symbolnum) orelse unreachable;
+ const where_index = context.object.symbol_mapping.get(rel.r_symbolnum) orelse unreachable;
parsed_rel.where = .local;
parsed_rel.where_index = where_index;
} else {
- const n_strx = ctx.macho_file.strtab_dir.getAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
- .strtab = &ctx.macho_file.strtab,
+ const n_strx = context.macho_file.strtab_dir.getAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
+ .strtab = &context.macho_file.strtab,
}) orelse unreachable;
- const resolv = ctx.macho_file.symbol_resolver.get(n_strx) orelse unreachable;
+ const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;
switch (resolv.where) {
.global => {
parsed_rel.where = .local;
@@ -675,29 +677,24 @@ fn initRelocFromObject(rel: macho.relocation_info, object: *Object, ctx: RelocCo
return parsed_rel;
}
-pub fn parseRelocsFromObject(
- self: *TextBlock,
- allocator: *Allocator,
- relocs: []macho.relocation_info,
- object: *Object,
- ctx: RelocContext,
-) !void {
- const filtered_relocs = filterRelocs(relocs, ctx.base_addr, ctx.base_addr + self.size);
+pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: RelocContext) !void {
+ const filtered_relocs = filterRelocs(relocs, context.base_addr, context.base_addr + self.size);
var it = RelocIterator{
.buffer = filtered_relocs,
};
var addend: u32 = 0;
var subtractor: ?u32 = null;
+ const arch = context.macho_file.base.options.target.cpu.arch;
while (it.next()) |rel| {
- if (isAddend(rel, object.arch.?)) {
+ if (isAddend(rel, arch)) {
// Addend is not a relocation with effect on the TextBlock, so
// parse it and carry on.
assert(addend == 0); // Oh no, addend was not reset!
addend = rel.r_symbolnum;
- // Verify ADDEND is followed by a load.
+ // Verify ADDEND is followed by a PAGE21 or PAGEOFF12.
const next = @intToEnum(macho.reloc_type_arm64, it.peek().r_type);
switch (next) {
.ARM64_RELOC_PAGE21, .ARM64_RELOC_PAGEOFF12 => {},
@@ -709,28 +706,28 @@ pub fn parseRelocsFromObject(
continue;
}
- if (isSubtractor(rel, object.arch.?)) {
+ if (isSubtractor(rel, arch)) {
// Subtractor is not a relocation with effect on the TextBlock, so
// parse it and carry on.
assert(subtractor == null); // Oh no, subtractor was not reset!
assert(rel.r_extern == 1);
- const sym = object.symtab.items[rel.r_symbolnum];
- const sym_name = object.getString(sym.n_strx);
+ const sym = context.object.symtab.items[rel.r_symbolnum];
+ const sym_name = context.object.getString(sym.n_strx);
if (MachO.symbolIsSect(sym) and !MachO.symbolIsExt(sym)) {
- const where_index = object.symbol_mapping.get(rel.r_symbolnum) orelse unreachable;
+ const where_index = context.object.symbol_mapping.get(rel.r_symbolnum) orelse unreachable;
subtractor = where_index;
} else {
- const n_strx = ctx.macho_file.strtab_dir.getAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
- .strtab = &ctx.macho_file.strtab,
+ const n_strx = context.macho_file.strtab_dir.getAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
+ .strtab = &context.macho_file.strtab,
}) orelse unreachable;
- const resolv = ctx.macho_file.symbol_resolver.get(n_strx) orelse unreachable;
+ const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;
assert(resolv.where == .global);
subtractor = resolv.local_sym_index;
}
// Verify SUBTRACTOR is followed by UNSIGNED.
- switch (object.arch.?) {
+ switch (arch) {
.aarch64 => {
const next = @intToEnum(macho.reloc_type_arm64, it.peek().r_type);
if (next != .ARM64_RELOC_UNSIGNED) {
@@ -750,19 +747,19 @@ pub fn parseRelocsFromObject(
continue;
}
- var parsed_rel = try initRelocFromObject(rel, object, ctx);
+ var parsed_rel = try initRelocFromObject(rel, context);
- switch (object.arch.?) {
+ switch (arch) {
.aarch64 => {
const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);
switch (rel_type) {
.ARM64_RELOC_ADDEND => unreachable,
.ARM64_RELOC_SUBTRACTOR => unreachable,
.ARM64_RELOC_BRANCH26 => {
- self.parseBranch(rel, &parsed_rel, ctx);
+ self.parseBranch(rel, &parsed_rel, context);
},
.ARM64_RELOC_UNSIGNED => {
- self.parseUnsigned(rel, &parsed_rel, subtractor, ctx);
+ self.parseUnsigned(rel, &parsed_rel, subtractor, context);
subtractor = null;
},
.ARM64_RELOC_PAGE21,
@@ -790,10 +787,10 @@ pub fn parseRelocsFromObject(
switch (@intToEnum(macho.reloc_type_x86_64, rel.r_type)) {
.X86_64_RELOC_SUBTRACTOR => unreachable,
.X86_64_RELOC_BRANCH => {
- self.parseBranch(rel, &parsed_rel, ctx);
+ self.parseBranch(rel, &parsed_rel, context);
},
.X86_64_RELOC_UNSIGNED => {
- self.parseUnsigned(rel, &parsed_rel, subtractor, ctx);
+ self.parseUnsigned(rel, &parsed_rel, subtractor, context);
subtractor = null;
},
.X86_64_RELOC_SIGNED,
@@ -801,7 +798,7 @@ pub fn parseRelocsFromObject(
.X86_64_RELOC_SIGNED_2,
.X86_64_RELOC_SIGNED_4,
=> {
- self.parseSigned(rel, &parsed_rel, ctx);
+ self.parseSigned(rel, &parsed_rel, context);
},
.X86_64_RELOC_GOT_LOAD,
.X86_64_RELOC_GOT,
@@ -814,7 +811,7 @@ pub fn parseRelocsFromObject(
else => unreachable,
}
- try self.relocs.append(allocator, parsed_rel);
+ try self.relocs.append(context.allocator, parsed_rel);
const is_via_got = switch (parsed_rel.payload) {
.pointer_to_got => true,
@@ -832,23 +829,23 @@ pub fn parseRelocsFromObject(
},
.where_index = parsed_rel.where_index,
};
- if (ctx.macho_file.got_entries_map.contains(key)) break :blk;
+ if (context.macho_file.got_entries_map.contains(key)) break :blk;
- const got_index = @intCast(u32, ctx.macho_file.got_entries.items.len);
- try ctx.macho_file.got_entries.append(ctx.macho_file.base.allocator, key);
- try ctx.macho_file.got_entries_map.putNoClobber(ctx.macho_file.base.allocator, key, got_index);
+ const got_index = @intCast(u32, context.macho_file.got_entries.items.len);
+ try context.macho_file.got_entries.append(context.allocator, key);
+ try context.macho_file.got_entries_map.putNoClobber(context.allocator, key, got_index);
} else if (parsed_rel.payload == .unsigned) {
switch (parsed_rel.where) {
.import => {
- try self.bindings.append(allocator, .{
+ try self.bindings.append(context.allocator, .{
.local_sym_index = parsed_rel.where_index,
.offset = parsed_rel.offset,
});
},
.local => {
- const source_sym = ctx.macho_file.locals.items[self.local_sym_index];
- const match = ctx.macho_file.section_ordinals.items[source_sym.n_sect];
- const seg = ctx.macho_file.load_commands.items[match.seg].Segment;
+ const source_sym = context.macho_file.locals.items[self.local_sym_index];
+ const match = context.macho_file.section_ordinals.items[source_sym.n_sect];
+ const seg = context.macho_file.load_commands.items[match.seg].Segment;
const sect = seg.sections.items[match.sect];
const sect_type = commands.sectionType(sect);
@@ -858,12 +855,12 @@ pub fn parseRelocsFromObject(
// TODO actually, a check similar to what dyld is doing, that is, verifying
// that the segment is writable should be enough here.
const is_right_segment = blk: {
- if (ctx.macho_file.data_segment_cmd_index) |idx| {
+ if (context.macho_file.data_segment_cmd_index) |idx| {
if (match.seg == idx) {
break :blk true;
}
}
- if (ctx.macho_file.data_const_segment_cmd_index) |idx| {
+ if (context.macho_file.data_const_segment_cmd_index) |idx| {
if (match.seg == idx) {
break :blk true;
}
@@ -884,17 +881,17 @@ pub fn parseRelocsFromObject(
};
if (should_rebase) {
- try self.rebases.append(allocator, parsed_rel.offset);
+ try self.rebases.append(context.allocator, parsed_rel.offset);
}
},
}
} else if (parsed_rel.payload == .branch) blk: {
if (parsed_rel.where != .import) break :blk;
- if (ctx.macho_file.stubs_map.contains(parsed_rel.where_index)) break :blk;
+ if (context.macho_file.stubs_map.contains(parsed_rel.where_index)) break :blk;
- const stubs_index = @intCast(u32, ctx.macho_file.stubs.items.len);
- try ctx.macho_file.stubs.append(ctx.macho_file.base.allocator, parsed_rel.where_index);
- try ctx.macho_file.stubs_map.putNoClobber(ctx.macho_file.base.allocator, parsed_rel.where_index, stubs_index);
+ const stubs_index = @intCast(u32, context.macho_file.stubs.items.len);
+ try context.macho_file.stubs.append(context.allocator, parsed_rel.where_index);
+ try context.macho_file.stubs_map.putNoClobber(context.allocator, parsed_rel.where_index, stubs_index);
}
}
}
@@ -917,7 +914,7 @@ fn parseUnsigned(
rel: macho.relocation_info,
out: *Relocation,
subtractor: ?u32,
- ctx: RelocContext,
+ context: RelocContext,
) void {
assert(rel.r_pcrel == 0);
@@ -934,7 +931,7 @@ fn parseUnsigned(
if (rel.r_extern == 0) {
assert(out.where == .local);
- const target_sym = ctx.macho_file.locals.items[out.where_index];
+ const target_sym = context.macho_file.locals.items[out.where_index];
addend -= @intCast(i64, target_sym.n_value);
}
@@ -947,14 +944,14 @@ fn parseUnsigned(
};
}
-fn parseBranch(self: TextBlock, rel: macho.relocation_info, out: *Relocation, ctx: RelocContext) void {
+fn parseBranch(self: TextBlock, rel: macho.relocation_info, out: *Relocation, context: RelocContext) void {
_ = self;
assert(rel.r_pcrel == 1);
assert(rel.r_length == 2);
out.payload = .{
.branch = .{
- .arch = ctx.macho_file.base.options.target.cpu.arch,
+ .arch = context.macho_file.base.options.target.cpu.arch,
},
};
}
@@ -1015,7 +1012,7 @@ fn parsePointerToGot(self: TextBlock, rel: macho.relocation_info, out: *Relocati
};
}
-fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, ctx: RelocContext) void {
+fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, context: RelocContext) void {
assert(rel.r_pcrel == 1);
assert(rel.r_length == 2);
@@ -1030,10 +1027,10 @@ fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, ct
var addend: i64 = mem.readIntLittle(i32, self.code.items[out.offset..][0..4]) + correction;
if (rel.r_extern == 0) {
- const source_sym = ctx.macho_file.locals.items[self.local_sym_index];
+ const source_sym = context.macho_file.locals.items[self.local_sym_index];
const target_sym = switch (out.where) {
- .local => ctx.macho_file.locals.items[out.where_index],
- .import => ctx.macho_file.imports.items[out.where_index],
+ .local => context.macho_file.locals.items[out.where_index],
+ .import => context.macho_file.imports.items[out.where_index],
};
addend = @intCast(i64, source_sym.n_value + out.offset + 4) + addend - @intCast(i64, target_sym.n_value);
}
From 586a19e3db7d462559874ce6ac877608f7e50f10 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 10:41:51 +0200
Subject: [PATCH 38/96] macho: don't store allocator in Archive
instead pass it in functions as an arg when required.
---
src/link/MachO.zig | 10 +++--
src/link/MachO/Archive.zig | 88 ++++++++++++++++----------------------
2 files changed, 44 insertions(+), 54 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 78c926f5f1..c42bf550ef 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -2228,7 +2228,11 @@ fn resolveSymbols(self: *MachO) !void {
};
assert(offsets.items.len > 0);
- const object = try archive.parseObject(offsets.items[0]);
+ const object = try archive.parseObject(
+ self.base.allocator,
+ self.base.options.target.cpu.arch,
+ offsets.items[0],
+ );
const object_id = @intCast(u16, self.objects.items.len);
try self.objects.append(self.base.allocator, object);
try self.resolveSymbolsInObject(object_id);
@@ -3340,7 +3344,7 @@ pub fn deinit(self: *MachO) void {
self.objects.deinit(self.base.allocator);
for (self.archives.items) |archive| {
- archive.deinit();
+ archive.deinit(self.base.allocator);
self.base.allocator.destroy(archive);
}
self.archives.deinit(self.base.allocator);
@@ -3375,7 +3379,7 @@ pub fn closeFiles(self: MachO) void {
object.file.close();
}
for (self.archives.items) |archive| {
- archive.closeFile();
+ archive.file.close();
}
}
diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig
index c5fab6a1d7..228e8f74b9 100644
--- a/src/link/MachO/Archive.zig
+++ b/src/link/MachO/Archive.zig
@@ -12,13 +12,10 @@ const Allocator = mem.Allocator;
const Arch = std.Target.Cpu.Arch;
const Object = @import("Object.zig");
-usingnamespace @import("commands.zig");
+file: fs.File,
+name: []const u8,
-allocator: *Allocator,
-arch: ?Arch = null,
-file: ?fs.File = null,
header: ?ar_hdr = null,
-name: ?[]const u8 = null,
// The actual contents we care about linking with will be embedded at
// an offset within a file if we are linking against a fat lib
@@ -110,15 +107,13 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u
errdefer allocator.free(name);
archive.* = .{
- .allocator = allocator,
- .arch = arch,
.name = name,
.file = file,
};
- archive.parse() catch |err| switch (err) {
+ archive.parse(allocator, arch) catch |err| switch (err) {
error.EndOfStream, error.NotArchive => {
- archive.deinit();
+ archive.deinit(allocator);
allocator.destroy(archive);
return null;
},
@@ -128,32 +123,23 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u
return archive;
}
-pub fn deinit(self: *Archive) void {
+pub fn deinit(self: *Archive, allocator: *Allocator) void {
for (self.toc.keys()) |*key| {
- self.allocator.free(key.*);
+ allocator.free(key.*);
}
for (self.toc.values()) |*value| {
- value.deinit(self.allocator);
- }
- self.toc.deinit(self.allocator);
-
- if (self.name) |n| {
- self.allocator.free(n);
+ value.deinit(allocator);
}
+ self.toc.deinit(allocator);
+ allocator.free(self.name);
}
-pub fn closeFile(self: Archive) void {
- if (self.file) |f| {
- f.close();
- }
-}
+pub fn parse(self: *Archive, allocator: *Allocator, arch: Arch) !void {
+ self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch);
-pub fn parse(self: *Archive) !void {
- self.library_offset = try fat.getLibraryOffset(self.file.?.reader(), self.arch.?);
+ try self.file.seekTo(self.library_offset);
- try self.file.?.seekTo(self.library_offset);
-
- var reader = self.file.?.reader();
+ var reader = self.file.reader();
const magic = try reader.readBytesNoEof(SARMAG);
if (!mem.eql(u8, &magic, ARMAG)) {
@@ -168,11 +154,11 @@ pub fn parse(self: *Archive) !void {
return error.NotArchive;
}
- var embedded_name = try parseName(self.allocator, self.header.?, reader);
- log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name.? });
- defer self.allocator.free(embedded_name);
+ var embedded_name = try parseName(allocator, self.header.?, reader);
+ log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name });
+ defer allocator.free(embedded_name);
- try self.parseTableOfContents(reader);
+ try self.parseTableOfContents(allocator, reader);
try reader.context.seekTo(0);
}
@@ -195,10 +181,10 @@ fn parseName(allocator: *Allocator, header: ar_hdr, reader: anytype) ![]u8 {
return name;
}
-fn parseTableOfContents(self: *Archive, reader: anytype) !void {
+fn parseTableOfContents(self: *Archive, allocator: *Allocator, reader: anytype) !void {
const symtab_size = try reader.readIntLittle(u32);
- var symtab = try self.allocator.alloc(u8, symtab_size);
- defer self.allocator.free(symtab);
+ var symtab = try allocator.alloc(u8, symtab_size);
+ defer allocator.free(symtab);
reader.readNoEof(symtab) catch {
log.err("incomplete symbol table: expected symbol table of length 0x{x}", .{symtab_size});
@@ -206,8 +192,8 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void {
};
const strtab_size = try reader.readIntLittle(u32);
- var strtab = try self.allocator.alloc(u8, strtab_size);
- defer self.allocator.free(strtab);
+ var strtab = try allocator.alloc(u8, strtab_size);
+ defer allocator.free(strtab);
reader.readNoEof(strtab) catch {
log.err("incomplete symbol table: expected string table of length 0x{x}", .{strtab_size});
@@ -225,21 +211,21 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void {
const object_offset = try symtab_reader.readIntLittle(u32);
const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + n_strx));
- const owned_name = try self.allocator.dupe(u8, sym_name);
- const res = try self.toc.getOrPut(self.allocator, owned_name);
- defer if (res.found_existing) self.allocator.free(owned_name);
+ const owned_name = try allocator.dupe(u8, sym_name);
+ const res = try self.toc.getOrPut(allocator, owned_name);
+ defer if (res.found_existing) allocator.free(owned_name);
if (!res.found_existing) {
res.value_ptr.* = .{};
}
- try res.value_ptr.append(self.allocator, object_offset);
+ try res.value_ptr.append(allocator, object_offset);
}
}
/// Caller owns the Object instance.
-pub fn parseObject(self: Archive, offset: u32) !*Object {
- var reader = self.file.?.reader();
+pub fn parseObject(self: Archive, allocator: *Allocator, arch: Arch, offset: u32) !*Object {
+ var reader = self.file.reader();
try reader.context.seekTo(offset + self.library_offset);
const object_header = try reader.readStruct(ar_hdr);
@@ -249,27 +235,27 @@ pub fn parseObject(self: Archive, offset: u32) !*Object {
return error.MalformedArchive;
}
- const object_name = try parseName(self.allocator, object_header, reader);
- defer self.allocator.free(object_name);
+ const object_name = try parseName(allocator, object_header, reader);
+ defer allocator.free(object_name);
- log.debug("extracting object '{s}' from archive '{s}'", .{ object_name, self.name.? });
+ log.debug("extracting object '{s}' from archive '{s}'", .{ object_name, self.name });
const name = name: {
var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
- const path = try std.os.realpath(self.name.?, &buffer);
- break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name });
+ const path = try std.os.realpath(self.name, &buffer);
+ break :name try std.fmt.allocPrint(allocator, "{s}({s})", .{ path, object_name });
};
- var object = try self.allocator.create(Object);
- errdefer self.allocator.destroy(object);
+ var object = try allocator.create(Object);
+ errdefer allocator.destroy(object);
object.* = .{
- .file = try fs.cwd().openFile(self.name.?, .{}),
+ .file = try fs.cwd().openFile(self.name, .{}),
.name = name,
.file_offset = @intCast(u32, try reader.context.getPos()),
.mtime = try self.header.?.date(),
};
- try object.parse(self.allocator, self.arch.?);
+ try object.parse(allocator, arch);
try reader.context.seekTo(0);
return object;
From e73777333dd66570ddacdb7de56a390de01b33c5 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 10:59:22 +0200
Subject: [PATCH 39/96] macho: don't store allocator in Dylib instance
instead pass it in as an arg to a function that requires it.
---
src/link/MachO.zig | 5 +-
src/link/MachO/Dylib.zig | 162 +++++++++++++++++++--------------------
2 files changed, 81 insertions(+), 86 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index c42bf550ef..aba45b6bd4 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -3350,7 +3350,7 @@ pub fn deinit(self: *MachO) void {
self.archives.deinit(self.base.allocator);
for (self.dylibs.items) |dylib| {
- dylib.deinit();
+ dylib.deinit(self.base.allocator);
self.base.allocator.destroy(dylib);
}
self.dylibs.deinit(self.base.allocator);
@@ -3381,6 +3381,9 @@ pub fn closeFiles(self: MachO) void {
for (self.archives.items) |archive| {
archive.file.close();
}
+ for (self.dylibs.items) |dylib| {
+ dylib.file.close();
+ }
}
fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig
index 0e7f95a3d5..de0d697db3 100644
--- a/src/link/MachO/Dylib.zig
+++ b/src/link/MachO/Dylib.zig
@@ -9,20 +9,18 @@ const macho = std.macho;
const math = std.math;
const mem = std.mem;
const fat = @import("fat.zig");
+const commands = @import("commands.zig");
const Allocator = mem.Allocator;
const Arch = std.Target.Cpu.Arch;
const LibStub = @import("../tapi.zig").LibStub;
+const LoadCommand = commands.LoadCommand;
const MachO = @import("../MachO.zig");
-usingnamespace @import("commands.zig");
+file: fs.File,
+name: []const u8,
-allocator: *Allocator,
-arch: ?Arch = null,
header: ?macho.mach_header_64 = null,
-file: ?fs.File = null,
-name: ?[]const u8 = null,
-syslibroot: ?[]const u8 = null,
ordinal: ?u16 = null,
@@ -61,7 +59,7 @@ pub const Id = struct {
};
}
- pub fn fromLoadCommand(allocator: *Allocator, lc: GenericCommandWithData(macho.dylib_command)) !Id {
+ pub fn fromLoadCommand(allocator: *Allocator, lc: commands.GenericCommandWithData(macho.dylib_command)) !Id {
const dylib = lc.inner.dylib;
const dylib_name = @ptrCast([*:0]const u8, lc.data[dylib.name - @sizeOf(macho.dylib_command) ..]);
const name = try allocator.dupe(u8, mem.spanZ(dylib_name));
@@ -164,25 +162,22 @@ pub fn createAndParseFromPath(
errdefer allocator.free(name);
dylib.* = .{
- .allocator = allocator,
- .arch = arch,
.name = name,
.file = file,
- .syslibroot = opts.syslibroot,
};
- dylib.parse() catch |err| switch (err) {
+ dylib.parse(allocator, arch) catch |err| switch (err) {
error.EndOfStream, error.NotDylib => {
try file.seekTo(0);
var lib_stub = LibStub.loadFromFile(allocator, file) catch {
- dylib.deinit();
+ dylib.deinit(allocator);
allocator.destroy(dylib);
return null;
};
defer lib_stub.deinit();
- try dylib.parseFromStub(lib_stub);
+ try dylib.parseFromStub(allocator, arch, lib_stub);
},
else => |e| return e,
};
@@ -195,7 +190,7 @@ pub fn createAndParseFromPath(
log.warn(" | dylib version: {}", .{dylib.id.?.current_version});
// TODO maybe this should be an error and facilitate auto-cleanup?
- dylib.deinit();
+ dylib.deinit(allocator);
allocator.destroy(dylib);
return null;
}
@@ -205,50 +200,41 @@ pub fn createAndParseFromPath(
defer dylibs.deinit();
try dylibs.append(dylib);
- try dylib.parseDependentLibs(&dylibs);
+ try dylib.parseDependentLibs(allocator, arch, &dylibs, opts.syslibroot);
return dylibs.toOwnedSlice();
}
-pub fn deinit(self: *Dylib) void {
+pub fn deinit(self: *Dylib, allocator: *Allocator) void {
for (self.load_commands.items) |*lc| {
- lc.deinit(self.allocator);
+ lc.deinit(allocator);
}
- self.load_commands.deinit(self.allocator);
+ self.load_commands.deinit(allocator);
for (self.symbols.keys()) |key| {
- self.allocator.free(key);
+ allocator.free(key);
}
- self.symbols.deinit(self.allocator);
+ self.symbols.deinit(allocator);
for (self.dependent_libs.items) |*id| {
- id.deinit(self.allocator);
- }
- self.dependent_libs.deinit(self.allocator);
-
- if (self.name) |name| {
- self.allocator.free(name);
+ id.deinit(allocator);
}
+ self.dependent_libs.deinit(allocator);
+ allocator.free(self.name);
if (self.id) |*id| {
- id.deinit(self.allocator);
+ id.deinit(allocator);
}
}
-pub fn closeFile(self: Dylib) void {
- if (self.file) |file| {
- file.close();
- }
-}
+pub fn parse(self: *Dylib, allocator: *Allocator, arch: Arch) !void {
+ log.debug("parsing shared library '{s}'", .{self.name});
-pub fn parse(self: *Dylib) !void {
- log.debug("parsing shared library '{s}'", .{self.name.?});
+ self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch);
- self.library_offset = try fat.getLibraryOffset(self.file.?.reader(), self.arch.?);
+ try self.file.seekTo(self.library_offset);
- try self.file.?.seekTo(self.library_offset);
-
- var reader = self.file.?.reader();
+ var reader = self.file.reader();
self.header = try reader.readStruct(macho.mach_header_64);
if (self.header.?.filetype != macho.MH_DYLIB) {
@@ -258,24 +244,24 @@ pub fn parse(self: *Dylib) !void {
const this_arch: Arch = try fat.decodeArch(self.header.?.cputype, true);
- if (this_arch != self.arch.?) {
- log.err("mismatched cpu architecture: expected {s}, found {s}", .{ self.arch.?, this_arch });
+ if (this_arch != arch) {
+ log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch });
return error.MismatchedCpuArchitecture;
}
- try self.readLoadCommands(reader);
- try self.parseId();
- try self.parseSymbols();
+ try self.readLoadCommands(allocator, reader);
+ try self.parseId(allocator);
+ try self.parseSymbols(allocator);
}
-fn readLoadCommands(self: *Dylib, reader: anytype) !void {
+fn readLoadCommands(self: *Dylib, allocator: *Allocator, reader: anytype) !void {
const should_lookup_reexports = self.header.?.flags & macho.MH_NO_REEXPORTED_DYLIBS == 0;
- try self.load_commands.ensureCapacity(self.allocator, self.header.?.ncmds);
+ try self.load_commands.ensureCapacity(allocator, self.header.?.ncmds);
var i: u16 = 0;
while (i < self.header.?.ncmds) : (i += 1) {
- var cmd = try LoadCommand.read(self.allocator, reader);
+ var cmd = try LoadCommand.read(allocator, reader);
switch (cmd.cmd()) {
macho.LC_SYMTAB => {
self.symtab_cmd_index = i;
@@ -289,8 +275,8 @@ fn readLoadCommands(self: *Dylib, reader: anytype) !void {
macho.LC_REEXPORT_DYLIB => {
if (should_lookup_reexports) {
// Parse install_name to dependent dylib.
- const id = try Id.fromLoadCommand(self.allocator, cmd.Dylib);
- try self.dependent_libs.append(self.allocator, id);
+ const id = try Id.fromLoadCommand(allocator, cmd.Dylib);
+ try self.dependent_libs.append(allocator, id);
}
},
else => {
@@ -301,27 +287,27 @@ fn readLoadCommands(self: *Dylib, reader: anytype) !void {
}
}
-fn parseId(self: *Dylib) !void {
+fn parseId(self: *Dylib, allocator: *Allocator) !void {
const index = self.id_cmd_index orelse {
log.debug("no LC_ID_DYLIB load command found; using hard-coded defaults...", .{});
- self.id = try Id.default(self.allocator, self.name.?);
+ self.id = try Id.default(allocator, self.name);
return;
};
- self.id = try Id.fromLoadCommand(self.allocator, self.load_commands.items[index].Dylib);
+ self.id = try Id.fromLoadCommand(allocator, self.load_commands.items[index].Dylib);
}
-fn parseSymbols(self: *Dylib) !void {
+fn parseSymbols(self: *Dylib, allocator: *Allocator) !void {
const index = self.symtab_cmd_index orelse return;
const symtab_cmd = self.load_commands.items[index].Symtab;
- var symtab = try self.allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms);
- defer self.allocator.free(symtab);
- _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff + self.library_offset);
+ var symtab = try allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms);
+ defer allocator.free(symtab);
+ _ = try self.file.preadAll(symtab, symtab_cmd.symoff + self.library_offset);
const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab));
- var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize);
- defer self.allocator.free(strtab);
- _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff + self.library_offset);
+ var strtab = try allocator.alloc(u8, symtab_cmd.strsize);
+ defer allocator.free(strtab);
+ _ = try self.file.preadAll(strtab, symtab_cmd.stroff + self.library_offset);
for (slice) |sym| {
const add_to_symtab = MachO.symbolIsExt(sym) and (MachO.symbolIsSect(sym) or MachO.symbolIsIndr(sym));
@@ -329,8 +315,8 @@ fn parseSymbols(self: *Dylib) !void {
if (!add_to_symtab) continue;
const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));
- const name = try self.allocator.dupe(u8, sym_name);
- try self.symbols.putNoClobber(self.allocator, name, {});
+ const name = try allocator.dupe(u8, sym_name);
+ try self.symbols.putNoClobber(allocator, name, {});
}
}
@@ -341,26 +327,26 @@ fn hasTarget(targets: []const []const u8, target: []const u8) bool {
return false;
}
-fn addObjCClassSymbols(self: *Dylib, sym_name: []const u8) !void {
+fn addObjCClassSymbols(self: *Dylib, allocator: *Allocator, sym_name: []const u8) !void {
const expanded = &[_][]const u8{
- try std.fmt.allocPrint(self.allocator, "_OBJC_CLASS_$_{s}", .{sym_name}),
- try std.fmt.allocPrint(self.allocator, "_OBJC_METACLASS_$_{s}", .{sym_name}),
+ try std.fmt.allocPrint(allocator, "_OBJC_CLASS_$_{s}", .{sym_name}),
+ try std.fmt.allocPrint(allocator, "_OBJC_METACLASS_$_{s}", .{sym_name}),
};
for (expanded) |sym| {
if (self.symbols.contains(sym)) continue;
- try self.symbols.putNoClobber(self.allocator, sym, .{});
+ try self.symbols.putNoClobber(allocator, sym, .{});
}
}
-pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
+pub fn parseFromStub(self: *Dylib, allocator: *Allocator, arch: Arch, lib_stub: LibStub) !void {
if (lib_stub.inner.len == 0) return error.EmptyStubFile;
- log.debug("parsing shared library from stub '{s}'", .{self.name.?});
+ log.debug("parsing shared library from stub '{s}'", .{self.name});
const umbrella_lib = lib_stub.inner[0];
- var id = try Id.default(self.allocator, umbrella_lib.install_name);
+ var id = try Id.default(allocator, umbrella_lib.install_name);
if (umbrella_lib.current_version) |version| {
try id.parseCurrentVersion(version);
}
@@ -369,13 +355,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
}
self.id = id;
- const target_string: []const u8 = switch (self.arch.?) {
+ const target_string: []const u8 = switch (arch) {
.aarch64 => "arm64-macos",
.x86_64 => "x86_64-macos",
else => unreachable,
};
- var umbrella_libs = std.StringHashMap(void).init(self.allocator);
+ var umbrella_libs = std.StringHashMap(void).init(allocator);
defer umbrella_libs.deinit();
for (lib_stub.inner) |stub, stub_index| {
@@ -395,13 +381,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
if (exp.symbols) |symbols| {
for (symbols) |sym_name| {
if (self.symbols.contains(sym_name)) continue;
- try self.symbols.putNoClobber(self.allocator, try self.allocator.dupe(u8, sym_name), {});
+ try self.symbols.putNoClobber(allocator, try allocator.dupe(u8, sym_name), {});
}
}
if (exp.objc_classes) |classes| {
for (classes) |sym_name| {
- try self.addObjCClassSymbols(sym_name);
+ try self.addObjCClassSymbols(allocator, sym_name);
}
}
}
@@ -414,13 +400,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
if (reexp.symbols) |symbols| {
for (symbols) |sym_name| {
if (self.symbols.contains(sym_name)) continue;
- try self.symbols.putNoClobber(self.allocator, try self.allocator.dupe(u8, sym_name), {});
+ try self.symbols.putNoClobber(allocator, try allocator.dupe(u8, sym_name), {});
}
}
if (reexp.objc_classes) |classes| {
for (classes) |sym_name| {
- try self.addObjCClassSymbols(sym_name);
+ try self.addObjCClassSymbols(allocator, sym_name);
}
}
}
@@ -428,7 +414,7 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
if (stub.objc_classes) |classes| {
for (classes) |sym_name| {
- try self.addObjCClassSymbols(sym_name);
+ try self.addObjCClassSymbols(allocator, sym_name);
}
}
}
@@ -451,15 +437,21 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
log.debug(" | {s}", .{lib});
- const dep_id = try Id.default(self.allocator, lib);
- try self.dependent_libs.append(self.allocator, dep_id);
+ const dep_id = try Id.default(allocator, lib);
+ try self.dependent_libs.append(allocator, dep_id);
}
}
}
}
}
-pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void {
+pub fn parseDependentLibs(
+ self: *Dylib,
+ allocator: *Allocator,
+ arch: Arch,
+ out: *std.ArrayList(*Dylib),
+ syslibroot: ?[]const u8,
+) !void {
outer: for (self.dependent_libs.items) |id| {
const has_ext = blk: {
const basename = fs.path.basename(id.name);
@@ -472,27 +464,27 @@ pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void {
} else id.name;
for (&[_][]const u8{ extension, ".tbd" }) |ext| {
- const with_ext = try std.fmt.allocPrint(self.allocator, "{s}{s}", .{
+ const with_ext = try std.fmt.allocPrint(allocator, "{s}{s}", .{
without_ext,
ext,
});
- defer self.allocator.free(with_ext);
+ defer allocator.free(with_ext);
- const full_path = if (self.syslibroot) |syslibroot|
- try fs.path.join(self.allocator, &.{ syslibroot, with_ext })
+ const full_path = if (syslibroot) |root|
+ try fs.path.join(allocator, &.{ root, with_ext })
else
with_ext;
- defer if (self.syslibroot) |_| self.allocator.free(full_path);
+ defer if (syslibroot) |_| allocator.free(full_path);
log.debug("trying dependency at fully resolved path {s}", .{full_path});
const dylibs = (try createAndParseFromPath(
- self.allocator,
- self.arch.?,
+ allocator,
+ arch,
full_path,
.{
.id = id,
- .syslibroot = self.syslibroot,
+ .syslibroot = syslibroot,
},
)) orelse {
continue;
From 06396ddd7d632704681bbd6278f18dcc2b6bf20c Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 15:01:37 +0200
Subject: [PATCH 40/96] macho: don't allocate Objects on the heap
instead, ownership is transferred to MachO. This makes Object
management align closer with data-oriented design.
---
src/link/MachO.zig | 32 ++++++++++----------
src/link/MachO/Archive.zig | 10 ++-----
src/link/MachO/Object.zig | 60 +++++++++++++++++---------------------
3 files changed, 46 insertions(+), 56 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index aba45b6bd4..e13fc9b91c 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -61,7 +61,7 @@ header_pad: u16 = 0x1000,
/// The absolute address of the entry point.
entry_addr: ?u64 = null,
-objects: std.ArrayListUnmanaged(*Object) = .{},
+objects: std.ArrayListUnmanaged(Object) = .{},
archives: std.ArrayListUnmanaged(*Archive) = .{},
dylibs: std.ArrayListUnmanaged(*Dylib) = .{},
@@ -990,13 +990,19 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
const arch = self.base.options.target.cpu.arch;
for (files) |file_name| {
const full_path = full_path: {
- var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
const path = try std.fs.realpath(file_name, &buffer);
break :full_path try self.base.allocator.dupe(u8, path);
};
+ const file = try fs.cwd().openFile(full_path, .{});
- if (try Object.createAndParseFromPath(self.base.allocator, arch, full_path)) |object| {
- try self.objects.append(self.base.allocator, object);
+ if (try Object.isObject(file)) {
+ const object = try self.objects.addOne(self.base.allocator);
+ object.* = .{
+ .name = full_path,
+ .file = file,
+ };
+ try object.parse(self.base.allocator, arch);
continue;
}
@@ -1993,7 +1999,7 @@ fn writeStubHelperCommon(self: *MachO) !void {
}
fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
- const object = self.objects.items[object_id];
+ const object = &self.objects.items[object_id];
log.debug("resolving symbols in '{s}'", .{object.name});
@@ -2228,13 +2234,10 @@ fn resolveSymbols(self: *MachO) !void {
};
assert(offsets.items.len > 0);
- const object = try archive.parseObject(
- self.base.allocator,
- self.base.options.target.cpu.arch,
- offsets.items[0],
- );
const object_id = @intCast(u16, self.objects.items.len);
- try self.objects.append(self.base.allocator, object);
+ const object = try self.objects.addOne(self.base.allocator);
+ object.* = try archive.extractObject(self.base.allocator, offsets.items[0]);
+ try object.parse(self.base.allocator, self.base.options.target.cpu.arch);
try self.resolveSymbolsInObject(object_id);
continue :loop;
@@ -2460,8 +2463,8 @@ fn resolveSymbols(self: *MachO) !void {
}
fn parseTextBlocks(self: *MachO) !void {
- for (self.objects.items) |object| {
- try object.parseTextBlocks(self.base.allocator, self);
+ for (self.objects.items) |*object, object_id| {
+ try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self);
}
}
@@ -3337,9 +3340,8 @@ pub fn deinit(self: *MachO) void {
self.locals_free_list.deinit(self.base.allocator);
self.symbol_resolver.deinit(self.base.allocator);
- for (self.objects.items) |object| {
+ for (self.objects.items) |*object| {
object.deinit(self.base.allocator);
- self.base.allocator.destroy(object);
}
self.objects.deinit(self.base.allocator);
diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig
index 228e8f74b9..23d5d259ef 100644
--- a/src/link/MachO/Archive.zig
+++ b/src/link/MachO/Archive.zig
@@ -223,8 +223,7 @@ fn parseTableOfContents(self: *Archive, allocator: *Allocator, reader: anytype)
}
}
-/// Caller owns the Object instance.
-pub fn parseObject(self: Archive, allocator: *Allocator, arch: Arch, offset: u32) !*Object {
+pub fn extractObject(self: Archive, allocator: *Allocator, offset: u32) !Object {
var reader = self.file.reader();
try reader.context.seekTo(offset + self.library_offset);
@@ -246,16 +245,13 @@ pub fn parseObject(self: Archive, allocator: *Allocator, arch: Arch, offset: u32
break :name try std.fmt.allocPrint(allocator, "{s}({s})", .{ path, object_name });
};
- var object = try allocator.create(Object);
- errdefer allocator.destroy(object);
-
- object.* = .{
+ var object = Object{
.file = try fs.cwd().openFile(self.name, .{}),
.name = name,
.file_offset = @intCast(u32, try reader.context.getPos()),
.mtime = try self.header.?.date(),
};
- try object.parse(allocator, arch);
+
try reader.context.seekTo(0);
return object;
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 1250f015ed..6a1bf8fd57 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -127,36 +127,6 @@ const DebugInfo = struct {
}
};
-pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8) !?*Object {
- const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
- error.FileNotFound => return null,
- else => |e| return e,
- };
- errdefer file.close();
-
- const object = try allocator.create(Object);
- errdefer allocator.destroy(object);
-
- const name = try allocator.dupe(u8, path);
- errdefer allocator.free(name);
-
- object.* = .{
- .name = name,
- .file = file,
- };
-
- object.parse(allocator, arch) catch |err| switch (err) {
- error.EndOfStream, error.NotObject => {
- object.deinit(allocator);
- allocator.destroy(object);
- return null;
- },
- else => |e| return e,
- };
-
- return object;
-}
-
pub fn deinit(self: *Object, allocator: *Allocator) void {
for (self.load_commands.items) |*lc| {
lc.deinit(allocator);
@@ -184,6 +154,22 @@ pub fn deinit(self: *Object, allocator: *Allocator) void {
}
}
+pub fn isObject(file: fs.File) !bool {
+ const reader = file.reader();
+ const is_object = blk: {
+ if (reader.readStruct(macho.mach_header_64)) |header| {
+ break :blk header.filetype == macho.MH_OBJECT;
+ } else |err| {
+ switch (err) {
+ error.EndOfStream => break :blk false,
+ else => |e| return e,
+ }
+ }
+ };
+ try file.seekTo(0);
+ return is_object;
+}
+
pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
var reader = self.file.reader();
if (self.file_offset) |offset| {
@@ -481,7 +467,12 @@ const TextBlockParser = struct {
}
};
-pub fn parseTextBlocks(self: *Object, allocator: *Allocator, macho_file: *MachO) !void {
+pub fn parseTextBlocks(
+ self: *Object,
+ allocator: *Allocator,
+ object_id: u16,
+ macho_file: *MachO,
+) !void {
const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
log.debug("analysing {s}", .{self.name});
@@ -668,13 +659,14 @@ pub fn parseTextBlocks(self: *Object, allocator: *Allocator, macho_file: *MachO)
if (is_ext) {
if (macho_file.symbol_resolver.get(sym.n_strx)) |resolv| {
assert(resolv.where == .global);
- const global_object = macho_file.objects.items[resolv.file];
- if (global_object != self) {
+ if (resolv.file != object_id) {
log.debug("deduping definition of {s} in {s}", .{
macho_file.getString(sym.n_strx),
self.name,
});
- log.debug(" already defined in {s}", .{global_object.name});
+ log.debug(" already defined in {s}", .{
+ macho_file.objects.items[resolv.file].name,
+ });
continue;
}
}
From f023cdad7ca676977d9b5abd3d38677779aab211 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 15:33:39 +0200
Subject: [PATCH 41/96] macho: don't allocate Archives on the heap
instead, transfer ownership directly to MachO struct.
---
src/link/MachO.zig | 28 +++++++++++----
src/link/MachO/Archive.zig | 72 +++++++++++++-------------------------
src/link/MachO/Object.zig | 27 ++++++--------
3 files changed, 56 insertions(+), 71 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index e13fc9b91c..544073f3e1 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -62,7 +62,7 @@ header_pad: u16 = 0x1000,
entry_addr: ?u64 = null,
objects: std.ArrayListUnmanaged(Object) = .{},
-archives: std.ArrayListUnmanaged(*Archive) = .{},
+archives: std.ArrayListUnmanaged(Archive) = .{},
dylibs: std.ArrayListUnmanaged(*Dylib) = .{},
next_dylib_ordinal: u16 = 1,
@@ -1006,8 +1006,13 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
continue;
}
- if (try Archive.createAndParseFromPath(self.base.allocator, arch, full_path)) |archive| {
- try self.archives.append(self.base.allocator, archive);
+ if (try Archive.isArchive(file, arch)) {
+ const archive = try self.archives.addOne(self.base.allocator);
+ archive.* = .{
+ .name = full_path,
+ .file = file,
+ };
+ try archive.parse(self.base.allocator, arch);
continue;
}
@@ -1019,6 +1024,8 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
continue;
}
+ self.base.allocator.free(full_path);
+ file.close();
log.warn("unknown filetype for positional input file: '{s}'", .{file_name});
}
}
@@ -1026,6 +1033,8 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !void {
const arch = self.base.options.target.cpu.arch;
for (libs) |lib| {
+ const file = try fs.cwd().openFile(lib, .{});
+
if (try Dylib.createAndParseFromPath(self.base.allocator, arch, lib, .{
.syslibroot = syslibroot,
})) |dylibs| {
@@ -1034,11 +1043,17 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !v
continue;
}
- if (try Archive.createAndParseFromPath(self.base.allocator, arch, lib)) |archive| {
- try self.archives.append(self.base.allocator, archive);
+ if (try Archive.isArchive(file, arch)) {
+ const archive = try self.archives.addOne(self.base.allocator);
+ archive.* = .{
+ .name = try self.base.allocator.dupe(u8, lib),
+ .file = file,
+ };
+ try archive.parse(self.base.allocator, arch);
continue;
}
+ file.close();
log.warn("unknown filetype for a library: '{s}'", .{lib});
}
}
@@ -3345,9 +3360,8 @@ pub fn deinit(self: *MachO) void {
}
self.objects.deinit(self.base.allocator);
- for (self.archives.items) |archive| {
+ for (self.archives.items) |*archive| {
archive.deinit(self.base.allocator);
- self.base.allocator.destroy(archive);
}
self.archives.deinit(self.base.allocator);
diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig
index 23d5d259ef..0ac34d90fc 100644
--- a/src/link/MachO/Archive.zig
+++ b/src/link/MachO/Archive.zig
@@ -93,36 +93,6 @@ const ar_hdr = extern struct {
}
};
-pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8) !?*Archive {
- const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
- error.FileNotFound => return null,
- else => |e| return e,
- };
- errdefer file.close();
-
- const archive = try allocator.create(Archive);
- errdefer allocator.destroy(archive);
-
- const name = try allocator.dupe(u8, path);
- errdefer allocator.free(name);
-
- archive.* = .{
- .name = name,
- .file = file,
- };
-
- archive.parse(allocator, arch) catch |err| switch (err) {
- error.EndOfStream, error.NotArchive => {
- archive.deinit(allocator);
- allocator.destroy(archive);
- return null;
- },
- else => |e| return e,
- };
-
- return archive;
-}
-
pub fn deinit(self: *Archive, allocator: *Allocator) void {
for (self.toc.keys()) |*key| {
allocator.free(key.*);
@@ -134,32 +104,40 @@ pub fn deinit(self: *Archive, allocator: *Allocator) void {
allocator.free(self.name);
}
+pub fn isArchive(file: fs.File, arch: Arch) !bool {
+ const Internal = struct {
+ fn isArchive(reader: anytype, a: Arch) !bool {
+ const offset = try fat.getLibraryOffset(reader, a);
+ try reader.context.seekTo(offset);
+ const magic = try reader.readBytesNoEof(SARMAG);
+ if (!mem.eql(u8, &magic, ARMAG)) return false;
+ const header = try reader.readStruct(ar_hdr);
+ return mem.eql(u8, &header.ar_fmag, ARFMAG);
+ }
+ };
+ const is_archive = if (Internal.isArchive(file.reader(), arch)) |res|
+ res
+ else |err| switch (err) {
+ error.EndOfStream => false,
+ error.MismatchedCpuArchitecture => true, // TODO maybe this check should be done differently?
+ else => |e| return e,
+ };
+ try file.seekTo(0);
+ return is_archive;
+}
+
pub fn parse(self: *Archive, allocator: *Allocator, arch: Arch) !void {
self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch);
-
try self.file.seekTo(self.library_offset);
-
- var reader = self.file.reader();
+ const reader = self.file.reader();
const magic = try reader.readBytesNoEof(SARMAG);
-
- if (!mem.eql(u8, &magic, ARMAG)) {
- log.debug("invalid magic: expected '{s}', found '{s}'", .{ ARMAG, magic });
- return error.NotArchive;
- }
-
self.header = try reader.readStruct(ar_hdr);
-
- if (!mem.eql(u8, &self.header.?.ar_fmag, ARFMAG)) {
- log.debug("invalid header delimiter: expected '{s}', found '{s}'", .{ ARFMAG, self.header.?.ar_fmag });
- return error.NotArchive;
- }
-
var embedded_name = try parseName(allocator, self.header.?, reader);
- log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name });
defer allocator.free(embedded_name);
- try self.parseTableOfContents(allocator, reader);
+ log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name });
+ try self.parseTableOfContents(allocator, reader);
try reader.context.seekTo(0);
}
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 6a1bf8fd57..ff397ed7b0 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -155,17 +155,18 @@ pub fn deinit(self: *Object, allocator: *Allocator) void {
}
pub fn isObject(file: fs.File) !bool {
- const reader = file.reader();
- const is_object = blk: {
- if (reader.readStruct(macho.mach_header_64)) |header| {
- break :blk header.filetype == macho.MH_OBJECT;
- } else |err| {
- switch (err) {
- error.EndOfStream => break :blk false,
- else => |e| return e,
- }
+ const Internal = struct {
+ fn isObject(reader: anytype) !bool {
+ const header = try reader.readStruct(macho.mach_header_64);
+ return header.filetype == macho.MH_OBJECT;
}
};
+ const is_object = if (Internal.isObject(file.reader())) |res|
+ res
+ else |err| switch (err) {
+ error.EndOfStream => false,
+ else => |e| return e,
+ };
try file.seekTo(0);
return is_object;
}
@@ -175,14 +176,7 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
if (self.file_offset) |offset| {
try reader.context.seekTo(offset);
}
-
const header = try reader.readStruct(macho.mach_header_64);
-
- if (header.filetype != macho.MH_OBJECT) {
- log.debug("invalid filetype: expected 0x{x}, found 0x{x}", .{ macho.MH_OBJECT, header.filetype });
- return error.NotObject;
- }
-
const this_arch: Arch = switch (header.cputype) {
macho.CPU_TYPE_ARM64 => .aarch64,
macho.CPU_TYPE_X86_64 => .x86_64,
@@ -195,7 +189,6 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch });
return error.MismatchedCpuArchitecture;
}
-
self.header = header;
try self.readLoadCommands(allocator, reader);
From 0b15ba8334bc03b59a975e579aac01a6b3fc2109 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 16:01:02 +0200
Subject: [PATCH 42/96] macho: don't allocate Dylib on the heap
instead, immediately transfer ownership to MachO struct. Also, revert
back to try-ok-fail parsing approach of objects, archives, and dylibs.
It seems easier to try and fail than check if the file *is* of a
certain type given that a dylib may be a stub and parsing yaml
twice in a row seems very wasteful.
Hint for the future: if we optimise yaml/TAPI parsing, this approach
may be rethought!
---
src/link/MachO.zig | 47 ++++++++---------------------
src/link/MachO/Archive.zig | 62 +++++++++++++++++++++++---------------
src/link/MachO/Dylib.zig | 14 +++------
src/link/MachO/Object.zig | 47 ++++++++++++++++++++---------
4 files changed, 89 insertions(+), 81 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 544073f3e1..3eb34cf415 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -63,7 +63,7 @@ entry_addr: ?u64 = null,
objects: std.ArrayListUnmanaged(Object) = .{},
archives: std.ArrayListUnmanaged(Archive) = .{},
-dylibs: std.ArrayListUnmanaged(*Dylib) = .{},
+dylibs: std.ArrayListUnmanaged(Dylib) = .{},
next_dylib_ordinal: u16 = 1,
@@ -994,25 +994,15 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
const path = try std.fs.realpath(file_name, &buffer);
break :full_path try self.base.allocator.dupe(u8, path);
};
- const file = try fs.cwd().openFile(full_path, .{});
+ defer self.base.allocator.free(full_path);
- if (try Object.isObject(file)) {
- const object = try self.objects.addOne(self.base.allocator);
- object.* = .{
- .name = full_path,
- .file = file,
- };
- try object.parse(self.base.allocator, arch);
+ if (try Object.createAndParseFromPath(self.base.allocator, arch, full_path)) |object| {
+ try self.objects.append(self.base.allocator, object);
continue;
}
- if (try Archive.isArchive(file, arch)) {
- const archive = try self.archives.addOne(self.base.allocator);
- archive.* = .{
- .name = full_path,
- .file = file,
- };
- try archive.parse(self.base.allocator, arch);
+ if (try Archive.createAndParseFromPath(self.base.allocator, arch, full_path)) |archive| {
+ try self.archives.append(self.base.allocator, archive);
continue;
}
@@ -1024,8 +1014,6 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
continue;
}
- self.base.allocator.free(full_path);
- file.close();
log.warn("unknown filetype for positional input file: '{s}'", .{file_name});
}
}
@@ -1033,8 +1021,6 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !void {
const arch = self.base.options.target.cpu.arch;
for (libs) |lib| {
- const file = try fs.cwd().openFile(lib, .{});
-
if (try Dylib.createAndParseFromPath(self.base.allocator, arch, lib, .{
.syslibroot = syslibroot,
})) |dylibs| {
@@ -1043,17 +1029,11 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !v
continue;
}
- if (try Archive.isArchive(file, arch)) {
- const archive = try self.archives.addOne(self.base.allocator);
- archive.* = .{
- .name = try self.base.allocator.dupe(u8, lib),
- .file = file,
- };
- try archive.parse(self.base.allocator, arch);
+ if (try Archive.createAndParseFromPath(self.base.allocator, arch, lib)) |archive| {
+ try self.archives.append(self.base.allocator, archive);
continue;
}
- file.close();
log.warn("unknown filetype for a library: '{s}'", .{lib});
}
}
@@ -2351,17 +2331,17 @@ fn resolveSymbols(self: *MachO) !void {
});
}
- var referenced = std.AutoHashMap(*Dylib, void).init(self.base.allocator);
+ var referenced = std.AutoHashMap(u16, void).init(self.base.allocator);
defer referenced.deinit();
loop: for (self.undefs.items) |sym| {
if (symbolIsNull(sym)) continue;
const sym_name = self.getString(sym.n_strx);
- for (self.dylibs.items) |dylib| {
+ for (self.dylibs.items) |*dylib, id| {
if (!dylib.symbols.contains(sym_name)) continue;
- if (!referenced.contains(dylib)) {
+ if (!referenced.contains(@intCast(u16, id))) {
// Add LC_LOAD_DYLIB load command for each referenced dylib/stub.
dylib.ordinal = self.next_dylib_ordinal;
const dylib_id = dylib.id orelse unreachable;
@@ -2375,7 +2355,7 @@ fn resolveSymbols(self: *MachO) !void {
errdefer dylib_cmd.deinit(self.base.allocator);
try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
self.next_dylib_ordinal += 1;
- try referenced.putNoClobber(dylib, {});
+ try referenced.putNoClobber(@intCast(u16, id), {});
}
const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable;
@@ -3365,9 +3345,8 @@ pub fn deinit(self: *MachO) void {
}
self.archives.deinit(self.base.allocator);
- for (self.dylibs.items) |dylib| {
+ for (self.dylibs.items) |*dylib| {
dylib.deinit(self.base.allocator);
- self.base.allocator.destroy(dylib);
}
self.dylibs.deinit(self.base.allocator);
diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig
index 0ac34d90fc..f02ad0cfa9 100644
--- a/src/link/MachO/Archive.zig
+++ b/src/link/MachO/Archive.zig
@@ -104,38 +104,52 @@ pub fn deinit(self: *Archive, allocator: *Allocator) void {
allocator.free(self.name);
}
-pub fn isArchive(file: fs.File, arch: Arch) !bool {
- const Internal = struct {
- fn isArchive(reader: anytype, a: Arch) !bool {
- const offset = try fat.getLibraryOffset(reader, a);
- try reader.context.seekTo(offset);
- const magic = try reader.readBytesNoEof(SARMAG);
- if (!mem.eql(u8, &magic, ARMAG)) return false;
- const header = try reader.readStruct(ar_hdr);
- return mem.eql(u8, &header.ar_fmag, ARFMAG);
- }
- };
- const is_archive = if (Internal.isArchive(file.reader(), arch)) |res|
- res
- else |err| switch (err) {
- error.EndOfStream => false,
- error.MismatchedCpuArchitecture => true, // TODO maybe this check should be done differently?
+pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8) !?Archive {
+ const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
+ error.FileNotFound => return null,
else => |e| return e,
};
- try file.seekTo(0);
- return is_archive;
+ errdefer file.close();
+
+ const name = try allocator.dupe(u8, path);
+ errdefer allocator.free(name);
+
+ var archive = Archive{
+ .name = name,
+ .file = file,
+ };
+
+ archive.parse(allocator, arch) catch |err| switch (err) {
+ error.EndOfStream, error.NotArchive => {
+ archive.deinit(allocator);
+ return null;
+ },
+ else => |e| return e,
+ };
+
+ return archive;
}
pub fn parse(self: *Archive, allocator: *Allocator, arch: Arch) !void {
- self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch);
- try self.file.seekTo(self.library_offset);
const reader = self.file.reader();
- const magic = try reader.readBytesNoEof(SARMAG);
- self.header = try reader.readStruct(ar_hdr);
- var embedded_name = try parseName(allocator, self.header.?, reader);
- defer allocator.free(embedded_name);
+ self.library_offset = try fat.getLibraryOffset(reader, arch);
+ try self.file.seekTo(self.library_offset);
+ const magic = try reader.readBytesNoEof(SARMAG);
+ if (!mem.eql(u8, &magic, ARMAG)) {
+ log.debug("invalid magic: expected '{s}', found '{s}'", .{ ARMAG, magic });
+ return error.NotArchive;
+ }
+
+ self.header = try reader.readStruct(ar_hdr);
+ if (!mem.eql(u8, &self.header.?.ar_fmag, ARFMAG)) {
+ log.debug("invalid header delimiter: expected '{s}', found '{s}'", .{ ARFMAG, self.header.?.ar_fmag });
+ return error.NotArchive;
+ }
+
+ var embedded_name = try parseName(allocator, self.header.?, reader);
log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name });
+ defer allocator.free(embedded_name);
try self.parseTableOfContents(allocator, reader);
try reader.context.seekTo(0);
diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig
index de0d697db3..7b2f94ba67 100644
--- a/src/link/MachO/Dylib.zig
+++ b/src/link/MachO/Dylib.zig
@@ -148,20 +148,17 @@ pub fn createAndParseFromPath(
arch: Arch,
path: []const u8,
opts: CreateOpts,
-) Error!?[]*Dylib {
+) Error!?[]Dylib {
const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
error.FileNotFound => return null,
else => |e| return e,
};
errdefer file.close();
- const dylib = try allocator.create(Dylib);
- errdefer allocator.destroy(dylib);
-
const name = try allocator.dupe(u8, path);
errdefer allocator.free(name);
- dylib.* = .{
+ var dylib = Dylib{
.name = name,
.file = file,
};
@@ -172,7 +169,6 @@ pub fn createAndParseFromPath(
var lib_stub = LibStub.loadFromFile(allocator, file) catch {
dylib.deinit(allocator);
- allocator.destroy(dylib);
return null;
};
defer lib_stub.deinit();
@@ -191,12 +187,11 @@ pub fn createAndParseFromPath(
// TODO maybe this should be an error and facilitate auto-cleanup?
dylib.deinit(allocator);
- allocator.destroy(dylib);
return null;
}
}
- var dylibs = std.ArrayList(*Dylib).init(allocator);
+ var dylibs = std.ArrayList(Dylib).init(allocator);
defer dylibs.deinit();
try dylibs.append(dylib);
@@ -449,7 +444,7 @@ pub fn parseDependentLibs(
self: *Dylib,
allocator: *Allocator,
arch: Arch,
- out: *std.ArrayList(*Dylib),
+ out: *std.ArrayList(Dylib),
syslibroot: ?[]const u8,
) !void {
outer: for (self.dependent_libs.items) |id| {
@@ -489,6 +484,7 @@ pub fn parseDependentLibs(
)) orelse {
continue;
};
+ defer allocator.free(dylibs);
try out.appendSlice(dylibs);
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index ff397ed7b0..04071a1cdb 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -154,29 +154,47 @@ pub fn deinit(self: *Object, allocator: *Allocator) void {
}
}
-pub fn isObject(file: fs.File) !bool {
- const Internal = struct {
- fn isObject(reader: anytype) !bool {
- const header = try reader.readStruct(macho.mach_header_64);
- return header.filetype == macho.MH_OBJECT;
- }
- };
- const is_object = if (Internal.isObject(file.reader())) |res|
- res
- else |err| switch (err) {
- error.EndOfStream => false,
+pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8) !?Object {
+ const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
+ error.FileNotFound => return null,
else => |e| return e,
};
- try file.seekTo(0);
- return is_object;
+ errdefer file.close();
+
+ const name = try allocator.dupe(u8, path);
+ errdefer allocator.free(name);
+
+ var object = Object{
+ .name = name,
+ .file = file,
+ };
+
+ object.parse(allocator, arch) catch |err| switch (err) {
+ error.EndOfStream, error.NotObject => {
+ object.deinit(allocator);
+ return null;
+ },
+ else => |e| return e,
+ };
+
+ return object;
}
pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
- var reader = self.file.reader();
+ const reader = self.file.reader();
if (self.file_offset) |offset| {
try reader.context.seekTo(offset);
}
+
const header = try reader.readStruct(macho.mach_header_64);
+ if (header.filetype != macho.MH_OBJECT) {
+ log.debug("invalid filetype: expected 0x{x}, found 0x{x}", .{
+ macho.MH_OBJECT,
+ header.filetype,
+ });
+ return error.NotObject;
+ }
+
const this_arch: Arch = switch (header.cputype) {
macho.CPU_TYPE_ARM64 => .aarch64,
macho.CPU_TYPE_X86_64 => .x86_64,
@@ -189,6 +207,7 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch });
return error.MismatchedCpuArchitecture;
}
+
self.header = header;
try self.readLoadCommands(allocator, reader);
From 2e30bf23aa4515682038bc69ffc0b7d06b734be9 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 16:06:50 +0200
Subject: [PATCH 43/96] macho: cleanup extracting objects from archives
---
src/link/MachO.zig | 7 +++++--
src/link/MachO/Archive.zig | 5 +++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 3eb34cf415..d4a30040fc 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -2231,8 +2231,11 @@ fn resolveSymbols(self: *MachO) !void {
const object_id = @intCast(u16, self.objects.items.len);
const object = try self.objects.addOne(self.base.allocator);
- object.* = try archive.extractObject(self.base.allocator, offsets.items[0]);
- try object.parse(self.base.allocator, self.base.options.target.cpu.arch);
+ object.* = try archive.parseObject(
+ self.base.allocator,
+ self.base.options.target.cpu.arch,
+ offsets.items[0],
+ );
try self.resolveSymbolsInObject(object_id);
continue :loop;
diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig
index f02ad0cfa9..6959dbac89 100644
--- a/src/link/MachO/Archive.zig
+++ b/src/link/MachO/Archive.zig
@@ -215,8 +215,8 @@ fn parseTableOfContents(self: *Archive, allocator: *Allocator, reader: anytype)
}
}
-pub fn extractObject(self: Archive, allocator: *Allocator, offset: u32) !Object {
- var reader = self.file.reader();
+pub fn parseObject(self: Archive, allocator: *Allocator, arch: Arch, offset: u32) !Object {
+ const reader = self.file.reader();
try reader.context.seekTo(offset + self.library_offset);
const object_header = try reader.readStruct(ar_hdr);
@@ -244,6 +244,7 @@ pub fn extractObject(self: Archive, allocator: *Allocator, offset: u32) !Object
.mtime = try self.header.?.date(),
};
+ try object.parse(allocator, arch);
try reader.context.seekTo(0);
return object;
From d19fdf09ae1686ae5f7eb5f2386dd6de1f441db5 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 21:31:06 +0200
Subject: [PATCH 44/96] macho: make CodeSignature accept allocator as param
instead storing it within the struct.
---
src/link/MachO.zig | 7 +++++--
src/link/MachO/CodeSignature.zig | 33 +++++++++++---------------------
2 files changed, 16 insertions(+), 24 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index d4a30040fc..fab655dc21 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -5239,14 +5239,17 @@ fn writeCodeSignature(self: *MachO) !void {
const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
const code_sig_cmd = self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData;
- var code_sig = CodeSignature.init(self.base.allocator, self.page_size);
- defer code_sig.deinit();
+ var code_sig: CodeSignature = .{};
+ defer code_sig.deinit(self.base.allocator);
+
try code_sig.calcAdhocSignature(
+ self.base.allocator,
self.base.file.?,
self.base.options.emit.?.sub_path,
text_segment.inner,
code_sig_cmd,
self.base.options.output_mode,
+ self.page_size,
);
var buffer = try self.base.allocator.alloc(u8, code_sig.size());
diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig
index d0dd47be92..293de32def 100644
--- a/src/link/MachO/CodeSignature.zig
+++ b/src/link/MachO/CodeSignature.zig
@@ -46,8 +46,6 @@ const CodeDirectory = struct {
}
};
-allocator: *Allocator,
-
/// Code signature blob header.
inner: macho.SuperBlob = .{
.magic = macho.CSMAGIC_EMBEDDED_SIGNATURE,
@@ -58,24 +56,15 @@ inner: macho.SuperBlob = .{
/// CodeDirectory header which holds the hash of the binary.
cdir: ?CodeDirectory = null,
-/// Page size is dependent on the target cpu architecture.
-/// For x86_64 that's 4KB, whereas for aarch64, that's 16KB.
-page_size: u16,
-
-pub fn init(allocator: *Allocator, page_size: u16) CodeSignature {
- return .{
- .allocator = allocator,
- .page_size = page_size,
- };
-}
-
pub fn calcAdhocSignature(
self: *CodeSignature,
+ allocator: *Allocator,
file: fs.File,
id: []const u8,
text_segment: macho.segment_command_64,
code_sig_cmd: macho.linkedit_data_command,
output_mode: std.builtin.OutputMode,
+ page_size: u16,
) !void {
const execSegBase: u64 = text_segment.fileoff;
const execSegLimit: u64 = text_segment.filesize;
@@ -95,7 +84,7 @@ pub fn calcAdhocSignature(
.hashSize = hash_size,
.hashType = macho.CS_HASHTYPE_SHA256,
.platform = 0,
- .pageSize = @truncate(u8, std.math.log2(self.page_size)),
+ .pageSize = @truncate(u8, std.math.log2(page_size)),
.spare2 = 0,
.scatterOffset = 0,
.teamOffset = 0,
@@ -107,13 +96,13 @@ pub fn calcAdhocSignature(
},
};
- const total_pages = mem.alignForward(file_size, self.page_size) / self.page_size;
+ const total_pages = mem.alignForward(file_size, page_size) / page_size;
var hash: [hash_size]u8 = undefined;
- var buffer = try self.allocator.alloc(u8, self.page_size);
- defer self.allocator.free(buffer);
+ var buffer = try allocator.alloc(u8, page_size);
+ defer allocator.free(buffer);
- try cdir.data.ensureCapacity(self.allocator, total_pages * hash_size + id.len + 1);
+ try cdir.data.ensureCapacity(allocator, total_pages * hash_size + id.len + 1);
// 1. Save the identifier and update offsets
cdir.inner.identOffset = cdir.inner.length;
@@ -126,8 +115,8 @@ pub fn calcAdhocSignature(
cdir.inner.hashOffset = cdir.inner.identOffset + @intCast(u32, id.len) + 1;
var i: usize = 0;
while (i < total_pages) : (i += 1) {
- const fstart = i * self.page_size;
- const fsize = if (fstart + self.page_size > file_size) file_size - fstart else self.page_size;
+ const fstart = i * page_size;
+ const fsize = if (fstart + page_size > file_size) file_size - fstart else page_size;
const len = try file.preadAll(buffer, fstart);
assert(fsize <= len);
@@ -156,9 +145,9 @@ pub fn write(self: CodeSignature, writer: anytype) !void {
try self.cdir.?.write(writer);
}
-pub fn deinit(self: *CodeSignature) void {
+pub fn deinit(self: *CodeSignature, allocator: *Allocator) void {
if (self.cdir) |*cdir| {
- cdir.data.deinit(self.allocator);
+ cdir.data.deinit(allocator);
}
}
From 58bc713c171e74b3c4f8283636561e6521edbeef Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 21:37:46 +0200
Subject: [PATCH 45/96] macho: make Trie accept allocator as a param
instead of storing it as a member of Trie struct.
---
src/link/MachO.zig | 16 ++++++++--------
src/link/MachO/Trie.zig | 30 ++++++++++++------------------
2 files changed, 20 insertions(+), 26 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index fab655dc21..9f9a0d5157 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -3126,8 +3126,8 @@ fn writeLazyBindInfoTableZld(self: *MachO) !void {
}
fn writeExportInfoZld(self: *MachO) !void {
- var trie = Trie.init(self.base.allocator);
- defer trie.deinit();
+ var trie: Trie = .{};
+ defer trie.deinit(self.base.allocator);
const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
const base_address = text_segment.inner.vmaddr;
@@ -3139,14 +3139,14 @@ fn writeExportInfoZld(self: *MachO) !void {
const sym_name = self.getString(sym.n_strx);
log.debug(" | putting '{s}' defined at 0x{x}", .{ sym_name, sym.n_value });
- try trie.put(.{
+ try trie.put(self.base.allocator, .{
.name = sym_name,
.vmaddr_offset = sym.n_value - base_address,
.export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
});
}
- try trie.finalize();
+ try trie.finalize(self.base.allocator);
var buffer = try self.base.allocator.alloc(u8, @intCast(usize, trie.size));
defer self.base.allocator.free(buffer);
@@ -5269,8 +5269,8 @@ fn writeExportInfo(self: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
- var trie = Trie.init(self.base.allocator);
- defer trie.deinit();
+ var trie: Trie = .{};
+ defer trie.deinit(self.base.allocator);
const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
const base_address = text_segment.inner.vmaddr;
@@ -5282,14 +5282,14 @@ fn writeExportInfo(self: *MachO) !void {
const sym_name = self.getString(sym.n_strx);
log.debug(" | putting '{s}' defined at 0x{x}", .{ sym_name, sym.n_value });
- try trie.put(.{
+ try trie.put(self.base.allocator, .{
.name = sym_name,
.vmaddr_offset = sym.n_value - base_address,
.export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
});
}
+ try trie.finalize(self.base.allocator);
- try trie.finalize();
var buffer = try self.base.allocator.alloc(u8, @intCast(usize, trie.size));
defer self.base.allocator.free(buffer);
var stream = std.io.fixedBufferStream(buffer);
diff --git a/src/link/MachO/Trie.zig b/src/link/MachO/Trie.zig
index 8aa2262bff..6f66f73a32 100644
--- a/src/link/MachO/Trie.zig
+++ b/src/link/MachO/Trie.zig
@@ -273,8 +273,6 @@ pub const Node = struct {
/// The root node of the trie.
root: ?*Node = null,
-allocator: *Allocator,
-
/// If you want to access nodes ordered in DFS fashion,
/// you should call `finalize` first since the nodes
/// in this container are not guaranteed to not be stale
@@ -294,10 +292,6 @@ node_count: usize = 0,
trie_dirty: bool = true,
-pub fn init(allocator: *Allocator) Trie {
- return .{ .allocator = allocator };
-}
-
/// Export symbol that is to be placed in the trie.
pub const ExportSymbol = struct {
/// Name of the symbol.
@@ -314,9 +308,9 @@ pub const ExportSymbol = struct {
/// Insert a symbol into the trie, updating the prefixes in the process.
/// This operation may change the layout of the trie by splicing edges in
/// certain circumstances.
-pub fn put(self: *Trie, symbol: ExportSymbol) !void {
- try self.createRoot();
- const node = try self.root.?.put(self.allocator, symbol.name);
+pub fn put(self: *Trie, allocator: *Allocator, symbol: ExportSymbol) !void {
+ try self.createRoot(allocator);
+ const node = try self.root.?.put(allocator, symbol.name);
node.terminal_info = .{
.vmaddr_offset = symbol.vmaddr_offset,
.export_flags = symbol.export_flags,
@@ -328,13 +322,13 @@ pub fn put(self: *Trie, symbol: ExportSymbol) !void {
/// This step performs multiple passes through the trie ensuring
/// there are no gaps after every `Node` is ULEB128 encoded.
/// Call this method before trying to `write` the trie to a byte stream.
-pub fn finalize(self: *Trie) !void {
+pub fn finalize(self: *Trie, allocator: *Allocator) !void {
if (!self.trie_dirty) return;
self.ordered_nodes.shrinkRetainingCapacity(0);
- try self.ordered_nodes.ensureCapacity(self.allocator, self.node_count);
+ try self.ordered_nodes.ensureCapacity(allocator, self.node_count);
- var fifo = std.fifo.LinearFifo(*Node, .Dynamic).init(self.allocator);
+ var fifo = std.fifo.LinearFifo(*Node, .Dynamic).init(allocator);
defer fifo.deinit();
try fifo.writeItem(self.root.?);
@@ -383,17 +377,17 @@ pub fn write(self: Trie, writer: anytype) !u64 {
return counting_writer.bytes_written;
}
-pub fn deinit(self: *Trie) void {
+pub fn deinit(self: *Trie, allocator: *Allocator) void {
if (self.root) |root| {
- root.deinit(self.allocator);
- self.allocator.destroy(root);
+ root.deinit(allocator);
+ allocator.destroy(root);
}
- self.ordered_nodes.deinit(self.allocator);
+ self.ordered_nodes.deinit(allocator);
}
-fn createRoot(self: *Trie) !void {
+fn createRoot(self: *Trie, allocator: *Allocator) !void {
if (self.root == null) {
- const root = try self.allocator.create(Node);
+ const root = try allocator.create(Node);
root.* = .{ .base = self };
self.root = root;
self.node_count += 1;
From 0ce56f93052184e5c0f627f6af1ff4d34bb3110a Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sat, 31 Jul 2021 22:01:26 +0200
Subject: [PATCH 46/96] macho: fix Trie and CodeSignature unit tests
after the cleanup.
---
src/link/MachO/CodeSignature.zig | 4 +--
src/link/MachO/Trie.zig | 50 ++++++++++++++++----------------
2 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig
index 293de32def..6dd7e556b5 100644
--- a/src/link/MachO/CodeSignature.zig
+++ b/src/link/MachO/CodeSignature.zig
@@ -163,8 +163,8 @@ fn writeBlobIndex(tt: u32, offset: u32, writer: anytype) !void {
}
test "CodeSignature header" {
- var code_sig = CodeSignature.init(testing.allocator, 0x1000);
- defer code_sig.deinit();
+ var code_sig: CodeSignature = .{};
+ defer code_sig.deinit(testing.allocator);
var buffer: [@sizeOf(macho.SuperBlob)]u8 = undefined;
var stream = std.io.fixedBufferStream(&buffer);
diff --git a/src/link/MachO/Trie.zig b/src/link/MachO/Trie.zig
index 6f66f73a32..ab3a97eb33 100644
--- a/src/link/MachO/Trie.zig
+++ b/src/link/MachO/Trie.zig
@@ -361,9 +361,9 @@ const ReadError = error{
};
/// Parse the trie from a byte stream.
-pub fn read(self: *Trie, reader: anytype) ReadError!usize {
- try self.createRoot();
- return self.root.?.read(self.allocator, reader);
+pub fn read(self: *Trie, allocator: *Allocator, reader: anytype) ReadError!usize {
+ try self.createRoot(allocator);
+ return self.root.?.read(allocator, reader);
}
/// Write the trie to a byte stream.
@@ -396,13 +396,13 @@ fn createRoot(self: *Trie, allocator: *Allocator) !void {
test "Trie node count" {
var gpa = testing.allocator;
- var trie = Trie.init(gpa);
- defer trie.deinit();
+ var trie: Trie = .{};
+ defer trie.deinit(gpa);
try testing.expectEqual(trie.node_count, 0);
try testing.expect(trie.root == null);
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "_main",
.vmaddr_offset = 0,
.export_flags = 0,
@@ -410,14 +410,14 @@ test "Trie node count" {
try testing.expectEqual(trie.node_count, 2);
// Inserting the same node shouldn't update the trie.
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "_main",
.vmaddr_offset = 0,
.export_flags = 0,
});
try testing.expectEqual(trie.node_count, 2);
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "__mh_execute_header",
.vmaddr_offset = 0x1000,
.export_flags = 0,
@@ -425,13 +425,13 @@ test "Trie node count" {
try testing.expectEqual(trie.node_count, 4);
// Inserting the same node shouldn't update the trie.
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "__mh_execute_header",
.vmaddr_offset = 0x1000,
.export_flags = 0,
});
try testing.expectEqual(trie.node_count, 4);
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "_main",
.vmaddr_offset = 0,
.export_flags = 0,
@@ -441,11 +441,11 @@ test "Trie node count" {
test "Trie basic" {
var gpa = testing.allocator;
- var trie = Trie.init(gpa);
- defer trie.deinit();
+ var trie: Trie = .{};
+ defer trie.deinit(gpa);
// root --- _st ---> node
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "_st",
.vmaddr_offset = 0,
.export_flags = 0,
@@ -455,7 +455,7 @@ test "Trie basic" {
{
// root --- _st ---> node --- art ---> node
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "_start",
.vmaddr_offset = 0,
.export_flags = 0,
@@ -471,7 +471,7 @@ test "Trie basic" {
// root --- _ ---> node --- st ---> node --- art ---> node
// |
// | --- main ---> node
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "_main",
.vmaddr_offset = 0,
.export_flags = 0,
@@ -491,22 +491,22 @@ test "Trie basic" {
test "write Trie to a byte stream" {
var gpa = testing.allocator;
- var trie = Trie.init(gpa);
- defer trie.deinit();
+ var trie: Trie = .{};
+ defer trie.deinit(gpa);
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "__mh_execute_header",
.vmaddr_offset = 0,
.export_flags = 0,
});
- try trie.put(.{
+ try trie.put(gpa, .{
.name = "_main",
.vmaddr_offset = 0x1000,
.export_flags = 0,
});
- try trie.finalize();
- try trie.finalize(); // Finalizing mulitple times is a nop subsequently unless we add new nodes.
+ try trie.finalize(gpa);
+ try trie.finalize(gpa); // Finalizing mulitple times is a nop subsequently unless we add new nodes.
const exp_buffer = [_]u8{
0x0, 0x1, // node root
@@ -551,13 +551,13 @@ test "parse Trie from byte stream" {
};
var in_stream = std.io.fixedBufferStream(&in_buffer);
- var trie = Trie.init(gpa);
- defer trie.deinit();
- const nread = try trie.read(in_stream.reader());
+ var trie: Trie = .{};
+ defer trie.deinit(gpa);
+ const nread = try trie.read(gpa, in_stream.reader());
try testing.expect(nread == in_buffer.len);
- try trie.finalize();
+ try trie.finalize(gpa);
var out_buffer = try gpa.alloc(u8, trie.size);
defer gpa.free(out_buffer);
From 0d09c6aed8811ded3e6dcb62fa9539d3795cf97b Mon Sep 17 00:00:00 2001
From: joachimschmidt557
Date: Sat, 31 Jul 2021 12:52:35 +0200
Subject: [PATCH 47/96] stage2 ARM: fix stack alignment
Acording to the AAPCS32, the stack alignment at public interfaces
should be 8, not 4.
---
src/codegen.zig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/codegen.zig b/src/codegen.zig
index 77672e82b0..8c56ab4431 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -4916,7 +4916,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
}
result.stack_byte_count = nsaa;
- result.stack_align = 4;
+ result.stack_align = 8;
},
else => return self.fail("TODO implement function parameters for {} on arm", .{cc}),
}
From 5589edf45ce20b5b6d893b1a5488007981322550 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=BDiga=20=C5=BDeljko?=
Date: Sat, 31 Jul 2021 10:58:42 +0200
Subject: [PATCH 48/96] fix help for ast-check command
---
src/main.zig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/main.zig b/src/main.zig
index 5b0c9edc8f..8c1964fc43 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -3886,6 +3886,8 @@ const usage_ast_check =
\\ -h, --help Print this help and exit
\\ --color [auto|off|on] Enable or disable colored error messages
\\ -t (debug option) Output ZIR in text form to stdout
+ \\
+ \\
;
pub fn cmdAstCheck(
From 5667ab7dcd2e367f3e1ac337eabadd64d9d850ad Mon Sep 17 00:00:00 2001
From: Luuk de Gram
Date: Fri, 30 Jul 2021 20:35:30 +0200
Subject: [PATCH 49/96] wasm: Implement wrapping operands, add opcodes to
wasm.zig
- Some opcodes have the incorrect value set in std.
- Some opcodes were missing and have now been added to std.
- Adding wrapping operands for add,sub and mul.
- Implement intCast which either extends or shortens the type.
---
lib/std/wasm.zig | 10 ++++++++--
src/codegen/wasm.zig | 29 ++++++++++++++++++++++++++++-
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/lib/std/wasm.zig b/lib/std/wasm.zig
index 8922b3c83e..aebbb3b163 100644
--- a/lib/std/wasm.zig
+++ b/lib/std/wasm.zig
@@ -162,8 +162,14 @@ pub const Opcode = enum(u8) {
i32_wrap_i64 = 0xA7,
i32_trunc_f32_s = 0xA8,
i32_trunc_f32_u = 0xA9,
- i32_trunc_f64_s = 0xB0,
- i32_trunc_f64_u = 0xB1,
+ i32_trunc_f64_s = 0xAA,
+ i32_trunc_f64_u = 0xAB,
+ i64_extend_i32_s = 0xAC,
+ i64_extend_i32_u = 0xAD,
+ i64_trunc_f32_s = 0xAE,
+ i64_trunc_f32_u = 0xAF,
+ i64_trunc_f64_s = 0xB0,
+ i64_trunc_f64_u = 0xB1,
f32_convert_i32_s = 0xB2,
f32_convert_i32_u = 0xB3,
f32_convert_i64_s = 0xB4,
diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig
index 2f1632e0fc..1a23a8fa35 100644
--- a/src/codegen/wasm.zig
+++ b/src/codegen/wasm.zig
@@ -591,7 +591,7 @@ pub const Context = struct {
.ErrorSet,
=> wasm.Valtype.i32,
.Struct, .ErrorUnion => unreachable, // Multi typed, must be handled individually.
- else => self.fail("TODO - Wasm valtype for type '{s}'", .{ty.zigTypeTag()}),
+ else => |tag| self.fail("TODO - Wasm valtype for type '{s}'", .{tag}),
};
}
@@ -800,8 +800,11 @@ pub const Context = struct {
const air_tags = self.air.instructions.items(.tag);
return switch (air_tags[inst]) {
.add => self.airBinOp(inst, .add),
+ .addwrap => self.airBinOp(inst, .add),
.sub => self.airBinOp(inst, .sub),
+ .subwrap => self.airBinOp(inst, .sub),
.mul => self.airBinOp(inst, .mul),
+ .mulwrap => self.airBinOp(inst, .mul),
.div => self.airBinOp(inst, .div),
.bit_and => self.airBinOp(inst, .@"and"),
.bit_or => self.airBinOp(inst, .@"or"),
@@ -826,6 +829,7 @@ pub const Context = struct {
.cond_br => self.airCondBr(inst),
.constant => unreachable,
.dbg_stmt => WValue.none,
+ .intcast => self.airIntcast(inst),
.is_err => self.airIsErr(inst, .i32_ne),
.is_non_err => self.airIsErr(inst, .i32_eq),
.load => self.airLoad(inst),
@@ -1494,4 +1498,27 @@ pub const Context = struct {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
return self.resolveInst(ty_op.operand);
}
+
+ fn airIntcast(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const ty = self.air.getRefType(ty_op.ty);
+ const operand = self.resolveInst(ty_op.operand);
+ const ref_ty = self.air.typeOf(ty_op.operand);
+ const ref_info = ref_ty.intInfo(self.target);
+ const op_bits = ref_info.bits;
+ const wanted_bits = ty.intInfo(self.target).bits;
+
+ try self.emitWValue(operand);
+ if (op_bits > 32 and wanted_bits <= 32) {
+ try self.code.append(wasm.opcode(.i32_wrap_i64));
+ } else if (op_bits <= 32 and wanted_bits > 32) {
+ try self.code.append(wasm.opcode(switch (ref_info.signedness) {
+ .signed => .i64_extend_i32_s,
+ .unsigned => .i64_extend_i32_u,
+ }));
+ }
+
+ // other cases are no-op
+ return .none;
+ }
};
From e58976542b096df6cbb2088b6c7a690d7b95c50a Mon Sep 17 00:00:00 2001
From: Luuk de Gram
Date: Fri, 30 Jul 2021 21:05:30 +0200
Subject: [PATCH 50/96] wasm: Test cases for wrap+intcast instructions
---
test/stage2/wasm.zig | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/test/stage2/wasm.zig b/test/stage2/wasm.zig
index f746be99d2..b0099c392c 100644
--- a/test/stage2/wasm.zig
+++ b/test/stage2/wasm.zig
@@ -113,6 +113,13 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "25\n");
+ case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i32 = 2147483647;
+ \\ return i +% 1;
+ \\}
+ , "-2147483648\n");
+
case.addCompareOutput(
\\pub export fn _start() u32 {
\\ var i: u32 = 5;
@@ -133,6 +140,13 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "15\n");
+ case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i32 = -2147483648;
+ \\ return i -% 1;
+ \\}
+ , "2147483647\n");
+
case.addCompareOutput(
\\pub export fn _start() u32 {
\\ var i: u32 = 5;
@@ -157,6 +171,13 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "350\n");
+ case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i32 = 2147483647;
+ \\ return i *% 2;
+ \\}
+ , "-2\n");
+
case.addCompareOutput(
\\pub export fn _start() u32 {
\\ var i: u32 = 352;
@@ -612,4 +633,15 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "42\n");
}
+
+ {
+ var case = ctx.exe("wasm integer widening", wasi);
+
+ case.addCompareOutput(
+ \\pub export fn _start() u64 {
+ \\ var x: u32 = 5;
+ \\ return x;
+ \\}
+ , "5\n");
+ }
}
From 61de59e121ebd5ad2a8af871ddb1d785c3694481 Mon Sep 17 00:00:00 2001
From: Luuk de Gram
Date: Sat, 31 Jul 2021 16:01:37 +0200
Subject: [PATCH 51/96] wasm: Implement optionals
This uses the same approach as error unions,
meaning it's a `WValue` with its tag set to `multi_value`.
The initial index of the multi_value will contain the null-tag, used to check if the value
is null or not. The other values will be the payload.
To support the `.?` shorthand syntax, we save the result from checking the null-tag
into a new local, which can then be loaded later in the block to either hit `unreachable` or
set the actual payload value.
Currently, it seems `.?` and `orelse unreachable` results in different AIR structure.
TODO: Is this expected?
---
src/codegen/wasm.zig | 106 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 104 insertions(+), 2 deletions(-)
diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig
index 1a23a8fa35..5178c43c00 100644
--- a/src/codegen/wasm.zig
+++ b/src/codegen/wasm.zig
@@ -590,7 +590,7 @@ pub const Context = struct {
.Pointer,
.ErrorSet,
=> wasm.Valtype.i32,
- .Struct, .ErrorUnion => unreachable, // Multi typed, must be handled individually.
+ .Struct, .ErrorUnion, .Optional => unreachable, // Multi typed, must be handled individually.
else => |tag| self.fail("TODO - Wasm valtype for type '{s}'", .{tag}),
};
}
@@ -663,6 +663,23 @@ pub const Context = struct {
.count = 2,
} };
},
+ .Optional => {
+ var opt_buf: Type.Payload.ElemType = undefined;
+ const child_type = ty.optionalChild(&opt_buf);
+ if (ty.isPtrLikeOptional()) {
+ return self.fail("TODO: wasm optional pointer", .{});
+ }
+
+ try self.locals.ensureCapacity(self.gpa, self.locals.items.len + 2);
+ self.locals.appendAssumeCapacity(wasm.valtype(.i32)); // optional 'tag' for null-checking is always i32
+ self.locals.appendAssumeCapacity(try self.genValtype(child_type));
+ self.local_index += 2;
+
+ return WValue{ .multi_value = .{
+ .index = initial_index,
+ .count = 2,
+ } };
+ },
else => {
const valtype = try self.genValtype(ty);
try self.locals.append(self.gpa, valtype);
@@ -830,8 +847,15 @@ pub const Context = struct {
.constant => unreachable,
.dbg_stmt => WValue.none,
.intcast => self.airIntcast(inst),
+
.is_err => self.airIsErr(inst, .i32_ne),
.is_non_err => self.airIsErr(inst, .i32_eq),
+
+ .is_null => self.airIsNull(inst, .i32_ne),
+ .is_non_null => self.airIsNull(inst, .i32_eq),
+ .is_null_ptr => self.airIsNull(inst, .i32_ne),
+ .is_non_null_ptr => self.airIsNull(inst, .i32_eq),
+
.load => self.airLoad(inst),
.loop => self.airLoop(inst),
.not => self.airNot(inst),
@@ -840,8 +864,13 @@ pub const Context = struct {
.struct_field_ptr => self.airStructFieldPtr(inst),
.switch_br => self.airSwitchBr(inst),
.unreach => self.airUnreachable(inst),
+ .wrap_optional => self.airWrapOptional(inst),
+
.unwrap_errunion_payload => self.airUnwrapErrUnionPayload(inst),
.wrap_errunion_payload => self.airWrapErrUnionPayload(inst),
+
+ .optional_payload => self.airOptionalPayload(inst),
+ .optional_payload_ptr => self.airOptionalPayload(inst),
else => |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
};
}
@@ -926,6 +955,22 @@ pub const Context = struct {
try leb.writeULEB128(writer, multi_value.index + i - 1);
}
},
+ .local => {
+ // This can occur when we wrap a single value into a multi-value,
+ // such as wrapping a non-optional value into an optional.
+ // This means we must zero the null-tag, and set the payload.
+ assert(multi_value.count == 2);
+ // set null-tag
+ try writer.writeByte(wasm.opcode(.i32_const));
+ try leb.writeULEB128(writer, @as(u32, 0));
+ try writer.writeByte(wasm.opcode(.local_set));
+ try leb.writeULEB128(writer, multi_value.index);
+
+ // set payload
+ try self.emitWValue(rhs);
+ try writer.writeByte(wasm.opcode(.local_set));
+ try leb.writeULEB128(writer, multi_value.index + 1);
+ },
else => unreachable,
},
.local => |local| {
@@ -1088,6 +1133,31 @@ pub const Context = struct {
try self.emitConstant(data, payload_type);
}
},
+ .Optional => {
+ var buf: Type.Payload.ElemType = undefined;
+ const payload_type = ty.optionalChild(&buf);
+ if (ty.isPtrLikeOptional()) {
+ return self.fail("Wasm TODO: emitConstant for optional pointer", .{});
+ }
+
+ // When constant has value 'null', set is_null local to '1'
+ // and payload to '0'
+ if (val.tag() == .null_value) {
+ try writer.writeByte(wasm.opcode(.i32_const));
+ try leb.writeILEB128(writer, @as(i32, 1));
+
+ const opcode: wasm.Opcode = buildOpcode(.{
+ .op = .@"const",
+ .valtype1 = try self.typeToValtype(payload_type),
+ });
+ try writer.writeByte(wasm.opcode(opcode));
+ try leb.writeULEB128(writer, @as(u32, 0));
+ } else {
+ try writer.writeByte(wasm.opcode(.i32_const));
+ try leb.writeILEB128(writer, @as(i32, 0));
+ try self.emitConstant(val, payload_type);
+ }
+ },
else => |zig_type| return self.fail("Wasm TODO: emitConstant for zigTypeTag {s}", .{zig_type}),
}
}
@@ -1188,7 +1258,6 @@ pub const Context = struct {
const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];
const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
const writer = self.code.writer();
-
// TODO: Handle death instructions for then and else body
// insert blocks at the position of `offset` so
@@ -1521,4 +1590,37 @@ pub const Context = struct {
// other cases are no-op
return .none;
}
+
+ fn airIsNull(self: *Context, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!WValue {
+ const un_op = self.air.instructions.items(.data)[inst].un_op;
+ const operand = self.resolveInst(un_op);
+ // const offset = self.code.items.len;
+ const writer = self.code.writer();
+
+ // load the null value which is positioned at multi_value's index
+ try self.emitWValue(.{ .local = operand.multi_value.index });
+ // Compare the null value with '0'
+ try writer.writeByte(wasm.opcode(.i32_const));
+ try leb.writeILEB128(writer, @as(i32, 0));
+
+ try writer.writeByte(@enumToInt(opcode));
+
+ // we save the result in a new local
+ const local = try self.allocLocal(Type.initTag(.i32));
+ try writer.writeByte(wasm.opcode(.local_set));
+ try leb.writeULEB128(writer, local.local);
+
+ return local;
+ }
+
+ fn airOptionalPayload(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const operand = self.resolveInst(ty_op.operand);
+ return WValue{ .local = operand.multi_value.index + 1 };
+ }
+
+ fn airWrapOptional(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ return self.resolveInst(ty_op.operand);
+ }
};
From a861b7d160737acb60913d2ff7ed316f19af9066 Mon Sep 17 00:00:00 2001
From: Luuk de Gram
Date: Sat, 31 Jul 2021 16:39:48 +0200
Subject: [PATCH 52/96] wasm: Test cases for optionals
---
test/stage2/wasm.zig | 54 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/test/stage2/wasm.zig b/test/stage2/wasm.zig
index b0099c392c..a9f7984893 100644
--- a/test/stage2/wasm.zig
+++ b/test/stage2/wasm.zig
@@ -644,4 +644,58 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "5\n");
}
+
+ {
+ var case = ctx.exe("wasm optionals", wasi);
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var x: ?u32 = 5;
+ \\ var y: u32 = 0;
+ \\ if (x) |val| {
+ \\ y = val;
+ \\ }
+ \\ return y;
+ \\}
+ , "5\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var x: ?u32 = null;
+ \\ var y: u32 = 0;
+ \\ if (x) |val| {
+ \\ y = val;
+ \\ }
+ \\ return y;
+ \\}
+ , "0\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var x: ?u32 = 5;
+ \\ return x.?;
+ \\}
+ , "5\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var x: u32 = 5;
+ \\ var y: ?u32 = x;
+ \\ return y.?;
+ \\}
+ , "5\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var val: ?u32 = 5;
+ \\ while (val) |*v| {
+ \\ v.* -= 1;
+ \\ if (v.* == 2) {
+ \\ val = null;
+ \\ }
+ \\ }
+ \\ return 0;
+ \\}
+ , "0\n");
+ }
}
From 32069d23301f624a7cdd4f1763c2de24f7a234ab Mon Sep 17 00:00:00 2001
From: Meghan
Date: Sun, 1 Aug 2021 02:42:05 -0700
Subject: [PATCH 53/96] langref- fix use after block error code
---
doc/langref.html.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 4efa7d0e3c..ce07d6494a 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -3422,10 +3422,11 @@ test "call foo" {
Blocks are used to limit the scope of variable declarations:
- {#code_begin|test_err|unused local variable#}
+ {#code_begin|test_err|use of undeclared identifier 'x'#}
test "access variable after block scope" {
{
var x: i32 = 1;
+ _ = x;
}
x += 1;
}
From 7e52a096dbace546cae89ab691741ecca45f28ce Mon Sep 17 00:00:00 2001
From: Meghan
Date: Sun, 1 Aug 2021 02:42:48 -0700
Subject: [PATCH 54/96] langref- fix packed struct error code
---
doc/langref.html.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index ce07d6494a..386fe9f41a 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -2846,7 +2846,7 @@ test "pointer to non-bit-aligned field" {
Zig should correctly understand the alignment of fields. However there is
a bug:
- {#code_begin|test_err#}
+ {#code_begin|test_err|expected type '*u32', found '*align(1) u32'#}
const S = packed struct {
a: u32,
b: u32,
@@ -2855,6 +2855,7 @@ test "overaligned pointer to packed struct" {
var foo: S align(4) = undefined;
const ptr: *align(4) S = &foo;
const ptr_to_b: *u32 = &ptr.b;
+ _ = ptr_to_b;
}
{#code_end#}
When this bug is fixed, the above test in the documentation will unexpectedly pass, which will
From d794f4cd2a1e62334ba6b413864bc33bae6d41ef Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sun, 1 Aug 2021 18:05:07 +0200
Subject: [PATCH 55/96] macho: add runaway section id when sorting sections
---
src/link/MachO.zig | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 9f9a0d5157..61b2ff888c 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -1471,6 +1471,7 @@ fn sortSections(self: *MachO) !void {
&self.cstring_section_index,
&self.ustring_section_index,
&self.text_const_section_index,
+ &self.objc_methlist_section_index,
&self.objc_methname_section_index,
&self.objc_methtype_section_index,
&self.objc_classname_section_index,
From 6e139d124be92cfddef01adaa166ce09691cd5cc Mon Sep 17 00:00:00 2001
From: Luuk de Gram
Date: Sun, 1 Aug 2021 11:05:15 +0200
Subject: [PATCH 56/96] wasm: Resolve feedback (wrapping arbitrary int sizes)
- This ensures we honor the user's integer size when performing wrapping operations.
- Also, instead of using ensureCapacity, we now use ensureUnusedCapacity.
---
src/codegen/wasm.zig | 68 ++++++++++++++++++++++++++++++++++++++++----
test/stage2/wasm.zig | 42 +++++++++++++++++++++++++++
2 files changed, 104 insertions(+), 6 deletions(-)
diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig
index 5178c43c00..e21645d1ee 100644
--- a/src/codegen/wasm.zig
+++ b/src/codegen/wasm.zig
@@ -634,7 +634,7 @@ pub const Context = struct {
// for each struct field, generate a local
const struct_data: *Module.Struct = ty.castTag(.@"struct").?.data;
const fields_len = @intCast(u32, struct_data.fields.count());
- try self.locals.ensureCapacity(self.gpa, self.locals.items.len + fields_len);
+ try self.locals.ensureUnusedCapacity(self.gpa, fields_len);
for (struct_data.fields.values()) |*value| {
const val_type = try self.genValtype(value.ty);
self.locals.appendAssumeCapacity(val_type);
@@ -653,7 +653,7 @@ pub const Context = struct {
// The first local is also used to find the index of the error and payload.
//
// TODO: Add support where the payload is a type that contains multiple locals such as a struct.
- try self.locals.ensureCapacity(self.gpa, self.locals.items.len + 2);
+ try self.locals.ensureUnusedCapacity(self.gpa, 2);
self.locals.appendAssumeCapacity(wasm.valtype(.i32)); // error values are always i32
self.locals.appendAssumeCapacity(val_type);
self.local_index += 2;
@@ -670,7 +670,7 @@ pub const Context = struct {
return self.fail("TODO: wasm optional pointer", .{});
}
- try self.locals.ensureCapacity(self.gpa, self.locals.items.len + 2);
+ try self.locals.ensureUnusedCapacity(self.gpa, 2);
self.locals.appendAssumeCapacity(wasm.valtype(.i32)); // optional 'tag' for null-checking is always i32
self.locals.appendAssumeCapacity(try self.genValtype(child_type));
self.local_index += 2;
@@ -817,11 +817,11 @@ pub const Context = struct {
const air_tags = self.air.instructions.items(.tag);
return switch (air_tags[inst]) {
.add => self.airBinOp(inst, .add),
- .addwrap => self.airBinOp(inst, .add),
+ .addwrap => self.airWrapBinOp(inst, .add),
.sub => self.airBinOp(inst, .sub),
- .subwrap => self.airBinOp(inst, .sub),
+ .subwrap => self.airWrapBinOp(inst, .sub),
.mul => self.airBinOp(inst, .mul),
- .mulwrap => self.airBinOp(inst, .mul),
+ .mulwrap => self.airWrapBinOp(inst, .mul),
.div => self.airBinOp(inst, .div),
.bit_and => self.airBinOp(inst, .@"and"),
.bit_or => self.airBinOp(inst, .@"or"),
@@ -1021,6 +1021,62 @@ pub const Context = struct {
return WValue{ .code_offset = offset };
}
+ fn airWrapBinOp(self: *Context, inst: Air.Inst.Index, op: Op) InnerError!WValue {
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const lhs = self.resolveInst(bin_op.lhs);
+ const rhs = self.resolveInst(bin_op.rhs);
+
+ // it's possible for both lhs and/or rhs to return an offset as well,
+ // in which case we return the first offset occurance we find.
+ const offset = blk: {
+ if (lhs == .code_offset) break :blk lhs.code_offset;
+ if (rhs == .code_offset) break :blk rhs.code_offset;
+ break :blk self.code.items.len;
+ };
+
+ try self.emitWValue(lhs);
+ try self.emitWValue(rhs);
+
+ const bin_ty = self.air.typeOf(bin_op.lhs);
+ const opcode: wasm.Opcode = buildOpcode(.{
+ .op = op,
+ .valtype1 = try self.typeToValtype(bin_ty),
+ .signedness = if (bin_ty.isSignedInt()) .signed else .unsigned,
+ });
+ try self.code.append(wasm.opcode(opcode));
+
+ const int_info = bin_ty.intInfo(self.target);
+ const bitsize = int_info.bits;
+ const is_signed = int_info.signedness == .signed;
+ // if target type bitsize is x < 32 and 32 > x < 64, we perform
+ // result & ((1< 64) {
+ return self.fail("TODO wasm: Integer wrapping for bitsizes larger than 64", .{});
+ }
+
+ return WValue{ .code_offset = offset };
+ }
+
fn emitConstant(self: *Context, val: Value, ty: Type) InnerError!void {
const writer = self.code.writer();
switch (ty.zigTypeTag()) {
diff --git a/test/stage2/wasm.zig b/test/stage2/wasm.zig
index a9f7984893..ab400f0a53 100644
--- a/test/stage2/wasm.zig
+++ b/test/stage2/wasm.zig
@@ -120,6 +120,20 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "-2147483648\n");
+ case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i4 = 7;
+ \\ return i +% 1;
+ \\}
+ , "0\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var i: u8 = 255;
+ \\ return i +% 1;
+ \\}
+ , "0\n");
+
case.addCompareOutput(
\\pub export fn _start() u32 {
\\ var i: u32 = 5;
@@ -147,6 +161,20 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "2147483647\n");
+ case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i7 = -64;
+ \\ return i -% 1;
+ \\}
+ , "63\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var i: u4 = 0;
+ \\ return i -% 1;
+ \\}
+ , "15\n");
+
case.addCompareOutput(
\\pub export fn _start() u32 {
\\ var i: u32 = 5;
@@ -178,6 +206,20 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "-2\n");
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var i: u3 = 3;
+ \\ return i *% 3;
+ \\}
+ , "1\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i4 = 3;
+ \\ return i *% 3;
+ \\}
+ , "1\n");
+
case.addCompareOutput(
\\pub export fn _start() u32 {
\\ var i: u32 = 352;
From 6ae0825e7f87fc9b73a4b968964196b0e164f062 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 1 Aug 2021 12:27:22 -0700
Subject: [PATCH 57/96] Sema: implement comptime variables
Sema now properly handles alloc_inferred and alloc_inferred_mut ZIR
instructions inside a comptime execution context. In this case it
creates Decl objects and points to them with the new `decl_ref_mut`
Value Tag. `storePtr` is updated to mutate such Decl types and values.
In this case it destroys the old arena and makes a new one, preventing
memory growth during comptime code execution.
Additionally:
* Fix `storePtr` to emit a compile error for a pointer comptime-known
to be undefined.
* Fix `storePtr` to emit runtime instructions for all the cases that a
pointer is comptime-known but does not support comptime
dereferencing, such as `@intToPtr` on a hard-coded address, or an
extern function.
* Fix `ret_coerce` not coercing inside inline function call context.
---
src/Sema.zig | 225 +++++++++++++++++++++++++---------------
src/value.zig | 45 +++++---
test/behavior.zig | 1 +
test/behavior/basic.zig | 9 ++
test/behavior/bool.zig | 44 ++++++++
test/behavior/misc.zig | 64 ------------
6 files changed, 226 insertions(+), 162 deletions(-)
create mode 100644 test/behavior/basic.zig
diff --git a/src/Sema.zig b/src/Sema.zig
index 4fa59c4744..5ad590be6a 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -154,9 +154,6 @@ pub fn analyzeBody(
// We use a while(true) loop here to avoid a redundant way of breaking out of
// the loop. The only way to break out of the loop is with a `noreturn`
// instruction.
- // TODO: As an optimization, make sure the codegen for these switch prongs
- // directly jump to the next one, rather than detouring through the loop
- // continue expression. Related: https://github.com/ziglang/zig/issues/8220
var i: usize = 0;
while (true) {
const inst = body[i];
@@ -391,7 +388,7 @@ pub fn analyzeBody(
.condbr => return sema.zirCondbr(block, inst),
.@"break" => return sema.zirBreak(block, inst),
.compile_error => return sema.zirCompileError(block, inst),
- .ret_coerce => return sema.zirRetCoerce(block, inst, true),
+ .ret_coerce => return sema.zirRetCoerce(block, inst),
.ret_node => return sema.zirRetNode(block, inst),
.ret_err_value => return sema.zirRetErrValue(block, inst),
.@"unreachable" => return sema.zirUnreachable(block, inst),
@@ -1396,14 +1393,19 @@ fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp
const var_type = try sema.resolveType(block, ty_src, inst_data.operand);
const ptr_type = try Module.simplePtrType(sema.arena, var_type, true, .One);
- const val_payload = try sema.arena.create(Value.Payload.ComptimeAlloc);
- val_payload.* = .{
- .data = .{
- .runtime_index = block.runtime_index,
- .val = undefined, // astgen guarantees there will be a store before the first load
- },
- };
- return sema.addConstant(ptr_type, Value.initPayload(&val_payload.base));
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
+ const decl = try anon_decl.finish(
+ try var_type.copy(anon_decl.arena()),
+ // AstGen guarantees there will be a store before the first load, so we put a value
+ // here indicating there is no valid value.
+ Value.initTag(.unreachable_value),
+ );
+ try sema.mod.declareDeclDependency(sema.owner_decl, decl);
+ return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{
+ .runtime_index = block.runtime_index,
+ .decl = decl,
+ }));
}
fn zirAllocInferredComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -1450,16 +1452,23 @@ fn zirAllocInferred(
const src_node = sema.code.instructions.items(.data)[inst].node;
const src: LazySrcLoc = .{ .node_offset = src_node };
+ sema.src = src;
- const val_payload = try sema.arena.create(Value.Payload.InferredAlloc);
- val_payload.* = .{
- .data = .{},
- };
- // `Module.constInst` does not add the instruction to the block because it is
+ if (block.is_comptime) {
+ return sema.addConstant(
+ inferred_alloc_ty,
+ try Value.Tag.inferred_alloc_comptime.create(sema.arena, undefined),
+ );
+ }
+
+ // `Sema.addConstant` does not add the instruction to the block because it is
// not needed in the case of constant values. However here, we plan to "downgrade"
// to a normal instruction when we hit `resolve_inferred_alloc`. So we append
// to the block even though it is currently a `.constant`.
- const result = try sema.addConstant(inferred_alloc_ty, Value.initPayload(&val_payload.base));
+ const result = try sema.addConstant(
+ inferred_alloc_ty,
+ try Value.Tag.inferred_alloc.create(sema.arena, .{}),
+ );
try sema.requireFunctionBlock(block, src);
try block.instructions.append(sema.gpa, Air.refToIndex(result).?);
return result;
@@ -1475,25 +1484,47 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
const ptr_inst = Air.refToIndex(ptr).?;
assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);
const air_datas = sema.air_instructions.items(.data);
- const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
- const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
- const peer_inst_list = inferred_alloc.data.stored_inst_list.items;
- const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list);
+ const value_index = air_datas[ptr_inst].ty_pl.payload;
+ const ptr_val = sema.air_values.items[value_index];
const var_is_mut = switch (sema.typeOf(ptr).tag()) {
.inferred_alloc_const => false,
.inferred_alloc_mut => true,
else => unreachable,
};
- if (var_is_mut) {
- try sema.validateVarType(block, ty_src, final_elem_ty);
- }
- const final_ptr_ty = try Module.simplePtrType(sema.arena, final_elem_ty, true, .One);
- // Change it to a normal alloc.
- sema.air_instructions.set(ptr_inst, .{
- .tag = .alloc,
- .data = .{ .ty = final_ptr_ty },
- });
+ if (ptr_val.castTag(.inferred_alloc_comptime)) |iac| {
+ const decl = iac.data;
+ try sema.mod.declareDeclDependency(sema.owner_decl, decl);
+
+ const final_elem_ty = try decl.ty.copy(sema.arena);
+ const final_ptr_ty = try Module.simplePtrType(sema.arena, final_elem_ty, true, .One);
+ air_datas[ptr_inst].ty_pl.ty = try sema.addType(final_ptr_ty);
+
+ if (var_is_mut) {
+ sema.air_values.items[value_index] = try Value.Tag.decl_ref_mut.create(sema.arena, .{
+ .decl = decl,
+ .runtime_index = block.runtime_index,
+ });
+ } else {
+ sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, decl);
+ }
+ return;
+ }
+
+ if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {
+ const peer_inst_list = inferred_alloc.data.stored_inst_list.items;
+ const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list);
+ if (var_is_mut) {
+ try sema.validateVarType(block, ty_src, final_elem_ty);
+ }
+ // Change it to a normal alloc.
+ const final_ptr_ty = try Module.simplePtrType(sema.arena, final_elem_ty, true, .One);
+ sema.air_instructions.set(ptr_inst, .{
+ .tag = .alloc,
+ .data = .{ .ty = final_ptr_ty },
+ });
+ return;
+ }
}
fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void {
@@ -1654,23 +1685,45 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
const tracy = trace(@src());
defer tracy.end();
- const src: LazySrcLoc = .unneeded;
+ const src: LazySrcLoc = sema.src;
const bin_inst = sema.code.instructions.items(.data)[inst].bin;
const ptr = sema.resolveInst(bin_inst.lhs);
- const value = sema.resolveInst(bin_inst.rhs);
+ const operand = sema.resolveInst(bin_inst.rhs);
+ const operand_ty = sema.typeOf(operand);
const ptr_inst = Air.refToIndex(ptr).?;
assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);
const air_datas = sema.air_instructions.items(.data);
const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
- const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
- // Add the stored instruction to the set we will use to resolve peer types
- // for the inferred allocation.
- try inferred_alloc.data.stored_inst_list.append(sema.arena, value);
- // Create a runtime bitcast instruction with exactly the type the pointer wants.
- const ptr_ty = try Module.simplePtrType(sema.arena, sema.typeOf(value), true, .One);
- try sema.requireRuntimeBlock(block, src);
- const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
- return sema.storePtr(block, src, bitcasted_ptr, value);
+
+ if (ptr_val.castTag(.inferred_alloc_comptime)) |iac| {
+ // There will be only one store_to_inferred_ptr because we are running at comptime.
+ // The alloc will turn into a Decl.
+ if (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) |operand_val| {
+ if (operand_val.tag() == .variable) {
+ return sema.failWithNeededComptime(block, src);
+ }
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
+ iac.data = try anon_decl.finish(
+ try operand_ty.copy(anon_decl.arena()),
+ try operand_val.copy(anon_decl.arena()),
+ );
+ return;
+ } else {
+ return sema.failWithNeededComptime(block, src);
+ }
+ }
+
+ if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {
+ // Add the stored instruction to the set we will use to resolve peer types
+ // for the inferred allocation.
+ try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);
+ // Create a runtime bitcast instruction with exactly the type the pointer wants.
+ const ptr_ty = try Module.simplePtrType(sema.arena, operand_ty, true, .One);
+ const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
+ return sema.storePtr(block, src, bitcasted_ptr, operand);
+ }
+ unreachable;
}
fn zirSetEvalBranchQuota(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void {
@@ -5643,7 +5696,6 @@ fn zirRetCoerce(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
- need_coercion: bool,
) CompileError!Zir.Inst.Index {
const tracy = trace(@src());
defer tracy.end();
@@ -5652,7 +5704,7 @@ fn zirRetCoerce(
const operand = sema.resolveInst(inst_data.operand);
const src = inst_data.src();
- return sema.analyzeRet(block, operand, src, need_coercion);
+ return sema.analyzeRet(block, operand, src, true);
}
fn zirRetNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
@@ -5673,23 +5725,20 @@ fn analyzeRet(
src: LazySrcLoc,
need_coercion: bool,
) CompileError!Zir.Inst.Index {
+ const casted_operand = if (!need_coercion) operand else op: {
+ const func = sema.func.?;
+ const fn_ty = func.owner_decl.ty;
+ const fn_ret_ty = fn_ty.fnReturnType();
+ break :op try sema.coerce(block, fn_ret_ty, operand, src);
+ };
if (block.inlining) |inlining| {
// We are inlining a function call; rewrite the `ret` as a `break`.
- try inlining.merges.results.append(sema.gpa, operand);
- _ = try block.addBr(inlining.merges.block_inst, operand);
+ try inlining.merges.results.append(sema.gpa, casted_operand);
+ _ = try block.addBr(inlining.merges.block_inst, casted_operand);
return always_noreturn;
}
- if (need_coercion) {
- if (sema.func) |func| {
- const fn_ty = func.owner_decl.ty;
- const fn_ret_ty = fn_ty.fnReturnType();
- const casted_operand = try sema.coerce(block, fn_ret_ty, operand, src);
- _ = try block.addUnOp(.ret, casted_operand);
- return always_noreturn;
- }
- }
- _ = try block.addUnOp(.ret, operand);
+ _ = try block.addUnOp(.ret, casted_operand);
return always_noreturn;
}
@@ -7603,37 +7652,45 @@ fn storePtr(
if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null)
return;
- if (try sema.resolveMaybeUndefVal(block, src, ptr)) |ptr_val| blk: {
- const const_val = (try sema.resolveMaybeUndefVal(block, src, value)) orelse
- return sema.mod.fail(&block.base, src, "cannot store runtime value in compile time variable", .{});
+ if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| {
+ if (ptr_val.castTag(.decl_ref_mut)) |decl_ref_mut| {
+ const const_val = (try sema.resolveMaybeUndefVal(block, src, value)) orelse
+ return sema.mod.fail(&block.base, src, "cannot store runtime value in compile time variable", .{});
- if (ptr_val.tag() == .int_u64)
- break :blk; // propogate it down to runtime
-
- const comptime_alloc = ptr_val.castTag(.comptime_alloc).?;
- if (comptime_alloc.data.runtime_index < block.runtime_index) {
- if (block.runtime_cond) |cond_src| {
- const msg = msg: {
- const msg = try sema.mod.errMsg(&block.base, src, "store to comptime variable depends on runtime condition", .{});
- errdefer msg.destroy(sema.gpa);
- try sema.mod.errNote(&block.base, cond_src, msg, "runtime condition here", .{});
- break :msg msg;
- };
- return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
+ if (decl_ref_mut.data.runtime_index < block.runtime_index) {
+ if (block.runtime_cond) |cond_src| {
+ const msg = msg: {
+ const msg = try sema.mod.errMsg(&block.base, src, "store to comptime variable depends on runtime condition", .{});
+ errdefer msg.destroy(sema.gpa);
+ try sema.mod.errNote(&block.base, cond_src, msg, "runtime condition here", .{});
+ break :msg msg;
+ };
+ return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
+ }
+ if (block.runtime_loop) |loop_src| {
+ const msg = msg: {
+ const msg = try sema.mod.errMsg(&block.base, src, "cannot store to comptime variable in non-inline loop", .{});
+ errdefer msg.destroy(sema.gpa);
+ try sema.mod.errNote(&block.base, loop_src, msg, "non-inline loop here", .{});
+ break :msg msg;
+ };
+ return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
+ }
+ unreachable;
}
- if (block.runtime_loop) |loop_src| {
- const msg = msg: {
- const msg = try sema.mod.errMsg(&block.base, src, "cannot store to comptime variable in non-inline loop", .{});
- errdefer msg.destroy(sema.gpa);
- try sema.mod.errNote(&block.base, loop_src, msg, "non-inline loop here", .{});
- break :msg msg;
- };
- return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
- }
- unreachable;
+ var new_arena = std.heap.ArenaAllocator.init(sema.gpa);
+ errdefer new_arena.deinit();
+ const new_ty = try elem_ty.copy(&new_arena.allocator);
+ const new_val = try const_val.copy(&new_arena.allocator);
+ const decl = decl_ref_mut.data.decl;
+ var old_arena = decl.value_arena.?.promote(sema.gpa);
+ decl.value_arena = null;
+ try decl.finalizeNewArena(&new_arena);
+ decl.ty = new_ty;
+ decl.val = new_val;
+ old_arena.deinit();
+ return;
}
- comptime_alloc.data.val = const_val;
- return;
}
// TODO handle if the element type requires comptime
diff --git a/src/value.zig b/src/value.zig
index 93d6625e7c..a0a7c0650c 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -100,11 +100,13 @@ pub const Value = extern union {
function,
extern_fn,
variable,
- /// Represents a comptime variables storage.
- comptime_alloc,
- /// Represents a pointer to a decl, not the value of the decl.
+ /// Represents a pointer to a Decl.
/// When machine codegen backend sees this, it must set the Decl's `alive` field to true.
decl_ref,
+ /// Pointer to a Decl, but allows comptime code to mutate the Decl's Value.
+ /// This Tag will never be seen by machine codegen backends. It is changed into a
+ /// `decl_ref` when a comptime variable goes out of scope.
+ decl_ref_mut,
elem_ptr,
field_ptr,
/// A slice of u8 whose memory is managed externally.
@@ -134,6 +136,9 @@ pub const Value = extern union {
/// This is a special value that tracks a set of types that have been stored
/// to an inferred allocation. It does not support any of the normal value queries.
inferred_alloc,
+ /// Used to coordinate alloc_inferred, store_to_inferred_ptr, and resolve_inferred_alloc
+ /// instructions for comptime code.
+ inferred_alloc_comptime,
pub const last_no_payload_tag = Tag.empty_array;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
@@ -213,6 +218,7 @@ pub const Value = extern union {
.extern_fn,
.decl_ref,
+ .inferred_alloc_comptime,
=> Payload.Decl,
.repeated,
@@ -235,7 +241,7 @@ pub const Value = extern union {
.int_i64 => Payload.I64,
.function => Payload.Function,
.variable => Payload.Variable,
- .comptime_alloc => Payload.ComptimeAlloc,
+ .decl_ref_mut => Payload.DeclRefMut,
.elem_ptr => Payload.ElemPtr,
.field_ptr => Payload.FieldPtr,
.float_16 => Payload.Float_16,
@@ -408,8 +414,8 @@ pub const Value = extern union {
.function => return self.copyPayloadShallow(allocator, Payload.Function),
.extern_fn => return self.copyPayloadShallow(allocator, Payload.Decl),
.variable => return self.copyPayloadShallow(allocator, Payload.Variable),
- .comptime_alloc => return self.copyPayloadShallow(allocator, Payload.ComptimeAlloc),
.decl_ref => return self.copyPayloadShallow(allocator, Payload.Decl),
+ .decl_ref_mut => return self.copyPayloadShallow(allocator, Payload.DeclRefMut),
.elem_ptr => {
const payload = self.castTag(.elem_ptr).?;
const new_payload = try allocator.create(Payload.ElemPtr);
@@ -485,6 +491,7 @@ pub const Value = extern union {
.@"union" => @panic("TODO can't copy union value without knowing the type"),
.inferred_alloc => unreachable,
+ .inferred_alloc_comptime => unreachable,
}
}
@@ -592,10 +599,9 @@ pub const Value = extern union {
.function => return out_stream.print("(function '{s}')", .{val.castTag(.function).?.data.owner_decl.name}),
.extern_fn => return out_stream.writeAll("(extern function)"),
.variable => return out_stream.writeAll("(variable)"),
- .comptime_alloc => {
- const ref_val = val.castTag(.comptime_alloc).?.data.val;
- try out_stream.writeAll("&");
- val = ref_val;
+ .decl_ref_mut => {
+ const decl = val.castTag(.decl_ref_mut).?.data.decl;
+ return out_stream.print("(decl_ref_mut '{s}')", .{decl.name});
},
.decl_ref => return out_stream.writeAll("(decl ref)"),
.elem_ptr => {
@@ -626,6 +632,7 @@ pub const Value = extern union {
// TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that
.error_union => return out_stream.print("error_union_val({})", .{val.castTag(.error_union).?.data}),
.inferred_alloc => return out_stream.writeAll("(inferred allocation value)"),
+ .inferred_alloc_comptime => return out_stream.writeAll("(inferred comptime allocation value)"),
.eu_payload_ptr => {
try out_stream.writeAll("(eu_payload_ptr)");
val = val.castTag(.eu_payload_ptr).?.data;
@@ -741,8 +748,8 @@ pub const Value = extern union {
.function,
.extern_fn,
.variable,
- .comptime_alloc,
.decl_ref,
+ .decl_ref_mut,
.elem_ptr,
.field_ptr,
.bytes,
@@ -761,6 +768,7 @@ pub const Value = extern union {
.@"struct",
.@"union",
.inferred_alloc,
+ .inferred_alloc_comptime,
.abi_align_default,
.eu_payload_ptr,
=> unreachable,
@@ -1234,7 +1242,13 @@ pub const Value = extern union {
allocator: *Allocator,
) error{ AnalysisFail, OutOfMemory }!?Value {
const sub_val: Value = switch (self.tag()) {
- .comptime_alloc => self.castTag(.comptime_alloc).?.data.val,
+ .decl_ref_mut => val: {
+ // The decl whose value we are obtaining here may be overwritten with
+ // a different value, which would invalidate this memory. So we must
+ // copy here.
+ const val = try self.castTag(.decl_ref_mut).?.data.decl.value();
+ break :val try val.copy(allocator);
+ },
.decl_ref => try self.castTag(.decl_ref).?.data.value(),
.elem_ptr => blk: {
const elem_ptr = self.castTag(.elem_ptr).?.data;
@@ -1351,6 +1365,7 @@ pub const Value = extern union {
.undef => unreachable,
.unreachable_value => unreachable,
.inferred_alloc => unreachable,
+ .inferred_alloc_comptime => unreachable,
.null_value => true,
else => false,
@@ -1371,6 +1386,7 @@ pub const Value = extern union {
.undef => unreachable,
.unreachable_value => unreachable,
.inferred_alloc => unreachable,
+ .inferred_alloc_comptime => unreachable,
else => null,
};
@@ -1380,6 +1396,7 @@ pub const Value = extern union {
return switch (self.tag()) {
.undef => unreachable,
.inferred_alloc => unreachable,
+ .inferred_alloc_comptime => unreachable,
.float_16,
.float_32,
@@ -1443,12 +1460,12 @@ pub const Value = extern union {
data: Value,
};
- pub const ComptimeAlloc = struct {
- pub const base_tag = Tag.comptime_alloc;
+ pub const DeclRefMut = struct {
+ pub const base_tag = Tag.decl_ref_mut;
base: Payload = Payload{ .tag = base_tag },
data: struct {
- val: Value,
+ decl: *Module.Decl,
runtime_index: u32,
},
};
diff --git a/test/behavior.zig b/test/behavior.zig
index a286b1a6e2..4cc4d7fb8b 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -3,6 +3,7 @@ const builtin = @import("builtin");
test {
// Tests that pass for both.
_ = @import("behavior/bool.zig");
+ _ = @import("behavior/basic.zig");
if (!builtin.zig_is_stage2) {
// Tests that only pass for stage1.
diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig
new file mode 100644
index 0000000000..8f0f20cdf5
--- /dev/null
+++ b/test/behavior/basic.zig
@@ -0,0 +1,9 @@
+// normal comment
+
+/// this is a documentation comment
+/// doc comment line 2
+fn emptyFunctionWithComments() void {}
+
+test "empty function with comments" {
+ emptyFunctionWithComments();
+}
diff --git a/test/behavior/bool.zig b/test/behavior/bool.zig
index dfa02a6bfd..447f9e02e6 100644
--- a/test/behavior/bool.zig
+++ b/test/behavior/bool.zig
@@ -33,3 +33,47 @@ test "compile time bool not" {
try expect(not_global_f);
try expect(!not_global_t);
}
+
+test "short circuit" {
+ try testShortCircuit(false, true);
+ comptime try testShortCircuit(false, true);
+}
+
+fn testShortCircuit(f: bool, t: bool) !void {
+ var hit_1 = f;
+ var hit_2 = f;
+ var hit_3 = f;
+ var hit_4 = f;
+
+ if (t or x: {
+ try expect(f);
+ break :x f;
+ }) {
+ hit_1 = t;
+ }
+ if (f or x: {
+ hit_2 = t;
+ break :x f;
+ }) {
+ try expect(f);
+ }
+
+ if (t and x: {
+ hit_3 = t;
+ break :x f;
+ }) {
+ try expect(f);
+ }
+ if (f and x: {
+ try expect(f);
+ break :x f;
+ }) {
+ try expect(f);
+ } else {
+ hit_4 = t;
+ }
+ try expect(hit_1);
+ try expect(hit_2);
+ try expect(hit_3);
+ try expect(hit_4);
+}
diff --git a/test/behavior/misc.zig b/test/behavior/misc.zig
index fdd3f3477b..ba38d6327c 100644
--- a/test/behavior/misc.zig
+++ b/test/behavior/misc.zig
@@ -5,70 +5,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;
const mem = std.mem;
const builtin = @import("builtin");
-// normal comment
-
-/// this is a documentation comment
-/// doc comment line 2
-fn emptyFunctionWithComments() void {}
-
-test "empty function with comments" {
- emptyFunctionWithComments();
-}
-
-comptime {
- @export(disabledExternFn, .{ .name = "disabledExternFn", .linkage = .Internal });
-}
-
-fn disabledExternFn() callconv(.C) void {}
-
-test "call disabled extern fn" {
- disabledExternFn();
-}
-
-test "short circuit" {
- try testShortCircuit(false, true);
- comptime try testShortCircuit(false, true);
-}
-
-fn testShortCircuit(f: bool, t: bool) !void {
- var hit_1 = f;
- var hit_2 = f;
- var hit_3 = f;
- var hit_4 = f;
-
- if (t or x: {
- try expect(f);
- break :x f;
- }) {
- hit_1 = t;
- }
- if (f or x: {
- hit_2 = t;
- break :x f;
- }) {
- try expect(f);
- }
-
- if (t and x: {
- hit_3 = t;
- break :x f;
- }) {
- try expect(f);
- }
- if (f and x: {
- try expect(f);
- break :x f;
- }) {
- try expect(f);
- } else {
- hit_4 = t;
- }
- try expect(hit_1);
- try expect(hit_2);
- try expect(hit_3);
- try expect(hit_4);
-}
-
test "truncate" {
try expect(testTruncate(0x10fd) == 0xfd);
}
From 0ce54a141628b27ceab074dac4c19827a2188165 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Sun, 1 Aug 2021 22:48:39 +0200
Subject: [PATCH 58/96] add standalone Objective-C enabled on macOS only
---
test/standalone.zig | 4 ++++
test/standalone/objc/Foo.h | 7 +++++++
test/standalone/objc/Foo.m | 11 +++++++++++
test/standalone/objc/build.zig | 22 ++++++++++++++++++++++
test/standalone/objc/test.m | 12 ++++++++++++
5 files changed, 56 insertions(+)
create mode 100644 test/standalone/objc/Foo.h
create mode 100644 test/standalone/objc/Foo.m
create mode 100644 test/standalone/objc/build.zig
create mode 100644 test/standalone/objc/test.m
diff --git a/test/standalone.zig b/test/standalone.zig
index a483097f4a..52fba31828 100644
--- a/test/standalone.zig
+++ b/test/standalone.zig
@@ -37,6 +37,10 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
if (std.Target.current.os.tag == .linux) {
cases.addBuildFile("test/standalone/pie/build.zig", .{});
}
+ // Try to build and run an Objective-C executable.
+ if (std.Target.current.os.tag == .macos) {
+ cases.addBuildFile("test/standalone/objc/build.zig", .{ .build_modes = true });
+ }
// Ensure the development tools are buildable.
cases.add("tools/gen_spirv_spec.zig");
diff --git a/test/standalone/objc/Foo.h b/test/standalone/objc/Foo.h
new file mode 100644
index 0000000000..05cb7df39b
--- /dev/null
+++ b/test/standalone/objc/Foo.h
@@ -0,0 +1,7 @@
+#import
+
+@interface Foo : NSObject
+
+- (NSString *)name;
+
+@end
diff --git a/test/standalone/objc/Foo.m b/test/standalone/objc/Foo.m
new file mode 100644
index 0000000000..6fc9b1edf0
--- /dev/null
+++ b/test/standalone/objc/Foo.m
@@ -0,0 +1,11 @@
+#import "Foo.h"
+
+@implementation Foo
+
+- (NSString *)name
+{
+ NSString *str = [[NSString alloc] initWithFormat:@"Zig"];
+ return str;
+}
+
+@end
diff --git a/test/standalone/objc/build.zig b/test/standalone/objc/build.zig
new file mode 100644
index 0000000000..30becd398c
--- /dev/null
+++ b/test/standalone/objc/build.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+const Builder = std.build.Builder;
+
+pub fn build(b: *Builder) void {
+ const mode = b.standardReleaseOptions();
+ const target = b.standardTargetOptions(.{});
+
+ const test_step = b.step("test", "Test the program");
+
+ const exe = b.addExecutable("test", null);
+ b.default_step.dependOn(&exe.step);
+ exe.addIncludeDir(".");
+ exe.addCSourceFile("Foo.m", &[0][]const u8{});
+ exe.addCSourceFile("test.m", &[0][]const u8{});
+ exe.setBuildMode(mode);
+ exe.setTarget(target);
+ exe.linkLibC();
+ exe.linkFramework("Foundation");
+
+ const run_cmd = exe.run();
+ test_step.dependOn(&run_cmd.step);
+}
diff --git a/test/standalone/objc/test.m b/test/standalone/objc/test.m
new file mode 100644
index 0000000000..3c81316788
--- /dev/null
+++ b/test/standalone/objc/test.m
@@ -0,0 +1,12 @@
+#import "Foo.h"
+#import
+
+int main(int argc, char *argv[])
+{
+ @autoreleasepool {
+ Foo *foo = [[Foo alloc] init];
+ NSString *result = [foo name];
+ assert([result isEqualToString:@"Zig"]);
+ return 0;
+ }
+}
From ddf14323ea9b2c75ac5ed286525d27730a192b53 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 1 Aug 2021 16:13:58 -0700
Subject: [PATCH 59/96] stage2: implement `@truncate`
---
src/Air.zig | 11 +-
src/Liveness.zig | 1 +
src/Module.zig | 238 ----------------------------------
src/Sema.zig | 104 ++++++++++-----
src/codegen.zig | 14 ++
src/codegen/c.zig | 15 ++-
src/codegen/llvm.zig | 11 ++
src/codegen/llvm/bindings.zig | 8 ++
src/print_air.zig | 1 +
src/value.zig | 238 ++++++++++++++++++++++++++++++++++
test/behavior/basic.zig | 11 ++
test/behavior/misc.zig | 7 -
12 files changed, 380 insertions(+), 279 deletions(-)
diff --git a/src/Air.zig b/src/Air.zig
index d202c079bc..d923bf0b02 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -206,10 +206,16 @@ pub const Inst = struct {
/// Convert from one float type to another.
/// Uses the `ty_op` field.
floatcast,
- /// TODO audit uses of this. We should have explicit instructions for integer
- /// widening and truncating.
+ /// Returns an integer with a different type than the operand. The new type may have
+ /// fewer, the same, or more bits than the operand type. However, the instruction
+ /// guarantees that the same integer value fits in both types.
+ /// See `trunc` for integer truncation.
/// Uses the `ty_op` field.
intcast,
+ /// Truncate higher bits from an integer, resulting in an integer with the same
+ /// sign but an equal or smaller number of bits.
+ /// Uses the `ty_op` field.
+ trunc,
/// ?T => T. If the value is null, undefined behavior.
/// Uses the `ty_op` field.
optional_payload,
@@ -452,6 +458,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.load,
.floatcast,
.intcast,
+ .trunc,
.optional_payload,
.optional_payload_ptr,
.wrap_optional,
diff --git a/src/Liveness.zig b/src/Liveness.zig
index 7ba062fa31..4e22febc5a 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -264,6 +264,7 @@ fn analyzeInst(
.load,
.floatcast,
.intcast,
+ .trunc,
.optional_payload,
.optional_payload_ptr,
.wrap_optional,
diff --git a/src/Module.zig b/src/Module.zig
index d87f20621c..84b721369d 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -4033,244 +4033,6 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) Co
return error.AnalysisFail;
}
-pub fn intAdd(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
- // TODO is this a performance issue? maybe we should try the operation without
- // resorting to BigInt first.
- var lhs_space: Value.BigIntSpace = undefined;
- var rhs_space: Value.BigIntSpace = undefined;
- const lhs_bigint = lhs.toBigInt(&lhs_space);
- const rhs_bigint = rhs.toBigInt(&rhs_space);
- const limbs = try allocator.alloc(
- std.math.big.Limb,
- std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
- );
- var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
- result_bigint.add(lhs_bigint, rhs_bigint);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
-
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
-}
-
-pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
- // TODO is this a performance issue? maybe we should try the operation without
- // resorting to BigInt first.
- var lhs_space: Value.BigIntSpace = undefined;
- var rhs_space: Value.BigIntSpace = undefined;
- const lhs_bigint = lhs.toBigInt(&lhs_space);
- const rhs_bigint = rhs.toBigInt(&rhs_space);
- const limbs = try allocator.alloc(
- std.math.big.Limb,
- std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
- );
- var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
- result_bigint.sub(lhs_bigint, rhs_bigint);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
-
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
-}
-
-pub fn intDiv(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
- // TODO is this a performance issue? maybe we should try the operation without
- // resorting to BigInt first.
- var lhs_space: Value.BigIntSpace = undefined;
- var rhs_space: Value.BigIntSpace = undefined;
- const lhs_bigint = lhs.toBigInt(&lhs_space);
- const rhs_bigint = rhs.toBigInt(&rhs_space);
- const limbs_q = try allocator.alloc(
- std.math.big.Limb,
- lhs_bigint.limbs.len + rhs_bigint.limbs.len + 1,
- );
- const limbs_r = try allocator.alloc(
- std.math.big.Limb,
- lhs_bigint.limbs.len,
- );
- const limbs_buffer = try allocator.alloc(
- std.math.big.Limb,
- std.math.big.int.calcDivLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
- );
- var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
- var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
- result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer, null);
- const result_limbs = result_q.limbs[0..result_q.len];
-
- if (result_q.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
-}
-
-pub fn intMul(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
- // TODO is this a performance issue? maybe we should try the operation without
- // resorting to BigInt first.
- var lhs_space: Value.BigIntSpace = undefined;
- var rhs_space: Value.BigIntSpace = undefined;
- const lhs_bigint = lhs.toBigInt(&lhs_space);
- const rhs_bigint = rhs.toBigInt(&rhs_space);
- const limbs = try allocator.alloc(
- std.math.big.Limb,
- lhs_bigint.limbs.len + rhs_bigint.limbs.len + 1,
- );
- var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
- var limbs_buffer = try allocator.alloc(
- std.math.big.Limb,
- std.math.big.int.calcMulLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len, 1),
- );
- defer allocator.free(limbs_buffer);
- result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, allocator);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
-
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
-}
-
-pub fn floatAdd(
- arena: *Allocator,
- float_type: Type,
- src: LazySrcLoc,
- lhs: Value,
- rhs: Value,
-) !Value {
- _ = src;
- switch (float_type.tag()) {
- .f16 => {
- @panic("TODO add __trunctfhf2 to compiler-rt");
- //const lhs_val = lhs.toFloat(f16);
- //const rhs_val = rhs.toFloat(f16);
- //return Value.Tag.float_16.create(arena, lhs_val + rhs_val);
- },
- .f32 => {
- const lhs_val = lhs.toFloat(f32);
- const rhs_val = rhs.toFloat(f32);
- return Value.Tag.float_32.create(arena, lhs_val + rhs_val);
- },
- .f64 => {
- const lhs_val = lhs.toFloat(f64);
- const rhs_val = rhs.toFloat(f64);
- return Value.Tag.float_64.create(arena, lhs_val + rhs_val);
- },
- .f128, .comptime_float, .c_longdouble => {
- const lhs_val = lhs.toFloat(f128);
- const rhs_val = rhs.toFloat(f128);
- return Value.Tag.float_128.create(arena, lhs_val + rhs_val);
- },
- else => unreachable,
- }
-}
-
-pub fn floatSub(
- arena: *Allocator,
- float_type: Type,
- src: LazySrcLoc,
- lhs: Value,
- rhs: Value,
-) !Value {
- _ = src;
- switch (float_type.tag()) {
- .f16 => {
- @panic("TODO add __trunctfhf2 to compiler-rt");
- //const lhs_val = lhs.toFloat(f16);
- //const rhs_val = rhs.toFloat(f16);
- //return Value.Tag.float_16.create(arena, lhs_val - rhs_val);
- },
- .f32 => {
- const lhs_val = lhs.toFloat(f32);
- const rhs_val = rhs.toFloat(f32);
- return Value.Tag.float_32.create(arena, lhs_val - rhs_val);
- },
- .f64 => {
- const lhs_val = lhs.toFloat(f64);
- const rhs_val = rhs.toFloat(f64);
- return Value.Tag.float_64.create(arena, lhs_val - rhs_val);
- },
- .f128, .comptime_float, .c_longdouble => {
- const lhs_val = lhs.toFloat(f128);
- const rhs_val = rhs.toFloat(f128);
- return Value.Tag.float_128.create(arena, lhs_val - rhs_val);
- },
- else => unreachable,
- }
-}
-
-pub fn floatDiv(
- arena: *Allocator,
- float_type: Type,
- src: LazySrcLoc,
- lhs: Value,
- rhs: Value,
-) !Value {
- _ = src;
- switch (float_type.tag()) {
- .f16 => {
- @panic("TODO add __trunctfhf2 to compiler-rt");
- //const lhs_val = lhs.toFloat(f16);
- //const rhs_val = rhs.toFloat(f16);
- //return Value.Tag.float_16.create(arena, lhs_val / rhs_val);
- },
- .f32 => {
- const lhs_val = lhs.toFloat(f32);
- const rhs_val = rhs.toFloat(f32);
- return Value.Tag.float_32.create(arena, lhs_val / rhs_val);
- },
- .f64 => {
- const lhs_val = lhs.toFloat(f64);
- const rhs_val = rhs.toFloat(f64);
- return Value.Tag.float_64.create(arena, lhs_val / rhs_val);
- },
- .f128, .comptime_float, .c_longdouble => {
- const lhs_val = lhs.toFloat(f128);
- const rhs_val = rhs.toFloat(f128);
- return Value.Tag.float_128.create(arena, lhs_val / rhs_val);
- },
- else => unreachable,
- }
-}
-
-pub fn floatMul(
- arena: *Allocator,
- float_type: Type,
- src: LazySrcLoc,
- lhs: Value,
- rhs: Value,
-) !Value {
- _ = src;
- switch (float_type.tag()) {
- .f16 => {
- @panic("TODO add __trunctfhf2 to compiler-rt");
- //const lhs_val = lhs.toFloat(f16);
- //const rhs_val = rhs.toFloat(f16);
- //return Value.Tag.float_16.create(arena, lhs_val * rhs_val);
- },
- .f32 => {
- const lhs_val = lhs.toFloat(f32);
- const rhs_val = rhs.toFloat(f32);
- return Value.Tag.float_32.create(arena, lhs_val * rhs_val);
- },
- .f64 => {
- const lhs_val = lhs.toFloat(f64);
- const rhs_val = rhs.toFloat(f64);
- return Value.Tag.float_64.create(arena, lhs_val * rhs_val);
- },
- .f128, .comptime_float, .c_longdouble => {
- const lhs_val = lhs.toFloat(f128);
- const rhs_val = rhs.toFloat(f128);
- return Value.Tag.float_128.create(arena, lhs_val * rhs_val);
- },
- else => unreachable,
- }
-}
-
pub fn simplePtrType(
arena: *Allocator,
elem_ty: Type,
diff --git a/src/Sema.zig b/src/Sema.zig
index 5ad590be6a..6b281f8569 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -3479,27 +3479,8 @@ fn zirIntCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs);
const operand = sema.resolveInst(extra.rhs);
- const dest_is_comptime_int = switch (dest_type.zigTypeTag()) {
- .ComptimeInt => true,
- .Int => false,
- else => return sema.mod.fail(
- &block.base,
- dest_ty_src,
- "expected integer type, found '{}'",
- .{dest_type},
- ),
- };
-
- const operand_ty = sema.typeOf(operand);
- switch (operand_ty.zigTypeTag()) {
- .ComptimeInt, .Int => {},
- else => return sema.mod.fail(
- &block.base,
- operand_src,
- "expected integer type, found '{}'",
- .{operand_ty},
- ),
- }
+ const dest_is_comptime_int = try sema.requireIntegerType(block, dest_ty_src, dest_type);
+ _ = try sema.requireIntegerType(block, operand_src, sema.typeOf(operand));
if (try sema.isComptimeKnown(block, operand_src, operand)) {
return sema.coerce(block, dest_type, operand, operand_src);
@@ -4951,30 +4932,30 @@ fn analyzeArithmetic(
const value = switch (zir_tag) {
.add => blk: {
const val = if (is_int)
- try Module.intAdd(sema.arena, lhs_val, rhs_val)
+ try lhs_val.intAdd(rhs_val, sema.arena)
else
- try Module.floatAdd(sema.arena, scalar_type, src, lhs_val, rhs_val);
+ try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena);
break :blk val;
},
.sub => blk: {
const val = if (is_int)
- try Module.intSub(sema.arena, lhs_val, rhs_val)
+ try lhs_val.intSub(rhs_val, sema.arena)
else
- try Module.floatSub(sema.arena, scalar_type, src, lhs_val, rhs_val);
+ try lhs_val.floatSub(rhs_val, scalar_type, sema.arena);
break :blk val;
},
.div => blk: {
const val = if (is_int)
- try Module.intDiv(sema.arena, lhs_val, rhs_val)
+ try lhs_val.intDiv(rhs_val, sema.arena)
else
- try Module.floatDiv(sema.arena, scalar_type, src, lhs_val, rhs_val);
+ try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena);
break :blk val;
},
.mul => blk: {
const val = if (is_int)
- try Module.intMul(sema.arena, lhs_val, rhs_val)
+ try lhs_val.intMul(rhs_val, sema.arena)
else
- try Module.floatMul(sema.arena, scalar_type, src, lhs_val, rhs_val);
+ try lhs_val.floatMul(rhs_val, scalar_type, sema.arena);
break :blk val;
},
else => return sema.mod.fail(&block.base, src, "TODO Implement arithmetic operand '{s}'", .{@tagName(zir_tag)}),
@@ -6173,7 +6154,62 @@ fn zirPtrCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
- return sema.mod.fail(&block.base, src, "TODO: Sema.zirTruncate", .{});
+ const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+ const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
+ const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
+ const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
+ const operand = sema.resolveInst(extra.rhs);
+ const operand_ty = sema.typeOf(operand);
+ const mod = sema.mod;
+ const dest_is_comptime_int = try sema.requireIntegerType(block, dest_ty_src, dest_ty);
+ const src_is_comptime_int = try sema.requireIntegerType(block, operand_src, operand_ty);
+
+ if (dest_is_comptime_int) {
+ return sema.coerce(block, dest_ty, operand, operand_src);
+ }
+
+ const target = mod.getTarget();
+ const src_info = operand_ty.intInfo(target);
+ const dest_info = dest_ty.intInfo(target);
+
+ if (src_info.bits == 0 or dest_info.bits == 0) {
+ return sema.addConstant(dest_ty, Value.initTag(.zero));
+ }
+
+ if (!src_is_comptime_int) {
+ if (src_info.signedness != dest_info.signedness) {
+ return mod.fail(&block.base, operand_src, "expected {s} integer type, found '{}'", .{
+ @tagName(dest_info.signedness), operand_ty,
+ });
+ }
+ if (src_info.bits > 0 and src_info.bits < dest_info.bits) {
+ const msg = msg: {
+ const msg = try mod.errMsg(
+ &block.base,
+ src,
+ "destination type '{}' has more bits than source type '{}'",
+ .{ dest_ty, operand_ty },
+ );
+ errdefer msg.destroy(mod.gpa);
+ try mod.errNote(&block.base, dest_ty_src, msg, "destination type has {d} bits", .{
+ dest_info.bits,
+ });
+ try mod.errNote(&block.base, operand_src, msg, "source type has {d} bits", .{
+ src_info.bits,
+ });
+ break :msg msg;
+ };
+ return mod.failWithOwnedErrorMsg(&block.base, msg);
+ }
+ }
+
+ if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
+ if (val.isUndef()) return sema.addConstUndef(dest_ty);
+ return sema.addConstant(dest_ty, try val.intTrunc(sema.arena, dest_info.bits));
+ }
+
+ try sema.requireRuntimeBlock(block, src);
+ return block.addTyOp(.trunc, dest_ty, operand);
}
fn zirAlignCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -6594,6 +6630,14 @@ fn requireRuntimeBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void
try sema.requireFunctionBlock(block, src);
}
+fn requireIntegerType(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) !bool {
+ switch (ty.zigTypeTag()) {
+ .ComptimeInt => return true,
+ .Int => return false,
+ else => return sema.mod.fail(&block.base, src, "expected integer type, found '{}'", .{ty}),
+ }
+}
+
fn validateVarType(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) !void {
if (!ty.isValidVarType(false)) {
return sema.mod.fail(&block.base, src, "variable of type '{}' must be const or comptime", .{ty});
diff --git a/src/codegen.zig b/src/codegen.zig
index 8c56ab4431..3864479d2d 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -835,6 +835,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.dbg_stmt => try self.airDbgStmt(inst),
.floatcast => try self.airFloatCast(inst),
.intcast => try self.airIntCast(inst),
+ .trunc => try self.airTrunc(inst),
.bool_to_int => try self.airBoolToInt(inst),
.is_non_null => try self.airIsNonNull(inst),
.is_non_null_ptr => try self.airIsNonNullPtr(inst),
@@ -1109,6 +1110,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
+ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ if (self.liveness.isUnused(inst))
+ return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
+
+ const operand = try self.resolveInst(ty_op.operand);
+ _ = operand;
+ const result: MCValue = switch (arch) {
+ else => return self.fail("TODO implement trunc for {}", .{self.target.cpu.arch}),
+ };
+ return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
+ }
+
fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
const un_op = self.air.instructions.items(.data)[inst].un_op;
const operand = try self.resolveInst(un_op);
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 826b73317c..22420aca45 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -900,6 +900,7 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
.call => try airCall(o, inst),
.dbg_stmt => try airDbgStmt(o, inst),
.intcast => try airIntCast(o, inst),
+ .trunc => try airTrunc(o, inst),
.bool_to_int => try airBoolToInt(o, inst),
.load => try airLoad(o, inst),
.ret => try airRet(o, inst),
@@ -1038,7 +1039,7 @@ fn airIntCast(o: *Object, inst: Air.Inst.Index) !CValue {
return CValue.none;
const ty_op = o.air.instructions.items(.data)[inst].ty_op;
- const from = try o.resolveInst(ty_op.operand);
+ const operand = try o.resolveInst(ty_op.operand);
const writer = o.writer();
const inst_ty = o.air.typeOfIndex(inst);
@@ -1046,11 +1047,21 @@ fn airIntCast(o: *Object, inst: Air.Inst.Index) !CValue {
try writer.writeAll(" = (");
try o.dg.renderType(writer, inst_ty);
try writer.writeAll(")");
- try o.writeCValue(writer, from);
+ try o.writeCValue(writer, operand);
try writer.writeAll(";\n");
return local;
}
+fn airTrunc(o: *Object, inst: Air.Inst.Index) !CValue {
+ if (o.liveness.isUnused(inst))
+ return CValue.none;
+
+ const ty_op = o.air.instructions.items(.data)[inst].ty_op;
+ const operand = try o.resolveInst(ty_op.operand);
+ _ = operand;
+ return o.dg.fail("TODO: C backend: airTrunc", .{});
+}
+
fn airBoolToInt(o: *Object, inst: Air.Inst.Index) !CValue {
if (o.liveness.isUnused(inst))
return CValue.none;
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 961ed7ee99..8b3edcfe23 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -960,6 +960,7 @@ pub const FuncGen = struct {
.call => try self.airCall(inst),
.cond_br => try self.airCondBr(inst),
.intcast => try self.airIntCast(inst),
+ .trunc => try self.airTrunc(inst),
.floatcast => try self.airFloatCast(inst),
.ptrtoint => try self.airPtrToInt(inst),
.load => try self.airLoad(inst),
@@ -1615,6 +1616,16 @@ pub const FuncGen = struct {
return self.builder.buildIntCast2(operand, try self.dg.llvmType(inst_ty), llvm.Bool.fromBool(signed), "");
}
+ fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const operand = try self.resolveInst(ty_op.operand);
+ const dest_llvm_ty = try self.dg.llvmType(self.air.typeOfIndex(inst));
+ return self.builder.buildTrunc(operand, dest_llvm_ty, "");
+ }
+
fn airFloatCast(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index 0977d6128d..4af3cadd84 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -423,6 +423,14 @@ pub const Builder = opaque {
Idx: c_uint,
Name: [*:0]const u8,
) *const Value;
+
+ pub const buildTrunc = LLVMBuildTrunc;
+ extern fn LLVMBuildTrunc(
+ *const Builder,
+ Val: *const Value,
+ DestTy: *const Type,
+ Name: [*:0]const u8,
+ ) *const Value;
};
pub const IntPredicate = enum(c_int) {
diff --git a/src/print_air.zig b/src/print_air.zig
index 5d77c303bb..00317b26e8 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -151,6 +151,7 @@ const Writer = struct {
.load,
.floatcast,
.intcast,
+ .trunc,
.optional_payload,
.optional_payload_ptr,
.wrap_optional,
diff --git a/src/value.zig b/src/value.zig
index a0a7c0650c..134b51e494 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1407,6 +1407,244 @@ pub const Value = extern union {
};
}
+ pub fn intAdd(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
+ // TODO is this a performance issue? maybe we should try the operation without
+ // resorting to BigInt first.
+ var lhs_space: Value.BigIntSpace = undefined;
+ var rhs_space: Value.BigIntSpace = undefined;
+ const lhs_bigint = lhs.toBigInt(&lhs_space);
+ const rhs_bigint = rhs.toBigInt(&rhs_space);
+ const limbs = try allocator.alloc(
+ std.math.big.Limb,
+ std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
+ );
+ var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
+ result_bigint.add(lhs_bigint, rhs_bigint);
+ const result_limbs = result_bigint.limbs[0..result_bigint.len];
+
+ if (result_bigint.positive) {
+ return Value.Tag.int_big_positive.create(allocator, result_limbs);
+ } else {
+ return Value.Tag.int_big_negative.create(allocator, result_limbs);
+ }
+ }
+
+ pub fn intSub(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
+ // TODO is this a performance issue? maybe we should try the operation without
+ // resorting to BigInt first.
+ var lhs_space: Value.BigIntSpace = undefined;
+ var rhs_space: Value.BigIntSpace = undefined;
+ const lhs_bigint = lhs.toBigInt(&lhs_space);
+ const rhs_bigint = rhs.toBigInt(&rhs_space);
+ const limbs = try allocator.alloc(
+ std.math.big.Limb,
+ std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
+ );
+ var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
+ result_bigint.sub(lhs_bigint, rhs_bigint);
+ const result_limbs = result_bigint.limbs[0..result_bigint.len];
+
+ if (result_bigint.positive) {
+ return Value.Tag.int_big_positive.create(allocator, result_limbs);
+ } else {
+ return Value.Tag.int_big_negative.create(allocator, result_limbs);
+ }
+ }
+
+ pub fn intDiv(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
+ // TODO is this a performance issue? maybe we should try the operation without
+ // resorting to BigInt first.
+ var lhs_space: Value.BigIntSpace = undefined;
+ var rhs_space: Value.BigIntSpace = undefined;
+ const lhs_bigint = lhs.toBigInt(&lhs_space);
+ const rhs_bigint = rhs.toBigInt(&rhs_space);
+ const limbs_q = try allocator.alloc(
+ std.math.big.Limb,
+ lhs_bigint.limbs.len + rhs_bigint.limbs.len + 1,
+ );
+ const limbs_r = try allocator.alloc(
+ std.math.big.Limb,
+ lhs_bigint.limbs.len,
+ );
+ const limbs_buffer = try allocator.alloc(
+ std.math.big.Limb,
+ std.math.big.int.calcDivLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
+ );
+ var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
+ var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
+ result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer, null);
+ const result_limbs = result_q.limbs[0..result_q.len];
+
+ if (result_q.positive) {
+ return Value.Tag.int_big_positive.create(allocator, result_limbs);
+ } else {
+ return Value.Tag.int_big_negative.create(allocator, result_limbs);
+ }
+ }
+
+ pub fn intMul(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
+ // TODO is this a performance issue? maybe we should try the operation without
+ // resorting to BigInt first.
+ var lhs_space: Value.BigIntSpace = undefined;
+ var rhs_space: Value.BigIntSpace = undefined;
+ const lhs_bigint = lhs.toBigInt(&lhs_space);
+ const rhs_bigint = rhs.toBigInt(&rhs_space);
+ const limbs = try allocator.alloc(
+ std.math.big.Limb,
+ lhs_bigint.limbs.len + rhs_bigint.limbs.len + 1,
+ );
+ var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
+ var limbs_buffer = try allocator.alloc(
+ std.math.big.Limb,
+ std.math.big.int.calcMulLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len, 1),
+ );
+ defer allocator.free(limbs_buffer);
+ result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, allocator);
+ const result_limbs = result_bigint.limbs[0..result_bigint.len];
+
+ if (result_bigint.positive) {
+ return Value.Tag.int_big_positive.create(allocator, result_limbs);
+ } else {
+ return Value.Tag.int_big_negative.create(allocator, result_limbs);
+ }
+ }
+
+ pub fn intTrunc(val: Value, arena: *Allocator, bits: u16) !Value {
+ const x = val.toUnsignedInt(); // TODO: implement comptime truncate on big ints
+ if (bits == 64) return val;
+ const mask = (@as(u64, 1) << @intCast(u6, bits)) - 1;
+ const truncated = x & mask;
+ return Tag.int_u64.create(arena, truncated);
+ }
+
+ pub fn floatAdd(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: *Allocator,
+ ) !Value {
+ switch (float_type.tag()) {
+ .f16 => {
+ @panic("TODO add __trunctfhf2 to compiler-rt");
+ //const lhs_val = lhs.toFloat(f16);
+ //const rhs_val = rhs.toFloat(f16);
+ //return Value.Tag.float_16.create(arena, lhs_val + rhs_val);
+ },
+ .f32 => {
+ const lhs_val = lhs.toFloat(f32);
+ const rhs_val = rhs.toFloat(f32);
+ return Value.Tag.float_32.create(arena, lhs_val + rhs_val);
+ },
+ .f64 => {
+ const lhs_val = lhs.toFloat(f64);
+ const rhs_val = rhs.toFloat(f64);
+ return Value.Tag.float_64.create(arena, lhs_val + rhs_val);
+ },
+ .f128, .comptime_float, .c_longdouble => {
+ const lhs_val = lhs.toFloat(f128);
+ const rhs_val = rhs.toFloat(f128);
+ return Value.Tag.float_128.create(arena, lhs_val + rhs_val);
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn floatSub(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: *Allocator,
+ ) !Value {
+ switch (float_type.tag()) {
+ .f16 => {
+ @panic("TODO add __trunctfhf2 to compiler-rt");
+ //const lhs_val = lhs.toFloat(f16);
+ //const rhs_val = rhs.toFloat(f16);
+ //return Value.Tag.float_16.create(arena, lhs_val - rhs_val);
+ },
+ .f32 => {
+ const lhs_val = lhs.toFloat(f32);
+ const rhs_val = rhs.toFloat(f32);
+ return Value.Tag.float_32.create(arena, lhs_val - rhs_val);
+ },
+ .f64 => {
+ const lhs_val = lhs.toFloat(f64);
+ const rhs_val = rhs.toFloat(f64);
+ return Value.Tag.float_64.create(arena, lhs_val - rhs_val);
+ },
+ .f128, .comptime_float, .c_longdouble => {
+ const lhs_val = lhs.toFloat(f128);
+ const rhs_val = rhs.toFloat(f128);
+ return Value.Tag.float_128.create(arena, lhs_val - rhs_val);
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn floatDiv(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: *Allocator,
+ ) !Value {
+ switch (float_type.tag()) {
+ .f16 => {
+ @panic("TODO add __trunctfhf2 to compiler-rt");
+ //const lhs_val = lhs.toFloat(f16);
+ //const rhs_val = rhs.toFloat(f16);
+ //return Value.Tag.float_16.create(arena, lhs_val / rhs_val);
+ },
+ .f32 => {
+ const lhs_val = lhs.toFloat(f32);
+ const rhs_val = rhs.toFloat(f32);
+ return Value.Tag.float_32.create(arena, lhs_val / rhs_val);
+ },
+ .f64 => {
+ const lhs_val = lhs.toFloat(f64);
+ const rhs_val = rhs.toFloat(f64);
+ return Value.Tag.float_64.create(arena, lhs_val / rhs_val);
+ },
+ .f128, .comptime_float, .c_longdouble => {
+ const lhs_val = lhs.toFloat(f128);
+ const rhs_val = rhs.toFloat(f128);
+ return Value.Tag.float_128.create(arena, lhs_val / rhs_val);
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn floatMul(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: *Allocator,
+ ) !Value {
+ switch (float_type.tag()) {
+ .f16 => {
+ @panic("TODO add __trunctfhf2 to compiler-rt");
+ //const lhs_val = lhs.toFloat(f16);
+ //const rhs_val = rhs.toFloat(f16);
+ //return Value.Tag.float_16.create(arena, lhs_val * rhs_val);
+ },
+ .f32 => {
+ const lhs_val = lhs.toFloat(f32);
+ const rhs_val = rhs.toFloat(f32);
+ return Value.Tag.float_32.create(arena, lhs_val * rhs_val);
+ },
+ .f64 => {
+ const lhs_val = lhs.toFloat(f64);
+ const rhs_val = rhs.toFloat(f64);
+ return Value.Tag.float_64.create(arena, lhs_val * rhs_val);
+ },
+ .f128, .comptime_float, .c_longdouble => {
+ const lhs_val = lhs.toFloat(f128);
+ const rhs_val = rhs.toFloat(f128);
+ return Value.Tag.float_128.create(arena, lhs_val * rhs_val);
+ },
+ else => unreachable,
+ }
+ }
+
/// This type is not copyable since it may contain pointers to its inner data.
pub const Payload = struct {
tag: Tag,
diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig
index 8f0f20cdf5..87de1c9fe5 100644
--- a/test/behavior/basic.zig
+++ b/test/behavior/basic.zig
@@ -1,3 +1,6 @@
+const std = @import("std");
+const expect = std.testing.expect;
+
// normal comment
/// this is a documentation comment
@@ -7,3 +10,11 @@ fn emptyFunctionWithComments() void {}
test "empty function with comments" {
emptyFunctionWithComments();
}
+
+test "truncate" {
+ try expect(testTruncate(0x10fd) == 0xfd);
+ comptime try expect(testTruncate(0x10fd) == 0xfd);
+}
+fn testTruncate(x: u32) u8 {
+ return @truncate(u8, x);
+}
diff --git a/test/behavior/misc.zig b/test/behavior/misc.zig
index ba38d6327c..700e043313 100644
--- a/test/behavior/misc.zig
+++ b/test/behavior/misc.zig
@@ -5,13 +5,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;
const mem = std.mem;
const builtin = @import("builtin");
-test "truncate" {
- try expect(testTruncate(0x10fd) == 0xfd);
-}
-fn testTruncate(x: u32) u8 {
- return @truncate(u8, x);
-}
-
fn first4KeysOfHomeRow() []const u8 {
return "aoeu";
}
From dae4c18aa7999a866b6b145ed3c88cb6c06852be Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 1 Aug 2021 22:04:18 -0700
Subject: [PATCH 60/96] stage2: ZIR encodes comptime parameters
`func_extended` ZIR instructions now have a one of the unused flags used
as a `has_comptime_bits` boolean. When set, it means 1 or more
parameters are `comptime`. In this case, there is a u32 per every 32
parameters (usually just 1 u32) with each bit indicating whether the
corresponding parameter is `comptime`.
Sema uses this information to correctly mark generic functions as
generic. There is now a TODO compile error in place in case a generic
function call happens. A future commit will do the generic function call
implementation.
---
src/AstGen.zig | 66 +++++++++++++++++++++++++++++++++++++++++++++++++-
src/Sema.zig | 29 +++++++++++++++++++++-
src/Zir.zig | 28 ++++++++++++++++++---
src/type.zig | 15 ++++++++++++
4 files changed, 132 insertions(+), 6 deletions(-)
diff --git a/src/AstGen.zig b/src/AstGen.zig
index b5e5d60b2c..20480ab33b 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -1064,11 +1064,28 @@ fn fnProtoExpr(
const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
defer gpa.free(param_types);
+ const bits_per_param = 1;
+ const params_per_u32 = 32 / bits_per_param;
+ // We only need this if there are greater than params_per_u32 fields.
+ var bit_bag = ArrayListUnmanaged(u32){};
+ defer bit_bag.deinit(gpa);
+ var cur_bit_bag: u32 = 0;
var is_var_args = false;
{
var param_type_i: usize = 0;
var it = fn_proto.iterate(tree.*);
while (it.next()) |param| : (param_type_i += 1) {
+ if (param_type_i % params_per_u32 == 0 and param_type_i != 0) {
+ try bit_bag.append(gpa, cur_bit_bag);
+ cur_bit_bag = 0;
+ }
+ const is_comptime = if (param.comptime_noalias) |token|
+ token_tags[token] == .keyword_comptime
+ else
+ false;
+ cur_bit_bag = (cur_bit_bag >> bits_per_param) |
+ (@as(u32, @boolToInt(is_comptime)) << 31);
+
if (param.anytype_ellipsis3) |token| {
switch (token_tags[token]) {
.keyword_anytype => {
@@ -1088,6 +1105,11 @@ fn fnProtoExpr(
try expr(gz, scope, .{ .ty = .type_type }, param_type_node);
}
assert(param_type_i == param_count);
+
+ const empty_slot_count = params_per_u32 - (param_type_i % params_per_u32);
+ if (empty_slot_count < params_per_u32) {
+ cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_param);
+ }
}
const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
@@ -1131,6 +1153,8 @@ fn fnProtoExpr(
.is_inferred_error = false,
.is_test = false,
.is_extern = false,
+ .cur_bit_bag = cur_bit_bag,
+ .bit_bag = bit_bag.items,
});
return rvalue(gz, rl, result, fn_proto.ast.proto_node);
}
@@ -2916,11 +2940,28 @@ fn fnDecl(
const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
defer gpa.free(param_types);
+ const bits_per_param = 1;
+ const params_per_u32 = 32 / bits_per_param;
+ // We only need this if there are greater than params_per_u32 fields.
+ var bit_bag = ArrayListUnmanaged(u32){};
+ defer bit_bag.deinit(gpa);
+ var cur_bit_bag: u32 = 0;
var is_var_args = false;
{
var param_type_i: usize = 0;
var it = fn_proto.iterate(tree.*);
while (it.next()) |param| : (param_type_i += 1) {
+ if (param_type_i % params_per_u32 == 0 and param_type_i != 0) {
+ try bit_bag.append(gpa, cur_bit_bag);
+ cur_bit_bag = 0;
+ }
+ const is_comptime = if (param.comptime_noalias) |token|
+ token_tags[token] == .keyword_comptime
+ else
+ false;
+ cur_bit_bag = (cur_bit_bag >> bits_per_param) |
+ (@as(u32, @boolToInt(is_comptime)) << 31);
+
if (param.anytype_ellipsis3) |token| {
switch (token_tags[token]) {
.keyword_anytype => {
@@ -2940,6 +2981,11 @@ fn fnDecl(
try expr(&decl_gz, &decl_gz.base, .{ .ty = .type_type }, param_type_node);
}
assert(param_type_i == param_count);
+
+ const empty_slot_count = params_per_u32 - (param_type_i % params_per_u32);
+ if (empty_slot_count < params_per_u32) {
+ cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_param);
+ }
}
const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: {
@@ -3001,6 +3047,8 @@ fn fnDecl(
.is_inferred_error = false,
.is_test = false,
.is_extern = true,
+ .cur_bit_bag = cur_bit_bag,
+ .bit_bag = bit_bag.items,
});
} else func: {
if (is_var_args) {
@@ -3094,6 +3142,8 @@ fn fnDecl(
.is_inferred_error = is_inferred_error,
.is_test = false,
.is_extern = false,
+ .cur_bit_bag = cur_bit_bag,
+ .bit_bag = bit_bag.items,
});
};
@@ -3439,6 +3489,8 @@ fn testDecl(
.is_inferred_error = true,
.is_test = true,
.is_extern = false,
+ .cur_bit_bag = 0,
+ .bit_bag = &.{},
});
_ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
@@ -9135,6 +9187,8 @@ const GenZir = struct {
is_inferred_error: bool,
is_test: bool,
is_extern: bool,
+ cur_bit_bag: u32,
+ bit_bag: []const u32,
}) !Zir.Inst.Ref {
assert(args.src_node != 0);
assert(args.ret_ty != .none);
@@ -9172,13 +9226,18 @@ const GenZir = struct {
src_locs = &src_locs_buffer;
}
+ const any_are_comptime = args.cur_bit_bag != 0 or for (args.bit_bag) |x| {
+ if (x != 0) break true;
+ } else false;
+
if (args.cc != .none or args.lib_name != 0 or
args.is_var_args or args.is_test or args.align_inst != .none or
- args.is_extern)
+ args.is_extern or any_are_comptime)
{
try astgen.extra.ensureUnusedCapacity(
gpa,
@typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
+ @boolToInt(any_are_comptime) + args.bit_bag.len +
args.param_types.len + args.body.len + src_locs.len +
@boolToInt(args.lib_name != 0) +
@boolToInt(args.align_inst != .none) +
@@ -9199,6 +9258,10 @@ const GenZir = struct {
if (args.align_inst != .none) {
astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
}
+ if (any_are_comptime) {
+ astgen.extra.appendSliceAssumeCapacity(args.bit_bag); // Likely empty.
+ astgen.extra.appendAssumeCapacity(args.cur_bit_bag);
+ }
astgen.appendRefsAssumeCapacity(args.param_types);
astgen.extra.appendSliceAssumeCapacity(args.body);
astgen.extra.appendSliceAssumeCapacity(src_locs);
@@ -9216,6 +9279,7 @@ const GenZir = struct {
.has_align = args.align_inst != .none,
.is_test = args.is_test,
.is_extern = args.is_extern,
+ .has_comptime_bits = any_are_comptime,
}),
.operand = payload_index,
} },
diff --git a/src/Sema.zig b/src/Sema.zig
index 6b281f8569..753ef8fb9c 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -104,6 +104,9 @@ pub fn analyzeFnBody(
extra_index += @boolToInt(small.has_lib_name);
extra_index += @boolToInt(small.has_cc);
extra_index += @boolToInt(small.has_align);
+ if (small.has_comptime_bits) {
+ extra_index += (extra.data.param_types_len + 31) / 32;
+ }
extra_index += extra.data.param_types_len;
const body = sema.code.extra[extra_index..][0..extra.data.body_len];
break :blk body;
@@ -2533,6 +2536,9 @@ fn analyzeCall(
break :res result;
} else res: {
+ if (func_ty.fnIsGeneric()) {
+ return sema.mod.fail(&block.base, func_src, "TODO implement generic fn call", .{});
+ }
try sema.requireRuntimeBlock(block, call_src);
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +
args.len);
@@ -3208,6 +3214,7 @@ fn zirFunc(
false,
src_locs,
null,
+ &.{},
);
}
@@ -3225,6 +3232,7 @@ fn funcCommon(
is_extern: bool,
src_locs: Zir.Inst.Func.SrcLocs,
opt_lib_name: ?[]const u8,
+ comptime_bits: []const u32,
) CompileError!Air.Inst.Ref {
const src: LazySrcLoc = .{ .node_offset = src_node_offset };
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
@@ -3257,13 +3265,23 @@ fn funcCommon(
}
}
+ var any_are_comptime = false;
const param_types = try sema.arena.alloc(Type, zir_param_types.len);
for (zir_param_types) |param_type, i| {
// TODO make a compile error from `resolveType` report the source location
// of the specific parameter. Will need to take a similar strategy as
// `resolveSwitchItemVal` to avoid resolving the source location unless
// we actually need to report an error.
- param_types[i] = try sema.resolveType(block, src, param_type);
+ const param_src = src;
+ param_types[i] = try sema.resolveType(block, param_src, param_type);
+
+ any_are_comptime = any_are_comptime or blk: {
+ if (comptime_bits.len == 0)
+ break :blk false;
+ const bag = comptime_bits[i / 32];
+ const is_comptime = @truncate(u1, bag >> @intCast(u5, i % 32)) != 0;
+ break :blk is_comptime;
+ };
}
if (align_val.tag() != .null_value) {
@@ -3286,6 +3304,7 @@ fn funcCommon(
.return_type = return_type,
.cc = cc,
.is_var_args = var_args,
+ .is_generic = any_are_comptime,
});
};
@@ -6526,6 +6545,13 @@ fn zirFuncExtended(
break :blk align_tv.val;
} else Value.initTag(.null_value);
+ const comptime_bits: []const u32 = if (!small.has_comptime_bits) &.{} else blk: {
+ const amt = (extra.data.param_types_len + 31) / 32;
+ const bit_bags = sema.code.extra[extra_index..][0..amt];
+ extra_index += amt;
+ break :blk bit_bags;
+ };
+
const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
extra_index += param_types.len;
@@ -6554,6 +6580,7 @@ fn zirFuncExtended(
is_extern,
src_locs,
lib_name,
+ comptime_bits,
);
}
diff --git a/src/Zir.zig b/src/Zir.zig
index a8320b65d4..109ae3b186 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -2226,9 +2226,13 @@ pub const Inst = struct {
/// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
/// 1. cc: Ref, // if has_cc is set
/// 2. align: Ref, // if has_align is set
- /// 3. param_type: Ref // for each param_types_len
- /// 4. body: Index // for each body_len
- /// 5. src_locs: Func.SrcLocs // if body_len != 0
+ /// 3. comptime_bits: u32 // for every 32 parameters, if has_comptime_bits is set
+ /// - sets of 1 bit:
+ /// 0bX: whether corresponding parameter is comptime
+ /// 4. param_type: Ref // for each param_types_len
+ /// - `none` indicates that the param type is `anytype`.
+ /// 5. body: Index // for each body_len
+ /// 6. src_locs: Func.SrcLocs // if body_len != 0
pub const ExtendedFunc = struct {
src_node: i32,
return_type: Ref,
@@ -2243,7 +2247,8 @@ pub const Inst = struct {
has_align: bool,
is_test: bool,
is_extern: bool,
- _: u9 = undefined,
+ has_comptime_bits: bool,
+ _: u8 = undefined,
};
};
@@ -4291,6 +4296,7 @@ const Writer = struct {
body,
src,
src_locs,
+ &.{},
);
}
@@ -4317,6 +4323,13 @@ const Writer = struct {
break :blk align_inst;
};
+ const comptime_bits: []const u32 = if (!small.has_comptime_bits) &.{} else blk: {
+ const amt = (extra.data.param_types_len + 31) / 32;
+ const bit_bags = self.code.extra[extra_index..][0..amt];
+ extra_index += amt;
+ break :blk bit_bags;
+ };
+
const param_types = self.code.refSlice(extra_index, extra.data.param_types_len);
extra_index += param_types.len;
@@ -4339,6 +4352,7 @@ const Writer = struct {
body,
src,
src_locs,
+ comptime_bits,
);
}
@@ -4422,10 +4436,16 @@ const Writer = struct {
body: []const Inst.Index,
src: LazySrcLoc,
src_locs: Zir.Inst.Func.SrcLocs,
+ comptime_bits: []const u32,
) !void {
try stream.writeAll("[");
for (param_types) |param_type, i| {
if (i != 0) try stream.writeAll(", ");
+ if (comptime_bits.len != 0) {
+ const bag = comptime_bits[i / 32];
+ const is_comptime = @truncate(u1, bag >> @intCast(u5, i % 32)) != 0;
+ try self.writeFlag(stream, "comptime ", is_comptime);
+ }
try self.writeInstRef(stream, param_type);
}
try stream.writeAll("], ");
diff --git a/src/type.zig b/src/type.zig
index 82c28ef398..a8c3d77bbb 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -764,6 +764,7 @@ pub const Type = extern union {
.param_types = param_types,
.cc = payload.cc,
.is_var_args = payload.is_var_args,
+ .is_generic = payload.is_generic,
});
},
.pointer => {
@@ -2407,6 +2408,19 @@ pub const Type = extern union {
};
}
+ /// Asserts the type is a function.
+ pub fn fnIsGeneric(self: Type) bool {
+ return switch (self.tag()) {
+ .fn_noreturn_no_args => false,
+ .fn_void_no_args => false,
+ .fn_naked_noreturn_no_args => false,
+ .fn_ccc_void_no_args => false,
+ .function => self.castTag(.function).?.data.is_generic,
+
+ else => unreachable,
+ };
+ }
+
pub fn isNumeric(self: Type) bool {
return switch (self.tag()) {
.f16,
@@ -3214,6 +3228,7 @@ pub const Type = extern union {
return_type: Type,
cc: std.builtin.CallingConvention,
is_var_args: bool,
+ is_generic: bool,
},
};
From b465037a65dd6a31c5865086ec4392a1d3a372bc Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 1 Aug 2021 23:27:38 -0700
Subject: [PATCH 61/96] move some behavior tests to the "passing for stage2"
section
---
test/behavior/basic.zig | 65 +++++++++++++++++++++++++++
test/behavior/misc.zig | 92 --------------------------------------
test/behavior/widening.zig | 11 +++++
3 files changed, 76 insertions(+), 92 deletions(-)
diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig
index 87de1c9fe5..c5c2972ffc 100644
--- a/test/behavior/basic.zig
+++ b/test/behavior/basic.zig
@@ -18,3 +18,68 @@ test "truncate" {
fn testTruncate(x: u32) u8 {
return @truncate(u8, x);
}
+
+const g1: i32 = 1233 + 1;
+var g2: i32 = 0;
+
+test "global variables" {
+ try expect(g2 == 0);
+ g2 = g1;
+ try expect(g2 == 1234);
+}
+
+test "comptime keyword on expressions" {
+ const x: i32 = comptime x: {
+ break :x 1 + 2 + 3;
+ };
+ try expect(x == comptime 6);
+}
+
+test "type equality" {
+ try expect(*const u8 != *u8);
+}
+
+test "pointer dereferencing" {
+ var x = @as(i32, 3);
+ const y = &x;
+
+ y.* += 1;
+
+ try expect(x == 4);
+ try expect(y.* == 4);
+}
+
+test "const expression eval handling of variables" {
+ var x = true;
+ while (x) {
+ x = false;
+ }
+}
+
+test "character literals" {
+ try expect('\'' == single_quote);
+}
+const single_quote = '\'';
+
+test "non const ptr to aliased type" {
+ const int = i32;
+ try expect(?*int == ?*i32);
+}
+
+test "cold function" {
+ thisIsAColdFn();
+ comptime thisIsAColdFn();
+}
+
+fn thisIsAColdFn() void {
+ @setCold(true);
+}
+
+test "unicode escape in character literal" {
+ var a: u24 = '\u{01f4a9}';
+ try expect(a == 128169);
+}
+
+test "unicode character in character literal" {
+ try expect('💩' == 128169);
+}
diff --git a/test/behavior/misc.zig b/test/behavior/misc.zig
index 700e043313..ddb90773d8 100644
--- a/test/behavior/misc.zig
+++ b/test/behavior/misc.zig
@@ -13,15 +13,6 @@ test "return string from function" {
try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
}
-const g1: i32 = 1233 + 1;
-var g2: i32 = 0;
-
-test "global variables" {
- try expect(g2 == 0);
- g2 = g1;
- try expect(g2 == 1234);
-}
-
test "memcpy and memset intrinsics" {
var foo: [20]u8 = undefined;
var bar: [20]u8 = undefined;
@@ -32,13 +23,6 @@ test "memcpy and memset intrinsics" {
if (bar[11] != 'A') unreachable;
}
-test "builtin static eval" {
- const x: i32 = comptime x: {
- break :x 1 + 2 + 3;
- };
- try expect(x == comptime 6);
-}
-
test "slicing" {
var array: [20]i32 = undefined;
@@ -148,10 +132,6 @@ test "multiline C string" {
try expect(std.cstr.cmp(s1, s2) == 0);
}
-test "type equality" {
- try expect(*const u8 != *u8);
-}
-
const global_a: i32 = 1234;
const global_b: *const i32 = &global_a;
const global_c: *const f32 = @ptrCast(*const f32, global_b);
@@ -187,17 +167,6 @@ fn testCastUndefined(x: []const u8) void {
_ = x;
}
-test "cast small unsigned to larger signed" {
- try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200));
- try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999));
-}
-fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
- return x;
-}
-fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
- return x;
-}
-
test "implicit cast after unreachable" {
try expect(outer() == 1234);
}
@@ -208,16 +177,6 @@ fn outer() i64 {
return inner();
}
-test "pointer dereferencing" {
- var x = @as(i32, 3);
- const y = &x;
-
- y.* += 1;
-
- try expect(x == 4);
- try expect(y.* == 4);
-}
-
test "call result of if else expression" {
try expect(mem.eql(u8, f2(true), "a"));
try expect(mem.eql(u8, f2(false), "b"));
@@ -232,13 +191,6 @@ fn fB() []const u8 {
return "b";
}
-test "const expression eval handling of variables" {
- var x = true;
- while (x) {
- x = false;
- }
-}
-
test "constant enum initialization with differing sizes" {
try test3_1(test3_foo);
try test3_2(test3_bar);
@@ -277,11 +229,6 @@ fn test3_2(f: Test3Foo) !void {
}
}
-test "character literals" {
- try expect('\'' == single_quote);
-}
-const single_quote = '\'';
-
test "take address of parameter" {
try testTakeAddressOfParameter(12.34);
}
@@ -330,11 +277,6 @@ fn testPointerToVoidReturnType2() *const void {
return &test_pointer_to_void_return_type_x;
}
-test "non const ptr to aliased type" {
- const int = i32;
- try expect(?*int == ?*i32);
-}
-
test "array 2D const double ptr" {
const rect_2d_vertexes = [_][1]f32{
[_]f32{1.0},
@@ -349,22 +291,6 @@ fn testArray2DConstDoublePtr(ptr: *const f32) !void {
try expect(ptr2[1] == 2.0);
}
-const AStruct = struct {
- x: i32,
-};
-const AnEnum = enum {
- One,
- Two,
-};
-const AUnionEnum = union(enum) {
- One: i32,
- Two: void,
-};
-const AUnion = union {
- One: void,
- Two: void,
-};
-
test "double implicit cast in same expression" {
var x = @as(i32, @as(u16, nine()));
try expect(x == 9);
@@ -440,15 +366,6 @@ test "function closes over local const" {
try expect(x == 1);
}
-test "cold function" {
- thisIsAColdFn();
- comptime thisIsAColdFn();
-}
-
-fn thisIsAColdFn() void {
- @setCold(true);
-}
-
const PackedStruct = packed struct {
a: u8,
b: u8,
@@ -562,15 +479,6 @@ test "thread local variable" {
try expect(S.t == 1235);
}
-test "unicode escape in character literal" {
- var a: u24 = '\u{01f4a9}';
- try expect(a == 128169);
-}
-
-test "unicode character in character literal" {
- try expect('💩' == 128169);
-}
-
test "result location zero sized array inside struct field implicit cast to slice" {
const E = struct {
entries: []u32,
diff --git a/test/behavior/widening.zig b/test/behavior/widening.zig
index dfa70ac4b2..19abf767b8 100644
--- a/test/behavior/widening.zig
+++ b/test/behavior/widening.zig
@@ -37,3 +37,14 @@ test "float widening f16 to f128" {
var y: f128 = x;
try expect(x == y);
}
+
+test "cast small unsigned to larger signed" {
+ try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200));
+ try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999));
+}
+fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
+ return x;
+}
+fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
+ return x;
+}
From 934df5bd448e7e27f2142d0d9ceec534f391c7f5 Mon Sep 17 00:00:00 2001
From: N00byEdge
Date: Fri, 30 Jul 2021 19:04:18 +0200
Subject: [PATCH 62/96] Make linux syscalls accessible with non-Linux target OS
---
lib/std/os/linux/arm-eabi.zig | 1 +
lib/std/os/linux/arm64.zig | 1 +
lib/std/os/linux/i386.zig | 1 +
lib/std/os/linux/mips.zig | 1 +
lib/std/os/linux/powerpc.zig | 1 +
lib/std/os/linux/powerpc64.zig | 1 +
lib/std/os/linux/riscv64.zig | 1 +
lib/std/os/linux/sparc64.zig | 1 +
lib/std/os/linux/thumb.zig | 1 +
lib/std/os/linux/x86_64.zig | 1 +
10 files changed, 10 insertions(+)
diff --git a/lib/std/os/linux/arm-eabi.zig b/lib/std/os/linux/arm-eabi.zig
index bac7048615..0fe74c9665 100644
--- a/lib/std/os/linux/arm-eabi.zig
+++ b/lib/std/os/linux/arm-eabi.zig
@@ -4,6 +4,7 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("svc #0"
diff --git a/lib/std/os/linux/arm64.zig b/lib/std/os/linux/arm64.zig
index dd5c3ef3af..0e1af98493 100644
--- a/lib/std/os/linux/arm64.zig
+++ b/lib/std/os/linux/arm64.zig
@@ -4,6 +4,7 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("svc #0"
diff --git a/lib/std/os/linux/i386.zig b/lib/std/os/linux/i386.zig
index c1ac6938fb..df58336eb0 100644
--- a/lib/std/os/linux/i386.zig
+++ b/lib/std/os/linux/i386.zig
@@ -4,6 +4,7 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("int $0x80"
diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig
index a04a592f3b..2ac029cae8 100644
--- a/lib/std/os/linux/mips.zig
+++ b/lib/std/os/linux/mips.zig
@@ -4,6 +4,7 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile (
diff --git a/lib/std/os/linux/powerpc.zig b/lib/std/os/linux/powerpc.zig
index 567ad2bc1f..341eb3f920 100644
--- a/lib/std/os/linux/powerpc.zig
+++ b/lib/std/os/linux/powerpc.zig
@@ -5,6 +5,7 @@
// and substantial portions of the software.
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile (
diff --git a/lib/std/os/linux/powerpc64.zig b/lib/std/os/linux/powerpc64.zig
index 567ad2bc1f..341eb3f920 100644
--- a/lib/std/os/linux/powerpc64.zig
+++ b/lib/std/os/linux/powerpc64.zig
@@ -5,6 +5,7 @@
// and substantial portions of the software.
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile (
diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig
index d58e080407..cab2ecfbaf 100644
--- a/lib/std/os/linux/riscv64.zig
+++ b/lib/std/os/linux/riscv64.zig
@@ -4,6 +4,7 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("ecall"
diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig
index 902940071e..cbe5ee3b70 100644
--- a/lib/std/os/linux/sparc64.zig
+++ b/lib/std/os/linux/sparc64.zig
@@ -1,4 +1,5 @@
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
pub fn syscall_pipe(fd: *[2]i32) usize {
return asm volatile (
diff --git a/lib/std/os/linux/thumb.zig b/lib/std/os/linux/thumb.zig
index 5db9d2cbf4..955c3420d4 100644
--- a/lib/std/os/linux/thumb.zig
+++ b/lib/std/os/linux/thumb.zig
@@ -4,6 +4,7 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
// The syscall interface is identical to the ARM one but we're facing an extra
// challenge: r7, the register where the syscall number is stored, may be
diff --git a/lib/std/os/linux/x86_64.zig b/lib/std/os/linux/x86_64.zig
index b9b3ff47eb..da4206a521 100644
--- a/lib/std/os/linux/x86_64.zig
+++ b/lib/std/os/linux/x86_64.zig
@@ -4,6 +4,7 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
usingnamespace @import("../bits.zig");
+usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("syscall"
From 871f6343f4d36c5c048f3307e2a38d184e248826 Mon Sep 17 00:00:00 2001
From: N00byEdge
Date: Fri, 30 Jul 2021 19:27:41 +0200
Subject: [PATCH 63/96] Move iovec and log levels to bits/posix.zig
This lets only the OSes that uses them to import them, and removes
dependencies on bits.zig for the os//.zig files
---
lib/std/os/bits.zig | 29 -----------------------------
lib/std/os/bits/darwin.zig | 2 ++
lib/std/os/bits/dragonfly.zig | 2 ++
lib/std/os/bits/freebsd.zig | 2 ++
lib/std/os/bits/haiku.zig | 2 ++
lib/std/os/bits/linux.zig | 2 +-
lib/std/os/bits/netbsd.zig | 2 ++
lib/std/os/bits/openbsd.zig | 2 ++
lib/std/os/bits/posix.zig | 34 ++++++++++++++++++++++++++++++++++
lib/std/os/bits/wasi.zig | 4 ++++
lib/std/os/bits/windows.zig | 5 +++++
lib/std/os/linux/arm-eabi.zig | 1 -
lib/std/os/linux/arm64.zig | 1 -
lib/std/os/linux/i386.zig | 1 -
lib/std/os/linux/mips.zig | 1 -
lib/std/os/linux/powerpc.zig | 1 -
lib/std/os/linux/powerpc64.zig | 1 -
lib/std/os/linux/riscv64.zig | 1 -
lib/std/os/linux/sparc64.zig | 1 -
lib/std/os/linux/thumb.zig | 1 -
lib/std/os/linux/x86_64.zig | 1 -
21 files changed, 56 insertions(+), 40 deletions(-)
create mode 100644 lib/std/os/bits/posix.zig
diff --git a/lib/std/os/bits.zig b/lib/std/os/bits.zig
index 5d1de28bad..5c39609182 100644
--- a/lib/std/os/bits.zig
+++ b/lib/std/os/bits.zig
@@ -25,32 +25,3 @@ pub usingnamespace switch (std.Target.current.os.tag) {
};
pub usingnamespace if (@hasDecl(root, "os") and @hasDecl(root.os, "bits")) root.os.bits else struct {};
-
-pub const iovec = extern struct {
- iov_base: [*]u8,
- iov_len: usize,
-};
-
-pub const iovec_const = extern struct {
- iov_base: [*]const u8,
- iov_len: usize,
-};
-
-// syslog
-
-/// system is unusable
-pub const LOG_EMERG = 0;
-/// action must be taken immediately
-pub const LOG_ALERT = 1;
-/// critical conditions
-pub const LOG_CRIT = 2;
-/// error conditions
-pub const LOG_ERR = 3;
-/// warning conditions
-pub const LOG_WARNING = 4;
-/// normal but significant condition
-pub const LOG_NOTICE = 5;
-/// informational
-pub const LOG_INFO = 6;
-/// debug-level messages
-pub const LOG_DEBUG = 7;
diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig
index be77722c05..91705c0d2e 100644
--- a/lib/std/os/bits/darwin.zig
+++ b/lib/std/os/bits/darwin.zig
@@ -7,6 +7,8 @@ const std = @import("../../std.zig");
const assert = std.debug.assert;
const maxInt = std.math.maxInt;
+pub usingnamespace @import("posix.zig");
+
// See: https://opensource.apple.com/source/xnu/xnu-6153.141.1/bsd/sys/_types.h.auto.html
// TODO: audit mode_t/pid_t, should likely be u16/i32
pub const fd_t = c_int;
diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig
index 9f6d3088ba..573721749c 100644
--- a/lib/std/os/bits/dragonfly.zig
+++ b/lib/std/os/bits/dragonfly.zig
@@ -6,6 +6,8 @@
const std = @import("../../std.zig");
const maxInt = std.math.maxInt;
+pub usingnamespace @import("posix.zig");
+
pub fn S_ISCHR(m: u32) bool {
return m & S_IFMT == S_IFCHR;
}
diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig
index 6d227a168a..1805941993 100644
--- a/lib/std/os/bits/freebsd.zig
+++ b/lib/std/os/bits/freebsd.zig
@@ -7,6 +7,8 @@ const std = @import("../../std.zig");
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
+pub usingnamespace @import("posix.zig");
+
pub const blksize_t = i32;
pub const blkcnt_t = i64;
pub const clockid_t = i32;
diff --git a/lib/std/os/bits/haiku.zig b/lib/std/os/bits/haiku.zig
index cb31166608..b3ea4aa0e2 100644
--- a/lib/std/os/bits/haiku.zig
+++ b/lib/std/os/bits/haiku.zig
@@ -6,6 +6,8 @@
const std = @import("../../std.zig");
const maxInt = std.math.maxInt;
+pub usingnamespace @import("posix.zig");
+
pub const fd_t = c_int;
pub const pid_t = c_int;
pub const uid_t = u32;
diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig
index 81bdfa6608..28683d47a9 100644
--- a/lib/std/os/bits/linux.zig
+++ b/lib/std/os/bits/linux.zig
@@ -6,7 +6,7 @@
const std = @import("../../std.zig");
const maxInt = std.math.maxInt;
const arch = @import("builtin").target.cpu.arch;
-usingnamespace @import("../bits.zig");
+pub usingnamespace @import("posix.zig");
pub usingnamespace switch (arch) {
.mips, .mipsel => @import("linux/errno-mips.zig"),
diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig
index d0240709e3..f3ece93493 100644
--- a/lib/std/os/bits/netbsd.zig
+++ b/lib/std/os/bits/netbsd.zig
@@ -7,6 +7,8 @@ const std = @import("../../std.zig");
const builtin = std.builtin;
const maxInt = std.math.maxInt;
+pub usingnamespace @import("posix.zig");
+
pub const blkcnt_t = i64;
pub const blksize_t = i32;
pub const clock_t = u32;
diff --git a/lib/std/os/bits/openbsd.zig b/lib/std/os/bits/openbsd.zig
index 3b9f8ccd4a..233ebcbd68 100644
--- a/lib/std/os/bits/openbsd.zig
+++ b/lib/std/os/bits/openbsd.zig
@@ -7,6 +7,8 @@ const std = @import("../../std.zig");
const builtin = std.builtin;
const maxInt = std.math.maxInt;
+pub usingnamespace @import("posix.zig");
+
pub const blkcnt_t = i64;
pub const blksize_t = i32;
pub const clock_t = i64;
diff --git a/lib/std/os/bits/posix.zig b/lib/std/os/bits/posix.zig
new file mode 100644
index 0000000000..0f015cd573
--- /dev/null
+++ b/lib/std/os/bits/posix.zig
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+pub const iovec = extern struct {
+ iov_base: [*]u8,
+ iov_len: usize,
+};
+
+pub const iovec_const = extern struct {
+ iov_base: [*]const u8,
+ iov_len: usize,
+};
+
+// syslog
+
+/// system is unusable
+pub const LOG_EMERG = 0;
+/// action must be taken immediately
+pub const LOG_ALERT = 1;
+/// critical conditions
+pub const LOG_CRIT = 2;
+/// error conditions
+pub const LOG_ERR = 3;
+/// warning conditions
+pub const LOG_WARNING = 4;
+/// normal but significant condition
+pub const LOG_NOTICE = 5;
+/// informational
+pub const LOG_INFO = 6;
+/// debug-level messages
+pub const LOG_DEBUG = 7;
diff --git a/lib/std/os/bits/wasi.zig b/lib/std/os/bits/wasi.zig
index 8b2f5c3351..5cb1334037 100644
--- a/lib/std/os/bits/wasi.zig
+++ b/lib/std/os/bits/wasi.zig
@@ -4,6 +4,10 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
// Convenience types and consts used by std.os module
+const posix = @import("posix.zig");
+pub const iovec = posix.iovec;
+pub const iovec_const = posix.iovec_const;
+
pub const STDIN_FILENO = 0;
pub const STDOUT_FILENO = 1;
pub const STDERR_FILENO = 2;
diff --git a/lib/std/os/bits/windows.zig b/lib/std/os/bits/windows.zig
index c5b101296b..05c50ffe47 100644
--- a/lib/std/os/bits/windows.zig
+++ b/lib/std/os/bits/windows.zig
@@ -8,6 +8,11 @@
usingnamespace @import("../windows/bits.zig");
const ws2_32 = @import("../windows/ws2_32.zig");
+// TODO: Stop using os.iovec in std.fs et al on Windows in the future
+const posix = @import("posix.zig");
+pub const iovec = posix.iovec;
+pub const iovec_const = posix.iovec_const;
+
pub const fd_t = HANDLE;
pub const ino_t = LARGE_INTEGER;
pub const pid_t = HANDLE;
diff --git a/lib/std/os/linux/arm-eabi.zig b/lib/std/os/linux/arm-eabi.zig
index 0fe74c9665..469b7299d1 100644
--- a/lib/std/os/linux/arm-eabi.zig
+++ b/lib/std/os/linux/arm-eabi.zig
@@ -3,7 +3,6 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
diff --git a/lib/std/os/linux/arm64.zig b/lib/std/os/linux/arm64.zig
index 0e1af98493..4c8306c048 100644
--- a/lib/std/os/linux/arm64.zig
+++ b/lib/std/os/linux/arm64.zig
@@ -3,7 +3,6 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
diff --git a/lib/std/os/linux/i386.zig b/lib/std/os/linux/i386.zig
index df58336eb0..2ec34bac40 100644
--- a/lib/std/os/linux/i386.zig
+++ b/lib/std/os/linux/i386.zig
@@ -3,7 +3,6 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig
index 2ac029cae8..85157f04f8 100644
--- a/lib/std/os/linux/mips.zig
+++ b/lib/std/os/linux/mips.zig
@@ -3,7 +3,6 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
diff --git a/lib/std/os/linux/powerpc.zig b/lib/std/os/linux/powerpc.zig
index 341eb3f920..611eee1c5f 100644
--- a/lib/std/os/linux/powerpc.zig
+++ b/lib/std/os/linux/powerpc.zig
@@ -4,7 +4,6 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
diff --git a/lib/std/os/linux/powerpc64.zig b/lib/std/os/linux/powerpc64.zig
index 341eb3f920..611eee1c5f 100644
--- a/lib/std/os/linux/powerpc64.zig
+++ b/lib/std/os/linux/powerpc64.zig
@@ -4,7 +4,6 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig
index cab2ecfbaf..3e2b15b599 100644
--- a/lib/std/os/linux/riscv64.zig
+++ b/lib/std/os/linux/riscv64.zig
@@ -3,7 +3,6 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig
index cbe5ee3b70..f347a0e88e 100644
--- a/lib/std/os/linux/sparc64.zig
+++ b/lib/std/os/linux/sparc64.zig
@@ -1,4 +1,3 @@
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
pub fn syscall_pipe(fd: *[2]i32) usize {
diff --git a/lib/std/os/linux/thumb.zig b/lib/std/os/linux/thumb.zig
index 955c3420d4..85f8bfc52b 100644
--- a/lib/std/os/linux/thumb.zig
+++ b/lib/std/os/linux/thumb.zig
@@ -3,7 +3,6 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
// The syscall interface is identical to the ARM one but we're facing an extra
diff --git a/lib/std/os/linux/x86_64.zig b/lib/std/os/linux/x86_64.zig
index da4206a521..5aa32c56c3 100644
--- a/lib/std/os/linux/x86_64.zig
+++ b/lib/std/os/linux/x86_64.zig
@@ -3,7 +3,6 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-usingnamespace @import("../bits.zig");
usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
From 68e26a2ceea85a149cb23286504cbdcec1ae814e Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Mon, 2 Aug 2021 11:10:07 +0200
Subject: [PATCH 64/96] std: check for overflow in writeCurrentStackTrace
On arm64 macOS, the address of the last frame is 0x0 rather than
a positive value like 0x1 on x86_64 macOS, therefore, we overflow
an integer trying to subtract 1 when printing the stack trace. This
patch fixes it by first checking for this condition before trying
to subtract 1.
Note that we do not need to signal the `SignalIterator` about this
as it will correctly detect this condition on the subsequent iteration
and return `null`, thus terminating the loop.
---
lib/std/debug.zig | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index f74d0b3f91..c3ef9dec4c 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -438,7 +438,12 @@ pub fn writeCurrentStackTrace(
}
var it = StackIterator.init(start_addr, null);
while (it.next()) |return_address| {
- try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
+ // On arm64 macOS, the address of the last frame is 0x0 rather than 0x1 as on x86_64 macOS,
+ // therefore, we do a check for `return_address == 0` before subtracting 1 from it to avoid
+ // an overflow. We do not need to signal `StackIterator` as it will correctly detect this
+ // condition on the subsequent iteration and return `null` thus terminating the loop.
+ const address = if (return_address == 0) return_address else return_address - 1;
+ try printSourceAtAddress(debug_info, out_stream, address, tty_config);
}
}
From 159cd528b164f77177e71309dee9fa79d2d5f4f4 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Mon, 2 Aug 2021 10:04:54 +0200
Subject: [PATCH 65/96] Add -Denable-macos-sdk explicit flag to build.zig
This way, we can explicitly signal if a test requires the presence
of macOS SDK to build. For instance, when testing our in-house
MachO linker for correctly linking Objective-C, we require the
presence of the SDK on the host system, and we can enforce this
with `-Denable-macos-sdk` flag to `zig build test-standalone`.
---
build.zig | 3 ++-
ci/azure/macos_script | 2 +-
test/standalone.zig | 4 +---
test/standalone/objc/build.zig | 18 ++++++++++++++++--
test/tests.zig | 19 +++++++++++++++++--
5 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/build.zig b/build.zig
index 40e1b36e71..f60cd573a4 100644
--- a/build.zig
+++ b/build.zig
@@ -61,6 +61,7 @@ pub fn build(b: *Builder) !void {
const omit_stage2 = b.option(bool, "omit-stage2", "Do not include stage2 behind a feature flag inside stage1") orelse false;
const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false;
const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (is_stage1 or static_llvm);
+ const enable_macos_sdk = b.option(bool, "enable-macos-sdk", "Run tests requiring presence of macOS SDK and frameworks") orelse false;
const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h");
if (!skip_install_lib_files) {
@@ -340,7 +341,7 @@ pub fn build(b: *Builder) !void {
));
toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
- toolchain_step.dependOn(tests.addStandaloneTests(b, test_filter, modes, skip_non_native, target));
+ toolchain_step.dependOn(tests.addStandaloneTests(b, test_filter, modes, skip_non_native, enable_macos_sdk, target));
toolchain_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));
toolchain_step.dependOn(tests.addCliTests(b, test_filter, modes));
toolchain_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
diff --git a/ci/azure/macos_script b/ci/azure/macos_script
index 01ac3f5838..d56ba63b6b 100755
--- a/ci/azure/macos_script
+++ b/ci/azure/macos_script
@@ -57,7 +57,7 @@ make $JOBS install
# TODO figure out why this causes a segmentation fault
# release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test
-release/bin/zig build test-toolchain
+release/bin/zig build test-toolchain -Denable-macos-sdk
release/bin/zig build test-std
release/bin/zig build docs
diff --git a/test/standalone.zig b/test/standalone.zig
index 52fba31828..9a32701ddd 100644
--- a/test/standalone.zig
+++ b/test/standalone.zig
@@ -38,9 +38,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
cases.addBuildFile("test/standalone/pie/build.zig", .{});
}
// Try to build and run an Objective-C executable.
- if (std.Target.current.os.tag == .macos) {
- cases.addBuildFile("test/standalone/objc/build.zig", .{ .build_modes = true });
- }
+ cases.addBuildFile("test/standalone/objc/build.zig", .{ .build_modes = true, .requires_macos_sdk = true });
// Ensure the development tools are buildable.
cases.add("tools/gen_spirv_spec.zig");
diff --git a/test/standalone/objc/build.zig b/test/standalone/objc/build.zig
index 30becd398c..7fdec514e7 100644
--- a/test/standalone/objc/build.zig
+++ b/test/standalone/objc/build.zig
@@ -1,5 +1,15 @@
const std = @import("std");
const Builder = std.build.Builder;
+const CrossTarget = std.zig.CrossTarget;
+
+fn isRunnableTarget(t: CrossTarget) bool {
+ // TODO I think we might be able to run this on Linux via Darling.
+ // Add a check for that here, and return true if Darling is available.
+ if (t.isNative() and t.getOsTag() == .macos)
+ return true
+ else
+ return false;
+}
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
@@ -15,8 +25,12 @@ pub fn build(b: *Builder) void {
exe.setBuildMode(mode);
exe.setTarget(target);
exe.linkLibC();
+ // TODO when we figure out how to ship framework stubs for cross-compilation,
+ // populate paths to the sysroot here.
exe.linkFramework("Foundation");
- const run_cmd = exe.run();
- test_step.dependOn(&run_cmd.step);
+ if (isRunnableTarget(target)) {
+ const run_cmd = exe.run();
+ test_step.dependOn(&run_cmd.step);
+ }
}
diff --git a/test/tests.zig b/test/tests.zig
index 0b736792b9..fc83137bc4 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -383,7 +383,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes:
return cases.step;
}
-pub fn addStandaloneTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode, skip_non_native: bool, target: std.zig.CrossTarget) *build.Step {
+pub fn addStandaloneTests(
+ b: *build.Builder,
+ test_filter: ?[]const u8,
+ modes: []const Mode,
+ skip_non_native: bool,
+ enable_macos_sdk: bool,
+ target: std.zig.CrossTarget,
+) *build.Step {
const cases = b.allocator.create(StandaloneContext) catch unreachable;
cases.* = StandaloneContext{
.b = b,
@@ -392,6 +399,7 @@ pub fn addStandaloneTests(b: *build.Builder, test_filter: ?[]const u8, modes: []
.test_filter = test_filter,
.modes = modes,
.skip_non_native = skip_non_native,
+ .enable_macos_sdk = enable_macos_sdk,
.target = target,
};
@@ -831,6 +839,7 @@ pub const StandaloneContext = struct {
test_filter: ?[]const u8,
modes: []const Mode,
skip_non_native: bool,
+ enable_macos_sdk: bool,
target: std.zig.CrossTarget,
pub fn addC(self: *StandaloneContext, root_src: []const u8) void {
@@ -841,9 +850,15 @@ pub const StandaloneContext = struct {
self.addAllArgs(root_src, false);
}
- pub fn addBuildFile(self: *StandaloneContext, build_file: []const u8, features: struct { build_modes: bool = false, cross_targets: bool = false }) void {
+ pub fn addBuildFile(self: *StandaloneContext, build_file: []const u8, features: struct {
+ build_modes: bool = false,
+ cross_targets: bool = false,
+ requires_macos_sdk: bool = false,
+ }) void {
const b = self.b;
+ if (features.requires_macos_sdk and !self.enable_macos_sdk) return;
+
const annotated_case_name = b.fmt("build {s}", .{build_file});
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
From f3b328ee8cb9c8340afaec510055d41aa4895583 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Mon, 2 Aug 2021 17:40:39 +0200
Subject: [PATCH 66/96] macho: refactor tracking of referenced dylibs
Now, index in the global referenced array hashmap is equivalent to
the dylib's ordinal in the final linked image.
---
src/link/MachO.zig | 72 +++++++++++++++++++++-------------------
src/link/MachO/Dylib.zig | 2 --
2 files changed, 38 insertions(+), 36 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 61b2ff888c..bfc0ab8ff6 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -63,9 +63,9 @@ entry_addr: ?u64 = null,
objects: std.ArrayListUnmanaged(Object) = .{},
archives: std.ArrayListUnmanaged(Archive) = .{},
-dylibs: std.ArrayListUnmanaged(Dylib) = .{},
-next_dylib_ordinal: u16 = 1,
+dylibs: std.ArrayListUnmanaged(Dylib) = .{},
+referenced_dylibs: std.AutoArrayHashMapUnmanaged(u16, void) = .{},
load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
@@ -929,6 +929,17 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
else => unreachable,
};
+ // TODO mimicking insertion of null symbol from incremental linker.
+ // This will need to moved.
+ try self.locals.append(self.base.allocator, .{
+ .n_strx = 0,
+ .n_type = macho.N_UNDF,
+ .n_sect = 0,
+ .n_desc = 0,
+ .n_value = 0,
+ });
+ try self.strtab.append(self.base.allocator, 0);
+
// Initialize section ordinals with null ordinal pointing at
// PAGEZERO segment.
try self.section_ordinals.append(self.base.allocator, .{
@@ -958,7 +969,8 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
}
try self.sortSections();
- try self.addRpaths(rpaths.items);
+ try self.addRpathLCs(rpaths.items);
+ try self.addLoadDylibLCs();
try self.addDataInCodeLC();
try self.addCodeSignatureLC();
try self.allocateTextSegment();
@@ -2196,17 +2208,6 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
}
fn resolveSymbols(self: *MachO) !void {
- // TODO mimicking insertion of null symbol from incremental linker.
- // This will need to moved.
- try self.locals.append(self.base.allocator, .{
- .n_strx = 0,
- .n_type = macho.N_UNDF,
- .n_sect = 0,
- .n_desc = 0,
- .n_value = 0,
- });
- try self.strtab.append(self.base.allocator, 0);
-
// First pass, resolve symbols in provided objects.
for (self.objects.items) |_, object_id| {
try self.resolveSymbolsInObject(@intCast(u16, object_id));
@@ -2335,9 +2336,6 @@ fn resolveSymbols(self: *MachO) !void {
});
}
- var referenced = std.AutoHashMap(u16, void).init(self.base.allocator);
- defer referenced.deinit();
-
loop: for (self.undefs.items) |sym| {
if (symbolIsNull(sym)) continue;
@@ -2345,23 +2343,12 @@ fn resolveSymbols(self: *MachO) !void {
for (self.dylibs.items) |*dylib, id| {
if (!dylib.symbols.contains(sym_name)) continue;
- if (!referenced.contains(@intCast(u16, id))) {
- // Add LC_LOAD_DYLIB load command for each referenced dylib/stub.
- dylib.ordinal = self.next_dylib_ordinal;
- const dylib_id = dylib.id orelse unreachable;
- var dylib_cmd = try commands.createLoadDylibCommand(
- self.base.allocator,
- dylib_id.name,
- dylib_id.timestamp,
- dylib_id.current_version,
- dylib_id.compatibility_version,
- );
- errdefer dylib_cmd.deinit(self.base.allocator);
- try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
- self.next_dylib_ordinal += 1;
- try referenced.putNoClobber(@intCast(u16, id), {});
+ const dylib_id = @intCast(u16, id);
+ if (!self.referenced_dylibs.contains(dylib_id)) {
+ try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {});
}
+ const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;
const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable;
const undef = &self.undefs.items[resolv.where_index];
const import_sym_index = @intCast(u32, self.imports.items.len);
@@ -2369,7 +2356,7 @@ fn resolveSymbols(self: *MachO) !void {
.n_strx = undef.n_strx,
.n_type = macho.N_UNDF | macho.N_EXT,
.n_sect = 0,
- .n_desc = packDylibOrdinal(dylib.ordinal.?),
+ .n_desc = packDylibOrdinal(@intCast(u16, ordinal + 1)),
.n_value = 0,
});
resolv.* = .{
@@ -2804,7 +2791,7 @@ fn addCodeSignatureLC(self: *MachO) !void {
}
}
-fn addRpaths(self: *MachO, rpaths: []const []const u8) !void {
+fn addRpathLCs(self: *MachO, rpaths: []const []const u8) !void {
for (rpaths) |rpath| {
const cmdsize = @intCast(u32, mem.alignForwardGeneric(
u64,
@@ -2823,6 +2810,22 @@ fn addRpaths(self: *MachO, rpaths: []const []const u8) !void {
}
}
+fn addLoadDylibLCs(self: *MachO) !void {
+ for (self.referenced_dylibs.keys()) |id| {
+ const dylib = self.dylibs.items[id];
+ const dylib_id = dylib.id orelse unreachable;
+ var dylib_cmd = try commands.createLoadDylibCommand(
+ self.base.allocator,
+ dylib_id.name,
+ dylib_id.timestamp,
+ dylib_id.current_version,
+ dylib_id.compatibility_version,
+ );
+ errdefer dylib_cmd.deinit(self.base.allocator);
+ try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
+ }
+}
+
fn flushZld(self: *MachO) !void {
self.load_commands_dirty = true;
try self.writeTextBlocks();
@@ -3353,6 +3356,7 @@ pub fn deinit(self: *MachO) void {
dylib.deinit(self.base.allocator);
}
self.dylibs.deinit(self.base.allocator);
+ self.referenced_dylibs.deinit(self.base.allocator);
for (self.load_commands.items) |*lc| {
lc.deinit(self.base.allocator);
diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig
index 7b2f94ba67..1d2833c764 100644
--- a/src/link/MachO/Dylib.zig
+++ b/src/link/MachO/Dylib.zig
@@ -22,8 +22,6 @@ name: []const u8,
header: ?macho.mach_header_64 = null,
-ordinal: ?u16 = null,
-
// The actual dylib contents we care about linking with will be embedded at
// an offset within a file if we are linking against a fat lib
library_offset: u64 = 0,
From bf25650974933cdb8c1314a85e0838257f6f4471 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Mon, 2 Aug 2021 18:15:27 +0200
Subject: [PATCH 67/96] macho: refactor management of section ordinals
Instead of storing a two-way relation (seg,sect) <=> ordinal
we get the latter with `getIndex((seg, sect))`.
---
src/link/MachO.zig | 55 ++++++++++++------------------------
src/link/MachO/Object.zig | 10 +++----
src/link/MachO/TextBlock.zig | 6 ++--
3 files changed, 26 insertions(+), 45 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index bfc0ab8ff6..d3412cec3d 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -168,8 +168,7 @@ strtab_needs_relocation: bool = false,
has_dices: bool = false,
has_stabs: bool = false,
-section_ordinals: std.ArrayListUnmanaged(MatchingSection) = .{},
-section_to_ordinal: std.AutoHashMapUnmanaged(MatchingSection, u8) = .{},
+section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{},
pending_updates: std.ArrayListUnmanaged(struct {
kind: enum {
@@ -940,13 +939,6 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
});
try self.strtab.append(self.base.allocator, 0);
- // Initialize section ordinals with null ordinal pointing at
- // PAGEZERO segment.
- try self.section_ordinals.append(self.base.allocator, .{
- .seg = 0,
- .sect = 0,
- });
-
try self.populateMetadata();
try self.parseInputFiles(positionals.items, self.base.options.sysroot);
try self.parseLibs(libs.items, self.base.options.sysroot);
@@ -1454,7 +1446,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
if (res) |match| {
- try self.createSectionOrdinal(match);
+ _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
}
return res;
@@ -1586,32 +1578,29 @@ fn sortSections(self: *MachO) !void {
{
// Create new section ordinals.
self.section_ordinals.clearRetainingCapacity();
- self.section_to_ordinal.clearRetainingCapacity();
- // First ordinal is always null
- self.section_ordinals.appendAssumeCapacity(.{
- .seg = 0,
- .sect = 0,
- });
const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
for (text_seg.sections.items) |_, sect_id| {
- try self.createSectionOrdinal(.{
+ const res = self.section_ordinals.getOrPutAssumeCapacity(.{
.seg = self.text_segment_cmd_index.?,
.sect = @intCast(u16, sect_id),
});
+ assert(!res.found_existing);
}
const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
for (data_const_seg.sections.items) |_, sect_id| {
- try self.createSectionOrdinal(.{
+ const res = self.section_ordinals.getOrPutAssumeCapacity(.{
.seg = self.data_const_segment_cmd_index.?,
.sect = @intCast(u16, sect_id),
});
+ assert(!res.found_existing);
}
const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
for (data_seg.sections.items) |_, sect_id| {
- try self.createSectionOrdinal(.{
+ const res = self.section_ordinals.getOrPutAssumeCapacity(.{
.seg = self.data_segment_cmd_index.?,
.sect = @intCast(u16, sect_id),
});
+ assert(!res.found_existing);
}
}
}
@@ -1740,7 +1729,7 @@ fn allocateTextBlocks(self: *MachO) !void {
const sect = seg.sections.items[match.sect];
var base_addr: u64 = sect.addr;
- const n_sect = self.section_to_ordinal.get(match) orelse unreachable;
+ const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
log.debug(" within section {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) });
log.debug(" {}", .{sect});
@@ -2262,7 +2251,7 @@ fn resolveSymbols(self: *MachO) !void {
.sect = self.common_section_index.?,
};
};
- try self.createSectionOrdinal(match);
+ _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
const size = sym.n_value;
const code = try self.base.allocator.alloc(u8, size);
@@ -2275,7 +2264,7 @@ fn resolveSymbols(self: *MachO) !void {
var nlist = macho.nlist_64{
.n_strx = sym.n_strx,
.n_type = macho.N_SECT,
- .n_sect = self.section_to_ordinal.get(match) orelse unreachable,
+ .n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1),
.n_desc = 0,
.n_value = 0,
};
@@ -2391,7 +2380,7 @@ fn resolveSymbols(self: *MachO) !void {
var nlist = macho.nlist_64{
.n_strx = undef.n_strx,
.n_type = macho.N_SECT,
- .n_sect = self.section_to_ordinal.get(match) orelse unreachable,
+ .n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1),
.n_desc = 0,
.n_value = 0,
};
@@ -2487,7 +2476,7 @@ fn populateMetadata(self: *MachO) !void {
.@"align" = alignment,
.flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
});
- try self.createSectionOrdinal(.{
+ _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
.seg = self.text_segment_cmd_index.?,
.sect = self.text_section_index.?,
});
@@ -2511,7 +2500,7 @@ fn populateMetadata(self: *MachO) !void {
.flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
.reserved2 = stub_size,
});
- try self.createSectionOrdinal(.{
+ _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
.seg = self.text_segment_cmd_index.?,
.sect = self.stubs_section_index.?,
});
@@ -2535,7 +2524,7 @@ fn populateMetadata(self: *MachO) !void {
.@"align" = alignment,
.flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
});
- try self.createSectionOrdinal(.{
+ _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
.seg = self.text_segment_cmd_index.?,
.sect = self.stub_helper_section_index.?,
});
@@ -2558,7 +2547,7 @@ fn populateMetadata(self: *MachO) !void {
.@"align" = 3, // 2^3 = @sizeOf(u64)
.flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
});
- try self.createSectionOrdinal(.{
+ _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
.seg = self.data_const_segment_cmd_index.?,
.sect = self.got_section_index.?,
});
@@ -2581,7 +2570,7 @@ fn populateMetadata(self: *MachO) !void {
.@"align" = 3, // 2^3 = @sizeOf(u64)
.flags = macho.S_LAZY_SYMBOL_POINTERS,
});
- try self.createSectionOrdinal(.{
+ _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
.seg = self.data_segment_cmd_index.?,
.sect = self.la_symbol_ptr_section_index.?,
});
@@ -2593,7 +2582,7 @@ fn populateMetadata(self: *MachO) !void {
try data_seg.addSection(self.base.allocator, "__data", .{
.@"align" = 3, // 2^3 = @sizeOf(u64)
});
- try self.createSectionOrdinal(.{
+ _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
.seg = self.data_segment_cmd_index.?,
.sect = self.data_section_index.?,
});
@@ -3324,7 +3313,6 @@ pub fn deinit(self: *MachO) void {
}
self.section_ordinals.deinit(self.base.allocator);
- self.section_to_ordinal.deinit(self.base.allocator);
self.pending_updates.deinit(self.base.allocator);
self.got_entries.deinit(self.base.allocator);
self.got_entries_map.deinit(self.base.allocator);
@@ -5882,13 +5870,6 @@ pub fn findFirst(comptime T: type, haystack: []T, start: usize, predicate: anyty
return i;
}
-fn createSectionOrdinal(self: *MachO, match: MatchingSection) !void {
- if (self.section_to_ordinal.contains(match)) return;
- const ordinal = @intCast(u8, self.section_ordinals.items.len);
- try self.section_ordinals.append(self.base.allocator, match);
- try self.section_to_ordinal.putNoClobber(self.base.allocator, match, ordinal);
-}
-
fn printSymtabAndTextBlock(self: *MachO) void {
log.debug("locals", .{});
for (self.locals.items) |sym, id| {
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 04071a1cdb..2e6a20ad4b 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -402,7 +402,7 @@ const TextBlockParser = struct {
const senior_nlist = aliases.pop();
const senior_sym = &context.macho_file.locals.items[senior_nlist.index];
- senior_sym.n_sect = context.macho_file.section_to_ordinal.get(context.match) orelse unreachable;
+ senior_sym.n_sect = @intCast(u8, context.macho_file.section_ordinals.getIndex(context.match).? + 1);
const start_addr = senior_nlist.nlist.n_value - self.section.addr;
const end_addr = if (next_nlist) |n| n.nlist.n_value - self.section.addr else self.section.size;
@@ -446,7 +446,7 @@ const TextBlockParser = struct {
for (aliases.items) |alias| {
block.aliases.appendAssumeCapacity(alias.index);
const sym = &context.macho_file.locals.items[alias.index];
- sym.n_sect = context.macho_file.section_to_ordinal.get(context.match) orelse unreachable;
+ sym.n_sect = @intCast(u8, context.macho_file.section_ordinals.getIndex(context.match).? + 1);
}
try block.parseRelocs(self.relocs, .{
@@ -588,7 +588,7 @@ pub fn parseTextBlocks(
try macho_file.locals.append(allocator, .{
.n_strx = try macho_file.makeString(sym_name),
.n_type = macho.N_SECT,
- .n_sect = macho_file.section_to_ordinal.get(match) orelse unreachable,
+ .n_sect = @intCast(u8, macho_file.section_ordinals.getIndex(match).? + 1),
.n_desc = 0,
.n_value = sect.addr,
});
@@ -733,7 +733,7 @@ pub fn parseTextBlocks(
try macho_file.locals.append(allocator, .{
.n_strx = try macho_file.makeString(sym_name),
.n_type = macho.N_SECT,
- .n_sect = macho_file.section_to_ordinal.get(match) orelse unreachable,
+ .n_sect = @intCast(u8, macho_file.section_ordinals.getIndex(match).? + 1),
.n_desc = 0,
.n_value = sect.addr,
});
@@ -781,7 +781,7 @@ pub fn parseTextBlocks(
const nlist = nlist_with_index.nlist;
const local_sym_index = self.symbol_mapping.get(nlist_with_index.index) orelse unreachable;
const local = &macho_file.locals.items[local_sym_index];
- local.n_sect = macho_file.section_to_ordinal.get(match) orelse unreachable;
+ local.n_sect = @intCast(u8, macho_file.section_ordinals.getIndex(match).? + 1);
const stab: ?TextBlock.Stab = if (self.debug_info) |di| blk: {
// TODO there has to be a better to handle this.
diff --git a/src/link/MachO/TextBlock.zig b/src/link/MachO/TextBlock.zig
index ef10d3fe09..55dc2db471 100644
--- a/src/link/MachO/TextBlock.zig
+++ b/src/link/MachO/TextBlock.zig
@@ -637,7 +637,7 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc
try context.macho_file.locals.append(context.allocator, .{
.n_strx = try context.macho_file.makeString(sym_name),
.n_type = macho.N_SECT,
- .n_sect = context.macho_file.section_to_ordinal.get(match) orelse unreachable,
+ .n_sect = @intCast(u8, context.macho_file.section_ordinals.getIndex(match).? + 1),
.n_desc = 0,
.n_value = sect.addr,
});
@@ -844,7 +844,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
},
.local => {
const source_sym = context.macho_file.locals.items[self.local_sym_index];
- const match = context.macho_file.section_ordinals.items[source_sym.n_sect];
+ const match = context.macho_file.section_ordinals.keys()[source_sym.n_sect - 1];
const seg = context.macho_file.load_commands.items[match.seg].Segment;
const sect = seg.sections.items[match.sect];
const sect_type = commands.sectionType(sect);
@@ -1108,7 +1108,7 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
const sym = macho_file.locals.items[rel.where_index];
const is_tlv = is_tlv: {
const source_sym = macho_file.locals.items[self.local_sym_index];
- const match = macho_file.section_ordinals.items[source_sym.n_sect];
+ const match = macho_file.section_ordinals.keys()[source_sym.n_sect - 1];
const seg = macho_file.load_commands.items[match.seg].Segment;
const sect = seg.sections.items[match.sect];
break :is_tlv commands.sectionType(sect) == macho.S_THREAD_LOCAL_VARIABLES;
From 41d7787b69a437e21351d103353fc2eefafb5d17 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Mon, 2 Aug 2021 19:48:23 +0200
Subject: [PATCH 68/96] macho: remove obsolete pack/unpack dylib ordinal fns
Remove some unused debugging machinery such as full printing of the
symtab after symbol resolution. It was there only for the time of
rewriting the linker.
---
src/link/MachO.zig | 94 +++++-----------------------------------------
1 file changed, 9 insertions(+), 85 deletions(-)
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index d3412cec3d..36d5bc6a87 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -970,7 +970,6 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
try self.allocateDataSegment();
self.allocateLinkeditSegment();
try self.allocateTextBlocks();
- self.printSymtabAndTextBlock();
try self.flushZld();
}
@@ -2345,7 +2344,7 @@ fn resolveSymbols(self: *MachO) !void {
.n_strx = undef.n_strx,
.n_type = macho.N_UNDF | macho.N_EXT,
.n_sect = 0,
- .n_desc = packDylibOrdinal(@intCast(u16, ordinal + 1)),
+ .n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER,
.n_value = 0,
});
resolv.* = .{
@@ -3021,7 +3020,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {
try pointers.append(.{
.offset = base_offset + i * @sizeOf(u64),
.segment_id = segment_id,
- .dylib_ordinal = unpackDylibOrdinal(sym.n_desc),
+ .dylib_ordinal = @divExact(sym.n_desc, macho.N_SYMBOL_RESOLVER),
.name = self.getString(sym.n_strx),
});
}
@@ -3046,7 +3045,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {
try pointers.append(.{
.offset = binding.offset + base_offset,
.segment_id = match.seg,
- .dylib_ordinal = unpackDylibOrdinal(bind_sym.n_desc),
+ .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
.name = self.getString(bind_sym.n_strx),
});
}
@@ -3093,7 +3092,7 @@ fn writeLazyBindInfoTableZld(self: *MachO) !void {
pointers.appendAssumeCapacity(.{
.offset = base_offset + i * @sizeOf(u64),
.segment_id = segment_id,
- .dylib_ordinal = unpackDylibOrdinal(sym.n_desc),
+ .dylib_ordinal = @divExact(sym.n_desc, macho.N_SYMBOL_RESOLVER),
.name = self.getString(sym.n_strx),
});
}
@@ -4395,7 +4394,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
.n_strx = n_strx,
.n_type = macho.N_UNDF | macho.N_EXT,
.n_sect = 0,
- .n_desc = packDylibOrdinal(1),
+ .n_desc = @intCast(u8, 1) * macho.N_SYMBOL_RESOLVER,
.n_value = 0,
});
try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
@@ -4541,7 +4540,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
.n_strx = n_strx,
.n_type = macho.N_UNDF | macho.N_EXT,
.n_sect = 0,
- .n_desc = packDylibOrdinal(1),
+ .n_desc = @intCast(u8, 1) * macho.N_SYMBOL_RESOLVER,
.n_value = 0,
});
try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
@@ -5423,7 +5422,7 @@ fn writeBindInfoTable(self: *MachO) !void {
try pointers.append(.{
.offset = base_offset + i * @sizeOf(u64),
.segment_id = segment_id,
- .dylib_ordinal = unpackDylibOrdinal(sym.n_desc),
+ .dylib_ordinal = @divExact(sym.n_desc, macho.N_SYMBOL_RESOLVER),
.name = self.getString(sym.n_strx),
});
}
@@ -5448,7 +5447,7 @@ fn writeBindInfoTable(self: *MachO) !void {
try pointers.append(.{
.offset = binding.offset + base_offset,
.segment_id = match.seg,
- .dylib_ordinal = unpackDylibOrdinal(bind_sym.n_desc),
+ .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
.name = self.getString(bind_sym.n_strx),
});
}
@@ -5507,7 +5506,7 @@ fn writeLazyBindInfoTable(self: *MachO) !void {
pointers.appendAssumeCapacity(.{
.offset = base_offset + i * @sizeOf(u64),
.segment_id = segment_id,
- .dylib_ordinal = unpackDylibOrdinal(sym.n_desc),
+ .dylib_ordinal = @divExact(sym.n_desc, macho.N_SYMBOL_RESOLVER),
.name = self.getString(sym.n_strx),
});
}
@@ -5849,14 +5848,6 @@ pub fn symbolIsTemp(sym: macho.nlist_64, sym_name: []const u8) bool {
return mem.startsWith(u8, sym_name, "l") or mem.startsWith(u8, sym_name, "L");
}
-fn packDylibOrdinal(ordinal: u16) u16 {
- return ordinal * macho.N_SYMBOL_RESOLVER;
-}
-
-fn unpackDylibOrdinal(pack: u16) u16 {
- return @divExact(pack, macho.N_SYMBOL_RESOLVER);
-}
-
pub fn findFirst(comptime T: type, haystack: []T, start: usize, predicate: anytype) usize {
if (!@hasDecl(@TypeOf(predicate), "predicate"))
@compileError("Predicate is required to define fn predicate(@This(), T) bool");
@@ -5869,70 +5860,3 @@ pub fn findFirst(comptime T: type, haystack: []T, start: usize, predicate: anyty
}
return i;
}
-
-fn printSymtabAndTextBlock(self: *MachO) void {
- log.debug("locals", .{});
- for (self.locals.items) |sym, id| {
- log.debug(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
- }
-
- log.debug("globals", .{});
- for (self.globals.items) |sym, id| {
- log.debug(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
- }
-
- log.debug("tentatives", .{});
- for (self.tentatives.items) |sym, id| {
- log.debug(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
- }
-
- log.debug("undefines", .{});
- for (self.undefs.items) |sym, id| {
- log.debug(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
- }
-
- log.debug("imports", .{});
- for (self.imports.items) |sym, id| {
- log.debug(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
- }
-
- {
- log.debug("symbol resolver", .{});
- var it = self.symbol_resolver.keyIterator();
- while (it.next()) |key_ptr| {
- const sym_name = self.getString(key_ptr.*);
- log.debug(" {s} => {}", .{ sym_name, self.symbol_resolver.get(key_ptr.*).? });
- }
- }
-
- log.debug("mappings", .{});
- for (self.objects.items) |object| {
- log.debug(" in object {s}", .{object.name});
- for (object.symtab.items) |sym, sym_id| {
- if (object.symbol_mapping.get(@intCast(u32, sym_id))) |local_id| {
- log.debug(" | {d} => {d}", .{ sym_id, local_id });
- } else {
- log.debug(" | {d} no local mapping for {s}", .{ sym_id, object.getString(sym.n_strx) });
- }
- }
- }
-
- {
- var it = self.blocks.iterator();
- while (it.next()) |entry| {
- const seg = self.load_commands.items[entry.key_ptr.seg].Segment;
- const sect = seg.sections.items[entry.key_ptr.sect];
-
- var block: *TextBlock = entry.value_ptr.*;
-
- log.debug("\n\n{s},{s} contents:", .{ commands.segmentName(sect), commands.sectionName(sect) });
- log.debug("{}", .{sect});
- log.debug("{}", .{block});
-
- while (block.prev) |prev| {
- block = prev;
- log.debug("{}", .{block});
- }
- }
- }
-}
From 1472dc3ddb6fd7932ff530e7a2fd3f0185c7353f Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 2 Aug 2021 20:35:55 -0700
Subject: [PATCH 69/96] stage2: update ZIR for generic functions
ZIR encoding for functions is changed in preparation for generic
function support. As an example:
```zig
const std = @import("std");
const expect = std.testing.expect;
test "example" {
var x: usize = 0;
x += checkSize(i32, 1);
x += checkSize(bool, true);
try expect(x == 5);
}
fn checkSize(comptime T: type, x: T) usize {
_ = x;
return @sizeOf(T);
}
```
Previous ZIR for the `checkSize` function:
```zir
[165] checkSize line(10) hash(0226f62e189fd0b1c5fca02cf4617562): %55 = block_inline({
%56 = decl_val("T") token_offset:11:35
%57 = as_node(@Ref.type_type, %56) node_offset:11:35
%69 = extended(func([comptime @Ref.type_type, %57], @Ref.usize_type, {
%58 = arg("T") token_offset:11:23
%59 = as_node(@Ref.type_type, %58) node_offset:11:35
%60 = arg("x") token_offset:11:32
%61 = dbg_stmt(11, 4)
```
ZIR for the `checkSize` function after this commit:
```zir
[157] checkSize line(10) hash(0226f62e189fd0b1c5fca02cf4617562): %55 = block_inline({
%56 = param_comptime("T", @Ref.type_type) token_offset:11:23
%57 = as_node(@Ref.type_type, %56) node_offset:11:35
%58 = param("x", %57) token_offset:11:32
%67 = func(@Ref.usize_type, {
%59 = dbg_stmt(11, 4)
```
Noted differences:
* Previously the type expression was redundantly repeated.
* Previously the parameter names were redundantly stored in the ZIR
extra array.
* Instead of `arg` ZIR instructions as the first instructions within a
function body, they are now outside the function body, in the same
block as the `func` instruction. There are variants:
- param
- param_comptime
- param_anytype
- param_anytype_comptime
* The param instructions additionally encode the type.
* Because of the param instructions, the `func` instruction no longer
encodes the list of parameter types or the comptime bits.
It's implied that Sema will collect the parameters so that when a `func`
instruction is encountered, they will be implicitly used to construct
the function's type. This is so that we can satisfy all 3 ways of
performing semantic analysis on a function:
1. runtime: Sema will insert AIR arg instructions for each parameter,
and insert into the Sema inst_map ZIR param => AIR arg.
2. comptime/inline: Sema will insert into the inst_map ZIR param =>
callsite arguments.
3. generic: Sema will map *only the comptime* ZIR param instructions to
the AIR instructions for the comptime arguments at the callsite, and
then re-run Sema for the function's Decl. This will produce a new
function which is the monomorphized function.
Additionally:
* AstGen: Update usage of deprecated `ensureCapacity` to
`ensureUnusedCapacity` or `ensureTotalCapacity`.
* Introduce `Type.fnInfo` for getting a bunch of data about a function
type at once, and use it in `analyzeCall`.
This commit starts a branch to implement generic functions in stage2.
Test regressions have not been addressed yet.
---
BRANCH_TODO | 9 ++
src/AstGen.zig | 424 +++++++++++++++++++++----------------------------
src/Module.zig | 2 +-
src/Sema.zig | 193 ++++++++++++++--------
src/Zir.zig | 121 +++++++-------
src/type.zig | 60 +++++--
6 files changed, 431 insertions(+), 378 deletions(-)
create mode 100644 BRANCH_TODO
diff --git a/BRANCH_TODO b/BRANCH_TODO
new file mode 100644
index 0000000000..bc0a67f799
--- /dev/null
+++ b/BRANCH_TODO
@@ -0,0 +1,9 @@
+* update arg instructions:
+ - runtime function call inserts AIR arg instructions and Sema map items for them
+ - comptime/inline function call inserts Sema map items for the args
+ - generic instantiation inserts Sema map items for the comptime args only, re-runs the
+ Decl ZIR to get the new Fn.
+* generic function call where it makes a new function
+* memoize the instantiation in a table
+* anytype with next parameter expression using it
+* comptime anytype
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 20480ab33b..0b78c839a0 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -42,7 +42,7 @@ const InnerError = error{ OutOfMemory, AnalysisFail };
fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
const fields = std.meta.fields(@TypeOf(extra));
- try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + fields.len);
+ try astgen.extra.ensureUnusedCapacity(astgen.gpa, fields.len);
return addExtraAssumeCapacity(astgen, extra);
}
@@ -259,6 +259,7 @@ pub const ResultLoc = union(enum) {
pub const align_rl: ResultLoc = .{ .ty = .u16_type };
pub const bool_rl: ResultLoc = .{ .ty = .bool_type };
+pub const type_rl: ResultLoc = .{ .ty = .type_type };
fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zir.Inst.Ref {
const prev_force_comptime = gz.force_comptime;
@@ -1036,7 +1037,6 @@ fn fnProtoExpr(
fn_proto: ast.full.FnProto,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
- const gpa = astgen.gpa;
const tree = astgen.tree;
const token_tags = tree.tokens.items(.tag);
@@ -1046,71 +1046,53 @@ fn fnProtoExpr(
};
assert(!is_extern);
- // The AST params array does not contain anytype and ... parameters.
- // We must iterate to count how many param types to allocate.
- const param_count = blk: {
- var count: usize = 0;
- var it = fn_proto.iterate(tree.*);
- while (it.next()) |param| {
- if (param.anytype_ellipsis3) |token| switch (token_tags[token]) {
- .ellipsis3 => break,
- .keyword_anytype => {},
- else => unreachable,
- };
- count += 1;
- }
- break :blk count;
- };
- const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
- defer gpa.free(param_types);
-
- const bits_per_param = 1;
- const params_per_u32 = 32 / bits_per_param;
- // We only need this if there are greater than params_per_u32 fields.
- var bit_bag = ArrayListUnmanaged(u32){};
- defer bit_bag.deinit(gpa);
- var cur_bit_bag: u32 = 0;
- var is_var_args = false;
- {
+ const is_var_args = is_var_args: {
var param_type_i: usize = 0;
var it = fn_proto.iterate(tree.*);
while (it.next()) |param| : (param_type_i += 1) {
- if (param_type_i % params_per_u32 == 0 and param_type_i != 0) {
- try bit_bag.append(gpa, cur_bit_bag);
- cur_bit_bag = 0;
- }
const is_comptime = if (param.comptime_noalias) |token|
token_tags[token] == .keyword_comptime
else
false;
- cur_bit_bag = (cur_bit_bag >> bits_per_param) |
- (@as(u32, @boolToInt(is_comptime)) << 31);
- if (param.anytype_ellipsis3) |token| {
+ const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
switch (token_tags[token]) {
- .keyword_anytype => {
- param_types[param_type_i] = .none;
- continue;
- },
- .ellipsis3 => {
- is_var_args = true;
- break;
- },
+ .keyword_anytype => break :blk true,
+ .ellipsis3 => break :is_var_args true,
else => unreachable,
}
- }
- const param_type_node = param.type_expr;
- assert(param_type_node != 0);
- param_types[param_type_i] =
- try expr(gz, scope, .{ .ty = .type_type }, param_type_node);
- }
- assert(param_type_i == param_count);
+ } else false;
- const empty_slot_count = params_per_u32 - (param_type_i % params_per_u32);
- if (empty_slot_count < params_per_u32) {
- cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_param);
+ const param_name: u32 = if (param.name_token) |name_token| blk: {
+ if (mem.eql(u8, "_", tree.tokenSlice(name_token)))
+ break :blk 0;
+
+ break :blk try astgen.identAsString(name_token);
+ } else 0;
+
+ if (is_anytype) {
+ const name_token = param.name_token orelse param.anytype_ellipsis3.?;
+
+ const tag: Zir.Inst.Tag = if (is_comptime)
+ .param_anytype_comptime
+ else
+ .param_anytype;
+ _ = try gz.addStrTok(tag, param_name, name_token);
+ } else {
+ const param_type_node = param.type_expr;
+ assert(param_type_node != 0);
+ const param_type = try expr(gz, scope, type_rl, param_type_node);
+ const main_tokens = tree.nodes.items(.main_token);
+ const name_token = param.name_token orelse main_tokens[param_type_node];
+ const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
+ _ = try gz.addPlTok(tag, name_token, Zir.Inst.Param{
+ .name = param_name,
+ .ty = param_type,
+ });
+ }
}
- }
+ break :is_var_args false;
+ };
const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
break :inst try expr(gz, scope, align_rl, fn_proto.ast.align_expr);
@@ -1144,7 +1126,6 @@ fn fnProtoExpr(
const result = try gz.addFunc(.{
.src_node = fn_proto.ast.proto_node,
.ret_ty = return_type_inst,
- .param_types = param_types,
.body = &[0]Zir.Inst.Index{},
.cc = cc,
.align_inst = align_inst,
@@ -1153,8 +1134,6 @@ fn fnProtoExpr(
.is_inferred_error = false,
.is_test = false,
.is_extern = false,
- .cur_bit_bag = cur_bit_bag,
- .bit_bag = bit_bag.items,
});
return rvalue(gz, rl, result, fn_proto.ast.proto_node);
}
@@ -1447,8 +1426,8 @@ fn structInitExprRlNone(
const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInitAnon{
.fields_len = @intCast(u32, fields_list.len),
});
- try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
- fields_list.len * @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len);
+ try astgen.extra.ensureUnusedCapacity(gpa, fields_list.len *
+ @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len);
for (fields_list) |field| {
_ = gz.astgen.addExtraAssumeCapacity(field);
}
@@ -1520,8 +1499,8 @@ fn structInitExprRlTy(
const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInit{
.fields_len = @intCast(u32, fields_list.len),
});
- try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
- fields_list.len * @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len);
+ try astgen.extra.ensureUnusedCapacity(gpa, fields_list.len *
+ @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len);
for (fields_list) |field| {
_ = gz.astgen.addExtraAssumeCapacity(field);
}
@@ -1918,7 +1897,10 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
// ZIR instructions that might be a type other than `noreturn` or `void`.
.add,
.addwrap,
- .arg,
+ .param,
+ .param_comptime,
+ .param_anytype,
+ .param_anytype_comptime,
.alloc,
.alloc_mut,
.alloc_comptime,
@@ -2488,7 +2470,7 @@ fn varDecl(
// Move the init_scope instructions into the parent scope, swapping
// store_to_block_ptr for store_to_inferred_ptr.
const expected_len = parent_zir.items.len + init_scope.instructions.items.len;
- try parent_zir.ensureCapacity(gpa, expected_len);
+ try parent_zir.ensureTotalCapacity(gpa, expected_len);
for (init_scope.instructions.items) |src_inst| {
if (zir_tags[src_inst] == .store_to_block_ptr) {
if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {
@@ -2750,10 +2732,10 @@ fn ptrType(
}
const gpa = gz.astgen.gpa;
- try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
- try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
- try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
- @typeInfo(Zir.Inst.PtrType).Struct.fields.len + trailing_count);
+ try gz.instructions.ensureUnusedCapacity(gpa, 1);
+ try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
+ try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.PtrType).Struct.fields.len +
+ trailing_count);
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.PtrType{ .elem_type = elem_type });
if (sentinel_ref != .none) {
@@ -2899,6 +2881,16 @@ fn fnDecl(
};
defer decl_gz.instructions.deinit(gpa);
+ var fn_gz: GenZir = .{
+ .force_comptime = false,
+ .in_defer = false,
+ .decl_node_index = fn_proto.ast.proto_node,
+ .decl_line = decl_gz.decl_line,
+ .parent = &decl_gz.base,
+ .astgen = astgen,
+ };
+ defer fn_gz.instructions.deinit(gpa);
+
// TODO: support noinline
const is_pub = fn_proto.visib_token != null;
const is_export = blk: {
@@ -2922,71 +2914,76 @@ fn fnDecl(
try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, section_inst != .none);
- // The AST params array does not contain anytype and ... parameters.
- // We must iterate to count how many param types to allocate.
- const param_count = blk: {
- var count: usize = 0;
- var it = fn_proto.iterate(tree.*);
- while (it.next()) |param| {
- if (param.anytype_ellipsis3) |token| switch (token_tags[token]) {
- .ellipsis3 => break,
- .keyword_anytype => {},
- else => unreachable,
- };
- count += 1;
- }
- break :blk count;
- };
- const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
- defer gpa.free(param_types);
-
- const bits_per_param = 1;
- const params_per_u32 = 32 / bits_per_param;
- // We only need this if there are greater than params_per_u32 fields.
- var bit_bag = ArrayListUnmanaged(u32){};
- defer bit_bag.deinit(gpa);
- var cur_bit_bag: u32 = 0;
- var is_var_args = false;
- {
+ var params_scope = &fn_gz.base;
+ const is_var_args = is_var_args: {
var param_type_i: usize = 0;
var it = fn_proto.iterate(tree.*);
while (it.next()) |param| : (param_type_i += 1) {
- if (param_type_i % params_per_u32 == 0 and param_type_i != 0) {
- try bit_bag.append(gpa, cur_bit_bag);
- cur_bit_bag = 0;
- }
const is_comptime = if (param.comptime_noalias) |token|
token_tags[token] == .keyword_comptime
else
false;
- cur_bit_bag = (cur_bit_bag >> bits_per_param) |
- (@as(u32, @boolToInt(is_comptime)) << 31);
- if (param.anytype_ellipsis3) |token| {
+ const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
switch (token_tags[token]) {
- .keyword_anytype => {
- param_types[param_type_i] = .none;
- continue;
- },
- .ellipsis3 => {
- is_var_args = true;
- break;
- },
+ .keyword_anytype => break :blk true,
+ .ellipsis3 => break :is_var_args true,
else => unreachable,
}
- }
- const param_type_node = param.type_expr;
- assert(param_type_node != 0);
- param_types[param_type_i] =
- try expr(&decl_gz, &decl_gz.base, .{ .ty = .type_type }, param_type_node);
- }
- assert(param_type_i == param_count);
+ } else false;
- const empty_slot_count = params_per_u32 - (param_type_i % params_per_u32);
- if (empty_slot_count < params_per_u32) {
- cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_param);
+ const param_name: u32 = if (param.name_token) |name_token| blk: {
+ if (mem.eql(u8, "_", tree.tokenSlice(name_token)))
+ break :blk 0;
+
+ const param_name = try astgen.identAsString(name_token);
+ if (!is_extern) {
+ try astgen.detectLocalShadowing(params_scope, param_name, name_token);
+ }
+ break :blk param_name;
+ } else if (!is_extern) {
+ if (param.anytype_ellipsis3) |tok| {
+ return astgen.failTok(tok, "missing parameter name", .{});
+ } else {
+ return astgen.failNode(param.type_expr, "missing parameter name", .{});
+ }
+ } else 0;
+
+ const param_inst = if (is_anytype) param: {
+ const name_token = param.name_token orelse param.anytype_ellipsis3.?;
+ const tag: Zir.Inst.Tag = if (is_comptime)
+ .param_anytype_comptime
+ else
+ .param_anytype;
+ break :param try decl_gz.addStrTok(tag, param_name, name_token);
+ } else param: {
+ const param_type_node = param.type_expr;
+ assert(param_type_node != 0);
+ const param_type = try expr(&decl_gz, params_scope, type_rl, param_type_node);
+ const main_tokens = tree.nodes.items(.main_token);
+ const name_token = param.name_token orelse main_tokens[param_type_node];
+ const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
+ break :param try decl_gz.addPlTok(tag, name_token, Zir.Inst.Param{
+ .name = param_name,
+ .ty = param_type,
+ });
+ };
+
+ if (param_name == 0) continue;
+
+ const sub_scope = try astgen.arena.create(Scope.LocalVal);
+ sub_scope.* = .{
+ .parent = params_scope,
+ .gen_zir = &decl_gz,
+ .name = param_name,
+ .inst = param_inst,
+ .token_src = param.name_token.?,
+ .id_cat = .@"function parameter",
+ };
+ params_scope = &sub_scope.base;
}
- }
+ break :is_var_args false;
+ };
const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: {
const lib_name_str = try astgen.strLitAsString(lib_name_token);
@@ -2998,7 +2995,7 @@ fn fnDecl(
const return_type_inst = try AstGen.expr(
&decl_gz,
- &decl_gz.base,
+ params_scope,
.{ .ty = .type_type },
fn_proto.ast.return_type,
);
@@ -3014,7 +3011,7 @@ fn fnDecl(
}
break :blk try AstGen.expr(
&decl_gz,
- &decl_gz.base,
+ params_scope,
.{ .ty = .calling_convention_type },
fn_proto.ast.callconv_expr,
);
@@ -3038,7 +3035,6 @@ fn fnDecl(
break :func try decl_gz.addFunc(.{
.src_node = decl_node,
.ret_ty = return_type_inst,
- .param_types = param_types,
.body = &[0]Zir.Inst.Index{},
.cc = cc,
.align_inst = .none, // passed in the per-decl data
@@ -3047,75 +3043,18 @@ fn fnDecl(
.is_inferred_error = false,
.is_test = false,
.is_extern = true,
- .cur_bit_bag = cur_bit_bag,
- .bit_bag = bit_bag.items,
});
} else func: {
if (is_var_args) {
return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{});
}
- var fn_gz: GenZir = .{
- .force_comptime = false,
- .in_defer = false,
- .decl_node_index = fn_proto.ast.proto_node,
- .decl_line = decl_gz.decl_line,
- .parent = &decl_gz.base,
- .astgen = astgen,
- };
- defer fn_gz.instructions.deinit(gpa);
-
const prev_fn_block = astgen.fn_block;
astgen.fn_block = &fn_gz;
defer astgen.fn_block = prev_fn_block;
- // Iterate over the parameters. We put the param names as the first N
- // items inside `extra` so that debug info later can refer to the parameter names
- // even while the respective source code is unloaded.
- try astgen.extra.ensureUnusedCapacity(gpa, param_count);
-
- {
- var params_scope = &fn_gz.base;
- var i: usize = 0;
- var it = fn_proto.iterate(tree.*);
- while (it.next()) |param| : (i += 1) {
- const name_token = param.name_token orelse {
- if (param.anytype_ellipsis3) |tok| {
- return astgen.failTok(tok, "missing parameter name", .{});
- } else {
- return astgen.failNode(param.type_expr, "missing parameter name", .{});
- }
- };
- if (param.type_expr != 0)
- _ = try typeExpr(&fn_gz, params_scope, param.type_expr);
- if (mem.eql(u8, "_", tree.tokenSlice(name_token)))
- continue;
- const param_name = try astgen.identAsString(name_token);
- // Create an arg instruction. This is needed to emit a semantic analysis
- // error for shadowing decls.
- try astgen.detectLocalShadowing(params_scope, param_name, name_token);
- const arg_inst = try fn_gz.addStrTok(.arg, param_name, name_token);
- const sub_scope = try astgen.arena.create(Scope.LocalVal);
- sub_scope.* = .{
- .parent = params_scope,
- .gen_zir = &fn_gz,
- .name = param_name,
- .inst = arg_inst,
- .token_src = name_token,
- .id_cat = .@"function parameter",
- };
- params_scope = &sub_scope.base;
-
- // Additionally put the param name into `string_bytes` and reference it with
- // `extra` so that we have access to the data in codegen, for debug info.
- const str_index = try astgen.identAsString(name_token);
- try astgen.extra.append(astgen.gpa, str_index);
- }
- _ = try typeExpr(&fn_gz, params_scope, fn_proto.ast.return_type);
-
- _ = try expr(&fn_gz, params_scope, .none, body_node);
- try checkUsed(gz, &fn_gz.base, params_scope);
- }
+ _ = try expr(&fn_gz, params_scope, .none, body_node);
+ try checkUsed(gz, &fn_gz.base, params_scope);
const need_implicit_ret = blk: {
if (fn_gz.instructions.items.len == 0)
@@ -3133,7 +3072,6 @@ fn fnDecl(
break :func try decl_gz.addFunc(.{
.src_node = decl_node,
.ret_ty = return_type_inst,
- .param_types = param_types,
.body = fn_gz.instructions.items,
.cc = cc,
.align_inst = .none, // passed in the per-decl data
@@ -3142,8 +3080,6 @@ fn fnDecl(
.is_inferred_error = is_inferred_error,
.is_test = false,
.is_extern = false,
- .cur_bit_bag = cur_bit_bag,
- .bit_bag = bit_bag.items,
});
};
@@ -3480,7 +3416,6 @@ fn testDecl(
const func_inst = try decl_block.addFunc(.{
.src_node = node,
.ret_ty = .void_type,
- .param_types = &[0]Zir.Inst.Ref{},
.body = fn_block.instructions.items,
.cc = .none,
.align_inst = .none,
@@ -3489,8 +3424,6 @@ fn testDecl(
.is_inferred_error = true,
.is_test = true,
.is_extern = false,
- .cur_bit_bag = 0,
- .bit_bag = &.{},
});
_ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
@@ -4238,7 +4171,7 @@ fn containerDecl(
var fields_data = ArrayListUnmanaged(u32){};
defer fields_data.deinit(gpa);
- try fields_data.ensureCapacity(gpa, counts.total_fields + counts.values);
+ try fields_data.ensureTotalCapacity(gpa, counts.total_fields + counts.values);
// We only need this if there are greater than 32 fields.
var bit_bag = ArrayListUnmanaged(u32){};
@@ -5184,8 +5117,7 @@ fn setCondBrPayload(
) !void {
const astgen = then_scope.astgen;
- try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len +
- @typeInfo(Zir.Inst.CondBr).Struct.fields.len +
+ try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len +
then_scope.instructions.items.len + else_scope.instructions.items.len);
const zir_datas = astgen.instructions.items(.data);
@@ -5839,10 +5771,9 @@ fn switchExpr(
_ = try case_scope.addBreak(.@"break", switch_block, case_result);
}
// Documentation for this: `Zir.Inst.SwitchBlock` and `Zir.Inst.SwitchBlockMulti`.
- try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len +
+ try scalar_cases_payload.ensureUnusedCapacity(gpa, case_scope.instructions.items.len +
3 + // operand, scalar_cases_len, else body len
- @boolToInt(multi_cases_len != 0) +
- case_scope.instructions.items.len);
+ @boolToInt(multi_cases_len != 0));
scalar_cases_payload.appendAssumeCapacity(@enumToInt(operand));
scalar_cases_payload.appendAssumeCapacity(scalar_cases_len);
if (multi_cases_len != 0) {
@@ -5852,9 +5783,11 @@ fn switchExpr(
scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items);
} else {
// Documentation for this: `Zir.Inst.SwitchBlock` and `Zir.Inst.SwitchBlockMulti`.
- try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len +
- 2 + // operand, scalar_cases_len
- @boolToInt(multi_cases_len != 0));
+ try scalar_cases_payload.ensureUnusedCapacity(
+ gpa,
+ @as(usize, 2) + // operand, scalar_cases_len
+ @boolToInt(multi_cases_len != 0),
+ );
scalar_cases_payload.appendAssumeCapacity(@enumToInt(operand));
scalar_cases_payload.appendAssumeCapacity(scalar_cases_len);
if (multi_cases_len != 0) {
@@ -5975,8 +5908,8 @@ fn switchExpr(
block_scope.break_count += 1;
_ = try case_scope.addBreak(.@"break", switch_block, case_result);
}
- try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len +
- 2 + case_scope.instructions.items.len);
+ try scalar_cases_payload.ensureUnusedCapacity(gpa, 2 +
+ case_scope.instructions.items.len);
scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst));
scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));
scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items);
@@ -6012,8 +5945,8 @@ fn switchExpr(
const payload_index = astgen.extra.items.len;
const zir_datas = astgen.instructions.items(.data);
zir_datas[switch_block].pl_node.payload_index = @intCast(u32, payload_index);
- try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
- scalar_cases_payload.items.len + multi_cases_payload.items.len);
+ try astgen.extra.ensureUnusedCapacity(gpa, scalar_cases_payload.items.len +
+ multi_cases_payload.items.len);
const strat = rl.strategy(&block_scope);
switch (strat.tag) {
.break_operand => {
@@ -8659,7 +8592,7 @@ fn failNodeNotes(
}
const notes_index: u32 = if (notes.len != 0) blk: {
const notes_start = astgen.extra.items.len;
- try astgen.extra.ensureCapacity(astgen.gpa, notes_start + 1 + notes.len);
+ try astgen.extra.ensureTotalCapacity(astgen.gpa, notes_start + 1 + notes.len);
astgen.extra.appendAssumeCapacity(@intCast(u32, notes.len));
astgen.extra.appendSliceAssumeCapacity(notes);
break :blk @intCast(u32, notes_start);
@@ -8700,7 +8633,7 @@ fn failTokNotes(
}
const notes_index: u32 = if (notes.len != 0) blk: {
const notes_start = astgen.extra.items.len;
- try astgen.extra.ensureCapacity(astgen.gpa, notes_start + 1 + notes.len);
+ try astgen.extra.ensureTotalCapacity(astgen.gpa, notes_start + 1 + notes.len);
astgen.extra.appendAssumeCapacity(@intCast(u32, notes.len));
astgen.extra.appendSliceAssumeCapacity(notes);
break :blk @intCast(u32, notes_start);
@@ -8864,7 +8797,7 @@ fn strLitNodeAsString(astgen: *AstGen, node: ast.Node.Index) !IndexSlice {
while (tok_i <= end) : (tok_i += 1) {
const slice = tree.tokenSlice(tok_i);
const line_bytes = slice[2 .. slice.len - 1];
- try string_bytes.ensureCapacity(gpa, string_bytes.items.len + line_bytes.len + 1);
+ try string_bytes.ensureUnusedCapacity(gpa, line_bytes.len + 1);
string_bytes.appendAssumeCapacity('\n');
string_bytes.appendSliceAssumeCapacity(line_bytes);
}
@@ -9131,8 +9064,8 @@ const GenZir = struct {
fn setBoolBrBody(gz: GenZir, inst: Zir.Inst.Index) !void {
const gpa = gz.astgen.gpa;
- try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
- @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
+ try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len +
+ gz.instructions.items.len);
const zir_datas = gz.astgen.instructions.items(.data);
zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity(
Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
@@ -9142,8 +9075,8 @@ const GenZir = struct {
fn setBlockBody(gz: GenZir, inst: Zir.Inst.Index) !void {
const gpa = gz.astgen.gpa;
- try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
- @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
+ try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len +
+ gz.instructions.items.len);
const zir_datas = gz.astgen.instructions.items(.data);
zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity(
Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
@@ -9155,8 +9088,8 @@ const GenZir = struct {
/// `store_to_block_ptr` instructions with lhs set to .none.
fn setBlockBodyEliding(gz: GenZir, inst: Zir.Inst.Index) !void {
const gpa = gz.astgen.gpa;
- try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
- @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
+ try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len +
+ gz.instructions.items.len);
const zir_datas = gz.astgen.instructions.items(.data);
const zir_tags = gz.astgen.instructions.items(.tag);
const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{
@@ -9177,7 +9110,6 @@ const GenZir = struct {
fn addFunc(gz: *GenZir, args: struct {
src_node: ast.Node.Index,
- param_types: []const Zir.Inst.Ref,
body: []const Zir.Inst.Index,
ret_ty: Zir.Inst.Ref,
cc: Zir.Inst.Ref,
@@ -9187,8 +9119,6 @@ const GenZir = struct {
is_inferred_error: bool,
is_test: bool,
is_extern: bool,
- cur_bit_bag: u32,
- bit_bag: []const u32,
}) !Zir.Inst.Ref {
assert(args.src_node != 0);
assert(args.ret_ty != .none);
@@ -9226,19 +9156,14 @@ const GenZir = struct {
src_locs = &src_locs_buffer;
}
- const any_are_comptime = args.cur_bit_bag != 0 or for (args.bit_bag) |x| {
- if (x != 0) break true;
- } else false;
-
if (args.cc != .none or args.lib_name != 0 or
args.is_var_args or args.is_test or args.align_inst != .none or
- args.is_extern or any_are_comptime)
+ args.is_extern)
{
try astgen.extra.ensureUnusedCapacity(
gpa,
@typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
- @boolToInt(any_are_comptime) + args.bit_bag.len +
- args.param_types.len + args.body.len + src_locs.len +
+ args.body.len + src_locs.len +
@boolToInt(args.lib_name != 0) +
@boolToInt(args.align_inst != .none) +
@boolToInt(args.cc != .none),
@@ -9246,7 +9171,6 @@ const GenZir = struct {
const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
.src_node = gz.nodeIndexToRelative(args.src_node),
.return_type = args.ret_ty,
- .param_types_len = @intCast(u32, args.param_types.len),
.body_len = @intCast(u32, args.body.len),
});
if (args.lib_name != 0) {
@@ -9258,11 +9182,6 @@ const GenZir = struct {
if (args.align_inst != .none) {
astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
}
- if (any_are_comptime) {
- astgen.extra.appendSliceAssumeCapacity(args.bit_bag); // Likely empty.
- astgen.extra.appendAssumeCapacity(args.cur_bit_bag);
- }
- astgen.appendRefsAssumeCapacity(args.param_types);
astgen.extra.appendSliceAssumeCapacity(args.body);
astgen.extra.appendSliceAssumeCapacity(src_locs);
@@ -9279,7 +9198,6 @@ const GenZir = struct {
.has_align = args.align_inst != .none,
.is_test = args.is_test,
.is_extern = args.is_extern,
- .has_comptime_bits = any_are_comptime,
}),
.operand = payload_index,
} },
@@ -9290,15 +9208,13 @@ const GenZir = struct {
try gz.astgen.extra.ensureUnusedCapacity(
gpa,
@typeInfo(Zir.Inst.Func).Struct.fields.len +
- args.param_types.len + args.body.len + src_locs.len,
+ args.body.len + src_locs.len,
);
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{
.return_type = args.ret_ty,
- .param_types_len = @intCast(u32, args.param_types.len),
.body_len = @intCast(u32, args.body.len),
});
- gz.astgen.appendRefsAssumeCapacity(args.param_types);
gz.astgen.extra.appendSliceAssumeCapacity(args.body);
gz.astgen.extra.appendSliceAssumeCapacity(src_locs);
@@ -9380,10 +9296,10 @@ const GenZir = struct {
assert(callee != .none);
assert(src_node != 0);
const gpa = gz.astgen.gpa;
- try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
- try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
- try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
- @typeInfo(Zir.Inst.Call).Struct.fields.len + args.len);
+ try gz.instructions.ensureUnusedCapacity(gpa, 1);
+ try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
+ try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Call).Struct.fields.len +
+ args.len);
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Call{
.callee = callee,
@@ -9412,8 +9328,8 @@ const GenZir = struct {
) !Zir.Inst.Index {
assert(lhs != .none);
const gpa = gz.astgen.gpa;
- try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
- try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
+ try gz.instructions.ensureUnusedCapacity(gpa, 1);
+ try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
gz.astgen.instructions.appendAssumeCapacity(.{
@@ -9486,8 +9402,8 @@ const GenZir = struct {
extra: anytype,
) !Zir.Inst.Ref {
const gpa = gz.astgen.gpa;
- try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
- try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
+ try gz.instructions.ensureUnusedCapacity(gpa, 1);
+ try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
const payload_index = try gz.astgen.addExtra(extra);
const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
@@ -9502,6 +9418,30 @@ const GenZir = struct {
return indexToRef(new_index);
}
+ fn addPlTok(
+ gz: *GenZir,
+ tag: Zir.Inst.Tag,
+ /// Absolute token index. This function does the conversion to Decl offset.
+ abs_tok_index: ast.TokenIndex,
+ extra: anytype,
+ ) !Zir.Inst.Ref {
+ const gpa = gz.astgen.gpa;
+ try gz.instructions.ensureUnusedCapacity(gpa, 1);
+ try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
+
+ const payload_index = try gz.astgen.addExtra(extra);
+ const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
+ gz.astgen.instructions.appendAssumeCapacity(.{
+ .tag = tag,
+ .data = .{ .pl_tok = .{
+ .src_tok = gz.tokenIndexToRelative(abs_tok_index),
+ .payload_index = payload_index,
+ } },
+ });
+ gz.instructions.appendAssumeCapacity(new_index);
+ return indexToRef(new_index);
+ }
+
fn addExtendedPayload(
gz: *GenZir,
opcode: Zir.Inst.Extended,
@@ -9509,8 +9449,8 @@ const GenZir = struct {
) !Zir.Inst.Ref {
const gpa = gz.astgen.gpa;
- try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
- try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
+ try gz.instructions.ensureUnusedCapacity(gpa, 1);
+ try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
const payload_index = try gz.astgen.addExtra(extra);
const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
@@ -9566,8 +9506,8 @@ const GenZir = struct {
elem_type: Zir.Inst.Ref,
) !Zir.Inst.Ref {
const gpa = gz.astgen.gpa;
- try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
- try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
+ try gz.instructions.ensureUnusedCapacity(gpa, 1);
+ try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
const payload_index = try gz.astgen.addExtra(Zir.Inst.ArrayTypeSentinel{
.sentinel = sentinel,
@@ -9822,7 +9762,7 @@ const GenZir = struct {
/// Leaves the `payload_index` field undefined.
fn addCondBr(gz: *GenZir, tag: Zir.Inst.Tag, node: ast.Node.Index) !Zir.Inst.Index {
const gpa = gz.astgen.gpa;
- try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
+ try gz.instructions.ensureUnusedCapacity(gpa, 1);
const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
try gz.astgen.instructions.append(gpa, .{
.tag = tag,
diff --git a/src/Module.zig b/src/Module.zig
index 84b721369d..fa8b4ca768 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -3714,7 +3714,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {
decl.analysis = .outdated;
}
-fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node.Index) !*Decl {
+pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node.Index) !*Decl {
// If we have emit-h then we must allocate a bigger structure to store the emit-h state.
const new_decl: *Decl = if (mod.emit_h != null) blk: {
const parent_struct = try mod.gpa.create(DeclPlusEmitH);
diff --git a/src/Sema.zig b/src/Sema.zig
index 753ef8fb9c..5fd3c149a2 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -44,6 +44,7 @@ branch_count: u32 = 0,
/// contain a mapped source location.
src: LazySrcLoc = .{ .token_offset = 0 },
next_arg_index: usize = 0,
+params: std.ArrayListUnmanaged(Param) = .{},
decl_val_table: std.AutoHashMapUnmanaged(*Decl, Air.Inst.Ref) = .{},
const std = @import("std");
@@ -68,6 +69,13 @@ const LazySrcLoc = Module.LazySrcLoc;
const RangeSet = @import("RangeSet.zig");
const target_util = @import("target.zig");
+const Param = struct {
+ name: [:0]const u8,
+ /// `none` means `anytype`.
+ ty: Air.Inst.Ref,
+ is_comptime: bool,
+};
+
pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, Air.Inst.Ref);
pub fn deinit(sema: *Sema) void {
@@ -91,8 +99,7 @@ pub fn analyzeFnBody(
.func, .func_inferred => blk: {
const inst_data = datas[fn_body_inst].pl_node;
const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
- const param_types_len = extra.data.param_types_len;
- const body = sema.code.extra[extra.end + param_types_len ..][0..extra.data.body_len];
+ const body = sema.code.extra[extra.end..][0..extra.data.body_len];
break :blk body;
},
.extended => blk: {
@@ -104,10 +111,6 @@ pub fn analyzeFnBody(
extra_index += @boolToInt(small.has_lib_name);
extra_index += @boolToInt(small.has_cc);
extra_index += @boolToInt(small.has_align);
- if (small.has_comptime_bits) {
- extra_index += (extra.data.param_types_len + 31) / 32;
- }
- extra_index += extra.data.param_types_len;
const body = sema.code.extra[extra_index..][0..extra.data.body_len];
break :blk body;
},
@@ -162,7 +165,6 @@ pub fn analyzeBody(
const inst = body[i];
const air_inst: Air.Inst.Ref = switch (tags[inst]) {
// zig fmt: off
- .arg => try sema.zirArg(block, inst),
.alloc => try sema.zirAlloc(block, inst),
.alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
.alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
@@ -404,6 +406,26 @@ pub fn analyzeBody(
// continue the loop.
// We also know that they cannot be referenced later, so we avoid
// putting them into the map.
+ .param => {
+ try sema.zirParam(inst, false);
+ i += 1;
+ continue;
+ },
+ .param_comptime => {
+ try sema.zirParam(inst, true);
+ i += 1;
+ continue;
+ },
+ .param_anytype => {
+ try sema.zirParamAnytype(inst, false);
+ i += 1;
+ continue;
+ },
+ .param_anytype_comptime => {
+ try sema.zirParamAnytype(inst, true);
+ i += 1;
+ continue;
+ },
.breakpoint => {
try sema.zirBreakpoint(block, inst);
i += 1;
@@ -1358,23 +1380,34 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
return sema.analyzeLoad(block, src, result_ptr, result_ptr_src);
}
-fn zirArg(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+fn zirParam(sema: *Sema, inst: Zir.Inst.Index, is_comptime: bool) CompileError!void {
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
+ const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data;
+ const param_name = sema.code.nullTerminatedString(extra.name);
+
+ // TODO check if param_name shadows a Decl. This only needs to be done if
+ // usingnamespace is implemented.
+
+ const param_ty = sema.resolveInst(extra.ty);
+ try sema.params.append(sema.gpa, .{
+ .name = param_name,
+ .ty = param_ty,
+ .is_comptime = is_comptime,
+ });
+}
+
+fn zirParamAnytype(sema: *Sema, inst: Zir.Inst.Index, is_comptime: bool) CompileError!void {
const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
- const arg_name = inst_data.get(sema.code);
- const arg_index = sema.next_arg_index;
- sema.next_arg_index += 1;
+ const param_name = inst_data.get(sema.code);
- // TODO check if arg_name shadows a Decl
- _ = arg_name;
+ // TODO check if param_name shadows a Decl. This only needs to be done if
+ // usingnamespace is implemented.
- if (block.inlining) |_| {
- return sema.param_inst_list[arg_index];
- }
-
- // Set the name of the Air.Arg instruction for use by codegen debug info.
- const air_arg = sema.param_inst_list[arg_index];
- sema.air_instructions.items(.data)[Air.refToIndex(air_arg).?].ty_str.str = inst_data.start;
- return air_arg;
+ try sema.params.append(sema.gpa, .{
+ .name = param_name,
+ .ty = .none,
+ .is_comptime = is_comptime,
+ });
}
fn zirAllocExtended(
@@ -2395,26 +2428,29 @@ fn analyzeCall(
ensure_result_used: bool,
args: []const Air.Inst.Ref,
) CompileError!Air.Inst.Ref {
+ const mod = sema.mod;
+
const func_ty = sema.typeOf(func);
if (func_ty.zigTypeTag() != .Fn)
- return sema.mod.fail(&block.base, func_src, "type '{}' not a function", .{func_ty});
+ return mod.fail(&block.base, func_src, "type '{}' not a function", .{func_ty});
- const cc = func_ty.fnCallingConvention();
+ const func_ty_info = func_ty.fnInfo();
+ const cc = func_ty_info.cc;
if (cc == .Naked) {
// TODO add error note: declared here
- return sema.mod.fail(
+ return mod.fail(
&block.base,
func_src,
"unable to call function with naked calling convention",
.{},
);
}
- const fn_params_len = func_ty.fnParamLen();
- if (func_ty.fnIsVarArgs()) {
+ const fn_params_len = func_ty_info.param_types.len;
+ if (func_ty_info.is_var_args) {
assert(cc == .C);
if (args.len < fn_params_len) {
// TODO add error note: declared here
- return sema.mod.fail(
+ return mod.fail(
&block.base,
func_src,
"expected at least {d} argument(s), found {d}",
@@ -2423,7 +2459,7 @@ fn analyzeCall(
}
} else if (fn_params_len != args.len) {
// TODO add error note: declared here
- return sema.mod.fail(
+ return mod.fail(
&block.base,
func_src,
"expected {d} argument(s), found {d}",
@@ -2442,7 +2478,7 @@ fn analyzeCall(
.never_inline,
.no_async,
.always_tail,
- => return sema.mod.fail(&block.base, call_src, "TODO implement call with modifier {}", .{
+ => return mod.fail(&block.base, call_src, "TODO implement call with modifier {}", .{
modifier,
}),
}
@@ -2451,12 +2487,12 @@ fn analyzeCall(
const is_comptime_call = block.is_comptime or modifier == .compile_time;
const is_inline_call = is_comptime_call or modifier == .always_inline or
- func_ty.fnCallingConvention() == .Inline;
+ func_ty_info.cc == .Inline;
const result: Air.Inst.Ref = if (is_inline_call) res: {
const func_val = try sema.resolveConstValue(block, func_src, func);
const module_fn = switch (func_val.tag()) {
.function => func_val.castTag(.function).?.data,
- .extern_fn => return sema.mod.fail(&block.base, call_src, "{s} call of extern function", .{
+ .extern_fn => return mod.fail(&block.base, call_src, "{s} call of extern function", .{
@as([]const u8, if (is_comptime_call) "comptime" else "inline"),
}),
else => unreachable,
@@ -2535,10 +2571,46 @@ fn analyzeCall(
const result = try sema.analyzeBlockBody(block, call_src, &child_block, merges);
break :res result;
+ } else if (func_ty_info.is_generic) {
+ const func_val = try sema.resolveConstValue(block, func_src, func);
+ const module_fn = func_val.castTag(.function).?.data;
+ // Check the Module's generic function map with an adapted context, so that we
+ // can match against `args` rather than doing the work below to create a generic Scope
+ // only to junk it if it matches an existing instantiation.
+ // TODO
+
+ // Create a Decl for the new function.
+ const generic_namespace = try sema.arena.create(Module.Scope.Namespace);
+ generic_namespace.* = .{
+ .parent = block.src_decl.namespace,
+ .file_scope = block.src_decl.namespace.file_scope,
+ .ty = func_ty,
+ };
+ const new_decl = try mod.allocateNewDecl(generic_namespace, module_fn.owner_decl.src_node);
+ _ = new_decl;
+
+ // Iterate over the parameters that are comptime, evaluating their type expressions
+ // inside a Scope which contains the previous parameters.
+ //for (args) |arg, arg_i| {
+ //}
+
+ // Create a new Fn with only the runtime-known parameters.
+ // TODO
+
+ // Populate the Decl ty/val with the function and its type.
+ // TODO
+
+ // Queue up a `codegen_func` work item for the new Fn, making sure it will have
+ // `analyzeFnBody` called with the Scope which contains the comptime parameters.
+ // TODO
+
+ // Save it into the Module's generic function map.
+ // TODO
+
+ // Call it the same as a runtime function.
+ // TODO
+ return mod.fail(&block.base, func_src, "TODO implement generic fn call", .{});
} else res: {
- if (func_ty.fnIsGeneric()) {
- return sema.mod.fail(&block.base, func_src, "TODO implement generic fn call", .{});
- }
try sema.requireRuntimeBlock(block, call_src);
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +
args.len);
@@ -3186,13 +3258,12 @@ fn zirFunc(
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
- const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
var body_inst: Zir.Inst.Index = 0;
var src_locs: Zir.Inst.Func.SrcLocs = undefined;
if (extra.data.body_len != 0) {
body_inst = inst;
- const extra_index = extra.end + extra.data.param_types_len + extra.data.body_len;
+ const extra_index = extra.end + extra.data.body_len;
src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
}
@@ -3204,7 +3275,6 @@ fn zirFunc(
return sema.funcCommon(
block,
inst_data.src_node,
- param_types,
body_inst,
extra.data.return_type,
cc,
@@ -3214,7 +3284,6 @@ fn zirFunc(
false,
src_locs,
null,
- &.{},
);
}
@@ -3222,7 +3291,6 @@ fn funcCommon(
sema: *Sema,
block: *Scope.Block,
src_node_offset: i32,
- zir_param_types: []const Zir.Inst.Ref,
body_inst: Zir.Inst.Index,
zir_return_type: Zir.Inst.Ref,
cc: std.builtin.CallingConvention,
@@ -3232,7 +3300,6 @@ fn funcCommon(
is_extern: bool,
src_locs: Zir.Inst.Func.SrcLocs,
opt_lib_name: ?[]const u8,
- comptime_bits: []const u32,
) CompileError!Air.Inst.Ref {
const src: LazySrcLoc = .{ .node_offset = src_node_offset };
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
@@ -3245,7 +3312,7 @@ fn funcCommon(
const fn_ty: Type = fn_ty: {
// Hot path for some common function types.
- if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value and
+ if (sema.params.items.len == 0 and !var_args and align_val.tag() == .null_value and
!inferred_error_set)
{
if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
@@ -3266,22 +3333,21 @@ fn funcCommon(
}
var any_are_comptime = false;
- const param_types = try sema.arena.alloc(Type, zir_param_types.len);
- for (zir_param_types) |param_type, i| {
- // TODO make a compile error from `resolveType` report the source location
- // of the specific parameter. Will need to take a similar strategy as
- // `resolveSwitchItemVal` to avoid resolving the source location unless
- // we actually need to report an error.
- const param_src = src;
- param_types[i] = try sema.resolveType(block, param_src, param_type);
-
- any_are_comptime = any_are_comptime or blk: {
- if (comptime_bits.len == 0)
- break :blk false;
- const bag = comptime_bits[i / 32];
- const is_comptime = @truncate(u1, bag >> @intCast(u5, i % 32)) != 0;
- break :blk is_comptime;
- };
+ const param_types = try sema.arena.alloc(Type, sema.params.items.len);
+ const comptime_params = try sema.arena.alloc(bool, sema.params.items.len);
+ for (sema.params.items) |param, i| {
+ if (param.ty == .none) {
+ param_types[i] = Type.initTag(.noreturn); // indicates anytype
+ } else {
+ // TODO make a compile error from `resolveType` report the source location
+ // of the specific parameter. Will need to take a similar strategy as
+ // `resolveSwitchItemVal` to avoid resolving the source location unless
+ // we actually need to report an error.
+ const param_src = src;
+ param_types[i] = try sema.resolveType(block, param_src, param.ty);
+ }
+ comptime_params[i] = param.is_comptime;
+ any_are_comptime = any_are_comptime or param.is_comptime;
}
if (align_val.tag() != .null_value) {
@@ -3301,6 +3367,7 @@ fn funcCommon(
break :fn_ty try Type.Tag.function.create(sema.arena, .{
.param_types = param_types,
+ .comptime_params = comptime_params.ptr,
.return_type = return_type,
.cc = cc,
.is_var_args = var_args,
@@ -6545,16 +6612,6 @@ fn zirFuncExtended(
break :blk align_tv.val;
} else Value.initTag(.null_value);
- const comptime_bits: []const u32 = if (!small.has_comptime_bits) &.{} else blk: {
- const amt = (extra.data.param_types_len + 31) / 32;
- const bit_bags = sema.code.extra[extra_index..][0..amt];
- extra_index += amt;
- break :blk bit_bags;
- };
-
- const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
- extra_index += param_types.len;
-
var body_inst: Zir.Inst.Index = 0;
var src_locs: Zir.Inst.Func.SrcLocs = undefined;
if (extra.data.body_len != 0) {
@@ -6570,7 +6627,6 @@ fn zirFuncExtended(
return sema.funcCommon(
block,
extra.data.src_node,
- param_types,
body_inst,
extra.data.return_type,
cc,
@@ -6580,7 +6636,6 @@ fn zirFuncExtended(
is_extern,
src_locs,
lib_name,
- comptime_bits,
);
}
diff --git a/src/Zir.zig b/src/Zir.zig
index 109ae3b186..6445d73af5 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -173,11 +173,22 @@ pub const Inst = struct {
/// Twos complement wrapping integer addition.
/// Uses the `pl_node` union field. Payload is `Bin`.
addwrap,
- /// Declares a parameter of the current function. Used for debug info and
- /// for checking shadowing against declarations in the current namespace.
- /// Uses the `str_tok` field. Token is the parameter name, string is the
- /// parameter name.
- arg,
+ /// Declares a parameter of the current function. Used for:
+ /// * debug info
+ /// * checking shadowing against declarations in the current namespace
+ /// * parameter type expressions referencing other parameters
+ /// These occur in the block outside a function body (the same block as
+ /// contains the func instruction).
+ /// Uses the `pl_tok` field. Token is the parameter name, payload is a `Param`.
+ param,
+ /// Same as `param` except the parameter is marked comptime.
+ param_comptime,
+ /// Same as `param` except the parameter is marked anytype.
+ /// Uses the `str_tok` field. Token is the parameter name. String is the parameter name.
+ param_anytype,
+ /// Same as `param` except the parameter is marked both comptime and anytype.
+ /// Uses the `str_tok` field. Token is the parameter name. String is the parameter name.
+ param_anytype_comptime,
/// Array concatenation. `a ++ b`
/// Uses the `pl_node` union field. Payload is `Bin`.
array_cat,
@@ -971,7 +982,10 @@ pub const Inst = struct {
/// Function calls do not count.
pub fn isNoReturn(tag: Tag) bool {
return switch (tag) {
- .arg,
+ .param,
+ .param_comptime,
+ .param_anytype,
+ .param_anytype_comptime,
.add,
.addwrap,
.alloc,
@@ -1233,7 +1247,10 @@ pub const Inst = struct {
break :list std.enums.directEnumArray(Tag, Data.FieldEnum, 0, .{
.add = .pl_node,
.addwrap = .pl_node,
- .arg = .str_tok,
+ .param = .pl_tok,
+ .param_comptime = .pl_tok,
+ .param_anytype = .str_tok,
+ .param_anytype_comptime = .str_tok,
.array_cat = .pl_node,
.array_mul = .pl_node,
.array_type = .bin,
@@ -2047,6 +2064,17 @@ pub const Inst = struct {
return .{ .node_offset = self.src_node };
}
},
+ pl_tok: struct {
+ /// Offset from Decl AST token index.
+ src_tok: ast.TokenIndex,
+ /// index into extra.
+ /// `Tag` determines what lives there.
+ payload_index: u32,
+
+ pub fn src(self: @This()) LazySrcLoc {
+ return .{ .token_offset = self.src_tok };
+ }
+ },
bin: Bin,
/// For strings which may contain null bytes.
str: struct {
@@ -2170,6 +2198,7 @@ pub const Inst = struct {
un_node,
un_tok,
pl_node,
+ pl_tok,
bin,
str,
str_tok,
@@ -2226,17 +2255,11 @@ pub const Inst = struct {
/// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
/// 1. cc: Ref, // if has_cc is set
/// 2. align: Ref, // if has_align is set
- /// 3. comptime_bits: u32 // for every 32 parameters, if has_comptime_bits is set
- /// - sets of 1 bit:
- /// 0bX: whether corresponding parameter is comptime
- /// 4. param_type: Ref // for each param_types_len
- /// - `none` indicates that the param type is `anytype`.
- /// 5. body: Index // for each body_len
- /// 6. src_locs: Func.SrcLocs // if body_len != 0
+ /// 3. body: Index // for each body_len
+ /// 4. src_locs: Func.SrcLocs // if body_len != 0
pub const ExtendedFunc = struct {
src_node: i32,
return_type: Ref,
- param_types_len: u32,
body_len: u32,
pub const Small = packed struct {
@@ -2247,8 +2270,7 @@ pub const Inst = struct {
has_align: bool,
is_test: bool,
is_extern: bool,
- has_comptime_bits: bool,
- _: u8 = undefined,
+ _: u9 = undefined,
};
};
@@ -2271,13 +2293,10 @@ pub const Inst = struct {
};
/// Trailing:
- /// 0. param_type: Ref // for each param_types_len
- /// - `none` indicates that the param type is `anytype`.
- /// 1. body: Index // for each body_len
- /// 2. src_locs: SrcLocs // if body_len != 0
+ /// 0. body: Index // for each body_len
+ /// 1. src_locs: SrcLocs // if body_len != 0
pub const Func = struct {
return_type: Ref,
- param_types_len: u32,
body_len: u32,
pub const SrcLocs = struct {
@@ -2764,6 +2783,12 @@ pub const Inst = struct {
args: Ref,
};
+ pub const Param = struct {
+ /// Null-terminated string index.
+ name: u32,
+ ty: Ref,
+ };
+
/// Trailing:
/// 0. type_inst: Ref, // if small 0b000X is set
/// 1. align_inst: Ref, // if small 0b00X0 is set
@@ -3108,11 +3133,14 @@ const Writer = struct {
.decl_ref,
.decl_val,
.import,
- .arg,
.ret_err_value,
.ret_err_value_code,
+ .param_anytype,
+ .param_anytype_comptime,
=> try self.writeStrTok(stream, inst),
+ .param, .param_comptime => try self.writeParam(stream, inst),
+
.func => try self.writeFunc(stream, inst, false),
.func_inferred => try self.writeFunc(stream, inst, true),
@@ -3314,6 +3342,17 @@ const Writer = struct {
try self.writeSrc(stream, inst_data.src());
}
+ fn writeParam(self: *Writer, stream: anytype, inst: Inst.Index) !void {
+ const inst_data = self.code.instructions.items(.data)[inst].pl_tok;
+ const extra = self.code.extraData(Inst.Param, inst_data.payload_index).data;
+ try stream.print("\"{}\", ", .{
+ std.zig.fmtEscapes(self.code.nullTerminatedString(extra.name)),
+ });
+ try self.writeInstRef(stream, extra.ty);
+ try stream.writeAll(") ");
+ try self.writeSrc(stream, inst_data.src());
+ }
+
fn writePlNodeBin(self: *Writer, stream: anytype, inst: Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
const extra = self.code.extraData(Inst.Bin, inst_data.payload_index).data;
@@ -4277,16 +4316,14 @@ const Writer = struct {
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
const extra = self.code.extraData(Inst.Func, inst_data.payload_index);
- const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
- const body = self.code.extra[extra.end + param_types.len ..][0..extra.data.body_len];
+ const body = self.code.extra[extra.end..][0..extra.data.body_len];
var src_locs: Zir.Inst.Func.SrcLocs = undefined;
if (body.len != 0) {
- const extra_index = extra.end + param_types.len + body.len;
+ const extra_index = extra.end + body.len;
src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
}
return self.writeFuncCommon(
stream,
- param_types,
extra.data.return_type,
inferred_error_set,
false,
@@ -4296,7 +4333,6 @@ const Writer = struct {
body,
src,
src_locs,
- &.{},
);
}
@@ -4323,16 +4359,6 @@ const Writer = struct {
break :blk align_inst;
};
- const comptime_bits: []const u32 = if (!small.has_comptime_bits) &.{} else blk: {
- const amt = (extra.data.param_types_len + 31) / 32;
- const bit_bags = self.code.extra[extra_index..][0..amt];
- extra_index += amt;
- break :blk bit_bags;
- };
-
- const param_types = self.code.refSlice(extra_index, extra.data.param_types_len);
- extra_index += param_types.len;
-
const body = self.code.extra[extra_index..][0..extra.data.body_len];
extra_index += body.len;
@@ -4342,7 +4368,6 @@ const Writer = struct {
}
return self.writeFuncCommon(
stream,
- param_types,
extra.data.return_type,
small.is_inferred_error,
small.is_var_args,
@@ -4352,7 +4377,6 @@ const Writer = struct {
body,
src,
src_locs,
- comptime_bits,
);
}
@@ -4426,7 +4450,6 @@ const Writer = struct {
fn writeFuncCommon(
self: *Writer,
stream: anytype,
- param_types: []const Inst.Ref,
ret_ty: Inst.Ref,
inferred_error_set: bool,
var_args: bool,
@@ -4436,19 +4459,7 @@ const Writer = struct {
body: []const Inst.Index,
src: LazySrcLoc,
src_locs: Zir.Inst.Func.SrcLocs,
- comptime_bits: []const u32,
) !void {
- try stream.writeAll("[");
- for (param_types) |param_type, i| {
- if (i != 0) try stream.writeAll(", ");
- if (comptime_bits.len != 0) {
- const bag = comptime_bits[i / 32];
- const is_comptime = @truncate(u1, bag >> @intCast(u5, i % 32)) != 0;
- try self.writeFlag(stream, "comptime ", is_comptime);
- }
- try self.writeInstRef(stream, param_type);
- }
- try stream.writeAll("], ");
try self.writeInstRef(stream, ret_ty);
try self.writeOptionalInstRef(stream, ", cc=", cc);
try self.writeOptionalInstRef(stream, ", align=", align_inst);
@@ -4714,8 +4725,7 @@ fn findDeclsInner(
const inst_data = datas[inst].pl_node;
const extra = zir.extraData(Inst.Func, inst_data.payload_index);
- const param_types_len = extra.data.param_types_len;
- const body = zir.extra[extra.end + param_types_len ..][0..extra.data.body_len];
+ const body = zir.extra[extra.end..][0..extra.data.body_len];
return zir.findDeclsBody(list, body);
},
.extended => {
@@ -4730,7 +4740,6 @@ fn findDeclsInner(
extra_index += @boolToInt(small.has_lib_name);
extra_index += @boolToInt(small.has_cc);
extra_index += @boolToInt(small.has_align);
- extra_index += extra.data.param_types_len;
const body = zir.extra[extra_index..][0..extra.data.body_len];
return zir.findDeclsBody(list, body);
},
diff --git a/src/type.zig b/src/type.zig
index a8c3d77bbb..feb16fd47c 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -759,12 +759,15 @@ pub const Type = extern union {
for (payload.param_types) |param_type, i| {
param_types[i] = try param_type.copy(allocator);
}
+ const other_comptime_params = payload.comptime_params[0..payload.param_types.len];
+ const comptime_params = try allocator.dupe(bool, other_comptime_params);
return Tag.function.create(allocator, .{
.return_type = try payload.return_type.copy(allocator),
.param_types = param_types,
.cc = payload.cc,
.is_var_args = payload.is_var_args,
.is_generic = payload.is_generic,
+ .comptime_params = comptime_params.ptr,
});
},
.pointer => {
@@ -2408,14 +2411,41 @@ pub const Type = extern union {
};
}
- /// Asserts the type is a function.
- pub fn fnIsGeneric(self: Type) bool {
- return switch (self.tag()) {
- .fn_noreturn_no_args => false,
- .fn_void_no_args => false,
- .fn_naked_noreturn_no_args => false,
- .fn_ccc_void_no_args => false,
- .function => self.castTag(.function).?.data.is_generic,
+ pub fn fnInfo(ty: Type) Payload.Function.Data {
+ return switch (ty.tag()) {
+ .fn_noreturn_no_args => .{
+ .param_types = &.{},
+ .comptime_params = undefined,
+ .return_type = initTag(.noreturn),
+ .cc = .Unspecified,
+ .is_var_args = false,
+ .is_generic = false,
+ },
+ .fn_void_no_args => .{
+ .param_types = &.{},
+ .comptime_params = undefined,
+ .return_type = initTag(.void),
+ .cc = .Unspecified,
+ .is_var_args = false,
+ .is_generic = false,
+ },
+ .fn_naked_noreturn_no_args => .{
+ .param_types = &.{},
+ .comptime_params = undefined,
+ .return_type = initTag(.noreturn),
+ .cc = .Naked,
+ .is_var_args = false,
+ .is_generic = false,
+ },
+ .fn_ccc_void_no_args => .{
+ .param_types = &.{},
+ .comptime_params = undefined,
+ .return_type = initTag(.void),
+ .cc = .C,
+ .is_var_args = false,
+ .is_generic = false,
+ },
+ .function => ty.castTag(.function).?.data,
else => unreachable,
};
@@ -3223,13 +3253,23 @@ pub const Type = extern union {
pub const base_tag = Tag.function;
base: Payload = Payload{ .tag = base_tag },
- data: struct {
+ data: Data,
+
+ // TODO look into optimizing this memory to take fewer bytes
+ const Data = struct {
param_types: []Type,
+ comptime_params: [*]bool,
return_type: Type,
cc: std.builtin.CallingConvention,
is_var_args: bool,
is_generic: bool,
- },
+
+ fn paramIsComptime(self: @This(), i: usize) bool {
+ if (!self.is_generic) return false;
+ assert(i < self.param_types.len);
+ return self.comptime_params[i];
+ }
+ };
};
pub const ErrorSet = struct {
From bc18e93825f1f3703b97590cc0e963b3faa8cd3e Mon Sep 17 00:00:00 2001
From: Evan Haas
Date: Mon, 2 Aug 2021 08:15:59 -0700
Subject: [PATCH 70/96] translate-c: better codegen for pointer index by int
literal
#8589 introduced correct handling of signed (possibly negative) array access
of pointers. Since unadorned integer literals in C are signed, this resulted
in inefficient generated code when indexing a pointer by a non-negative
integer literal.
---
src/clang.zig | 4 ++--
src/translate_c.zig | 20 +++++++++++++++++---
src/zig_clang.cpp | 14 ++++++++++++--
src/zig_clang.h | 2 +-
test/translate_c.zig | 11 +++++++++++
5 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/src/clang.zig b/src/clang.zig
index 0632c5ab67..1254a505f4 100644
--- a/src/clang.zig
+++ b/src/clang.zig
@@ -616,8 +616,8 @@ pub const IntegerLiteral = opaque {
pub const getBeginLoc = ZigClangIntegerLiteral_getBeginLoc;
extern fn ZigClangIntegerLiteral_getBeginLoc(*const IntegerLiteral) SourceLocation;
- pub const isZero = ZigClangIntegerLiteral_isZero;
- extern fn ZigClangIntegerLiteral_isZero(*const IntegerLiteral, *bool, *const ASTContext) bool;
+ pub const getSignum = ZigClangIntegerLiteral_getSignum;
+ extern fn ZigClangIntegerLiteral_getSignum(*const IntegerLiteral, *c_int, *const ASTContext) bool;
};
/// This is just used as a namespace for a static method on clang's Lexer class; we don't directly
diff --git a/src/translate_c.zig b/src/translate_c.zig
index 8b465fff96..e6d6392a9c 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -1985,10 +1985,11 @@ fn transBoolExpr(
used: ResultUsed,
) TransError!Node {
if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) {
- var is_zero: bool = undefined;
- if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) {
+ var signum: c_int = undefined;
+ if (!(@ptrCast(*const clang.IntegerLiteral, expr).getSignum(&signum, c.clang_context))) {
return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});
}
+ const is_zero = signum == 0;
return Node{ .tag_if_small_enough = @enumToInt(([2]Tag{ .true_literal, .false_literal })[@boolToInt(is_zero)]) };
}
@@ -3360,6 +3361,7 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip
const subscr_qt = getExprQualType(c, subscr_expr);
const is_longlong = cIsLongLongInteger(subscr_qt);
const is_signed = cIsSignedInteger(subscr_qt);
+ const is_nonnegative_int_literal = cIsNonNegativeIntLiteral(c, subscr_expr);
// Unwrap the base statement if it's an array decayed to a bare pointer type
// so that we index the array itself
@@ -3374,7 +3376,7 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip
// Special case: actual pointer (not decayed array) and signed integer subscript
// See discussion at https://github.com/ziglang/zig/pull/8589
- if (is_signed and (base_stmt == unwrapped_base) and !is_vector) return transSignedArrayAccess(c, scope, base_stmt, subscr_expr, result_used);
+ if (is_signed and (base_stmt == unwrapped_base) and !is_vector and !is_nonnegative_int_literal) return transSignedArrayAccess(c, scope, base_stmt, subscr_expr, result_used);
const container_node = try transExpr(c, scope, unwrapped_base, .used);
const rhs = if (is_longlong or is_signed) blk: {
@@ -4260,6 +4262,18 @@ fn cIntTypeCmp(a: clang.QualType, b: clang.QualType) math.Order {
return math.order(a_index, b_index);
}
+/// Checks if expr is an integer literal >= 0
+fn cIsNonNegativeIntLiteral(c: *Context, expr: *const clang.Expr) bool {
+ if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) {
+ var signum: c_int = undefined;
+ if (!(@ptrCast(*const clang.IntegerLiteral, expr).getSignum(&signum, c.clang_context))) {
+ return false;
+ }
+ return signum >= 0;
+ }
+ return false;
+}
+
fn cIsSignedInteger(qt: clang.QualType) bool {
const c_type = qualTypeCanon(qt);
if (c_type.getTypeClass() != .Builtin) return false;
diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp
index 4fe1dfc286..6611585f68 100644
--- a/src/zig_clang.cpp
+++ b/src/zig_clang.cpp
@@ -2754,7 +2754,7 @@ struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct Zi
return bitcast(casted->getBeginLoc());
}
-bool ZigClangIntegerLiteral_isZero(const struct ZigClangIntegerLiteral *self, bool *result, const struct ZigClangASTContext *ctx) {
+bool ZigClangIntegerLiteral_getSignum(const struct ZigClangIntegerLiteral *self, int *result, const struct ZigClangASTContext *ctx) {
auto casted_self = reinterpret_cast(self);
auto casted_ctx = reinterpret_cast(ctx);
clang::Expr::EvalResult eval_result;
@@ -2763,7 +2763,17 @@ bool ZigClangIntegerLiteral_isZero(const struct ZigClangIntegerLiteral *self, bo
}
const llvm::APSInt result_int = eval_result.Val.getInt();
const llvm::APSInt zero(result_int.getBitWidth(), result_int.isUnsigned());
- *result = zero == result_int;
+
+ if (zero == result_int) {
+ *result = 0;
+ } else if (result_int < zero) {
+ *result = -1;
+ } else if (result_int > zero) {
+ *result = 1;
+ } else {
+ return false;
+ }
+
return true;
}
diff --git a/src/zig_clang.h b/src/zig_clang.h
index dc35df3772..0e7a8b2990 100644
--- a/src/zig_clang.h
+++ b/src/zig_clang.h
@@ -1222,7 +1222,7 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangCStyleCastExpr_getType(const struct
ZIG_EXTERN_C bool ZigClangIntegerLiteral_EvaluateAsInt(const struct ZigClangIntegerLiteral *, struct ZigClangExprEvalResult *, const struct ZigClangASTContext *);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct ZigClangIntegerLiteral *);
-ZIG_EXTERN_C bool ZigClangIntegerLiteral_isZero(const struct ZigClangIntegerLiteral *, bool *, const struct ZigClangASTContext *);
+ZIG_EXTERN_C bool ZigClangIntegerLiteral_getSignum(const struct ZigClangIntegerLiteral *, int *, const struct ZigClangASTContext *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangReturnStmt_getRetValue(const struct ZigClangReturnStmt *);
diff --git a/test/translate_c.zig b/test/translate_c.zig
index b75d3b5cac..6ddc2107ee 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -3630,4 +3630,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub const FOO = @import("std").zig.c_translation.Macros.U_SUFFIX;
});
+
+ cases.add("Simple array access of pointer with non-negative integer constant",
+ \\void foo(int *p) {
+ \\ p[0];
+ \\ p[1];
+ \\}
+ , &[_][]const u8{
+ \\_ = p[@intCast(c_uint, @as(c_int, 0))];
+ ,
+ \\_ = p[@intCast(c_uint, @as(c_int, 1))];
+ });
}
From aad4598367b136a06e3569373be7da8febea7f31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carlos=20Z=C3=BA=C3=B1iga?=
Date: Thu, 22 Jul 2021 18:01:56 -0500
Subject: [PATCH 71/96] ci: remove extra zig directory in windows builds
From $prefix/lib/zig/std/std.zig to $prefix/lib/std/std.zig
---
ci/azure/windows_upload | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/ci/azure/windows_upload b/ci/azure/windows_upload
index 1f47359dd9..9c5e07e5f9 100755
--- a/ci/azure/windows_upload
+++ b/ci/azure/windows_upload
@@ -11,6 +11,11 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
mv dist/bin/zig.exe dist/
rmdir dist/bin
+ # Remove the unnecessary zig dir in $prefix/lib/zig/std/std.zig
+ mv dist/lib/zig dist/lib2
+ rmdir dist/lib
+ mv dist/lib2 dist/lib
+
VERSION=$(dist/zig.exe version)
DIRNAME="zig-windows-x86_64-$VERSION"
TARBALL="$DIRNAME.zip"
From 609b84611dcde382af5d9fbc2345ede468d31a6f Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 3 Aug 2021 17:29:59 -0700
Subject: [PATCH 72/96] stage2: rework runtime, comptime, inline function calls
* ZIR function instructions encode the index of the block that
contains the function instruction. This allows Zig to later scan the
block and find the parameter instructions, which is needed for
semantically analyzing function bodies.
* Runtime function calls insert AIR arg instructions and then inserts
Sema inst_map entries mapping the ZIR param instructions to them.
* comptime/inline function call inserts Sema inst_map entries mapping
the ZIR param instructions to the AIR callsite arguments.
With this commit we are back to the tests passing.
---
BRANCH_TODO | 2 --
src/AstGen.zig | 7 +++++
src/Module.zig | 57 +++++++++++++++++++++++++-------------
src/Sema.zig | 75 ++++++++++++++------------------------------------
src/Zir.zig | 54 ++++++++++++++++++++++++++++++++++--
5 files changed, 117 insertions(+), 78 deletions(-)
diff --git a/BRANCH_TODO b/BRANCH_TODO
index bc0a67f799..1cdd8362e7 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,6 +1,4 @@
* update arg instructions:
- - runtime function call inserts AIR arg instructions and Sema map items for them
- - comptime/inline function call inserts Sema map items for the args
- generic instantiation inserts Sema map items for the comptime args only, re-runs the
Decl ZIR to get the new Fn.
* generic function call where it makes a new function
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 0b78c839a0..f88b59d211 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -1125,6 +1125,7 @@ fn fnProtoExpr(
const result = try gz.addFunc(.{
.src_node = fn_proto.ast.proto_node,
+ .param_block = 0,
.ret_ty = return_type_inst,
.body = &[0]Zir.Inst.Index{},
.cc = cc,
@@ -3035,6 +3036,7 @@ fn fnDecl(
break :func try decl_gz.addFunc(.{
.src_node = decl_node,
.ret_ty = return_type_inst,
+ .param_block = block_inst,
.body = &[0]Zir.Inst.Index{},
.cc = cc,
.align_inst = .none, // passed in the per-decl data
@@ -3071,6 +3073,7 @@ fn fnDecl(
break :func try decl_gz.addFunc(.{
.src_node = decl_node,
+ .param_block = block_inst,
.ret_ty = return_type_inst,
.body = fn_gz.instructions.items,
.cc = cc,
@@ -3415,6 +3418,7 @@ fn testDecl(
const func_inst = try decl_block.addFunc(.{
.src_node = node,
+ .param_block = block_inst,
.ret_ty = .void_type,
.body = fn_block.instructions.items,
.cc = .none,
@@ -9111,6 +9115,7 @@ const GenZir = struct {
fn addFunc(gz: *GenZir, args: struct {
src_node: ast.Node.Index,
body: []const Zir.Inst.Index,
+ param_block: Zir.Inst.Index,
ret_ty: Zir.Inst.Ref,
cc: Zir.Inst.Ref,
align_inst: Zir.Inst.Ref,
@@ -9170,6 +9175,7 @@ const GenZir = struct {
);
const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
.src_node = gz.nodeIndexToRelative(args.src_node),
+ .param_block = args.param_block,
.return_type = args.ret_ty,
.body_len = @intCast(u32, args.body.len),
});
@@ -9212,6 +9218,7 @@ const GenZir = struct {
);
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{
+ .param_block = args.param_block,
.return_type = args.ret_ty,
.body_len = @intCast(u32, args.body.len),
});
diff --git a/src/Module.zig b/src/Module.zig
index fa8b4ca768..6253e2808d 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -2899,7 +2899,6 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void {
.namespace = &struct_obj.namespace,
.func = null,
.owner_func = null,
- .param_inst_list = &.{},
};
defer sema.deinit();
var block_scope: Scope.Block = .{
@@ -2954,7 +2953,6 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
.namespace = decl.namespace,
.func = null,
.owner_func = null,
- .param_inst_list = &.{},
};
defer sema.deinit();
@@ -3625,8 +3623,6 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air {
defer decl.value_arena.?.* = arena.state;
const fn_ty = decl.ty;
- const param_inst_list = try gpa.alloc(Air.Inst.Ref, fn_ty.fnParamLen());
- defer gpa.free(param_inst_list);
var sema: Sema = .{
.mod = mod,
@@ -3637,7 +3633,6 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air {
.namespace = decl.namespace,
.func = func,
.owner_func = func,
- .param_inst_list = param_inst_list,
};
defer sema.deinit();
@@ -3656,29 +3651,55 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air {
};
defer inner_block.instructions.deinit(gpa);
- // AIR requires the arg parameters to be the first N instructions.
- try inner_block.instructions.ensureTotalCapacity(gpa, param_inst_list.len);
- for (param_inst_list) |*param_inst, param_index| {
+ const fn_info = sema.code.getFnInfo(func.zir_body_inst);
+ const zir_tags = sema.code.instructions.items(.tag);
+
+ // Here we are performing "runtime semantic analysis" for a function body, which means
+ // we must map the parameter ZIR instructions to `arg` AIR instructions.
+ // AIR requires the `arg` parameters to be the first N instructions.
+ const params_len = @intCast(u32, fn_ty.fnParamLen());
+ try inner_block.instructions.ensureTotalCapacity(gpa, params_len);
+ try sema.air_instructions.ensureUnusedCapacity(gpa, params_len * 2); // * 2 for the `addType`
+ try sema.inst_map.ensureUnusedCapacity(gpa, params_len);
+
+ var param_index: usize = 0;
+ for (fn_info.param_body) |inst| {
+ const name = switch (zir_tags[inst]) {
+ .param, .param_comptime => blk: {
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
+ const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data;
+ break :blk extra.name;
+ },
+
+ .param_anytype, .param_anytype_comptime => blk: {
+ const str_tok = sema.code.instructions.items(.data)[inst].str_tok;
+ break :blk str_tok.start;
+ },
+
+ else => continue,
+ };
const param_type = fn_ty.fnParamType(param_index);
+ param_index += 1;
const ty_ref = try sema.addType(param_type);
const arg_index = @intCast(u32, sema.air_instructions.len);
inner_block.instructions.appendAssumeCapacity(arg_index);
- param_inst.* = Air.indexToRef(arg_index);
- try sema.air_instructions.append(gpa, .{
+ sema.air_instructions.appendAssumeCapacity(.{
.tag = .arg,
- .data = .{
- .ty_str = .{
- .ty = ty_ref,
- .str = undefined, // Set in the semantic analysis of the arg instruction.
- },
- },
+ .data = .{ .ty_str = .{
+ .ty = ty_ref,
+ .str = name,
+ } },
});
+ sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
}
func.state = .in_progress;
log.debug("set {s} to in_progress", .{decl.name});
- try sema.analyzeFnBody(&inner_block, func.zir_body_inst);
+ _ = sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
+ error.NeededSourceLocation => unreachable,
+ else => |e| return e,
+ };
// Copy the block into place and mark that as the main block.
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
@@ -4330,7 +4351,6 @@ pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) CompileError!void
.namespace = &struct_obj.namespace,
.owner_func = null,
.func = null,
- .param_inst_list = &.{},
};
defer sema.deinit();
@@ -4484,7 +4504,6 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) CompileError!void {
.namespace = &union_obj.namespace,
.owner_func = null,
.func = null,
- .param_inst_list = &.{},
};
defer sema.deinit();
diff --git a/src/Sema.zig b/src/Sema.zig
index 5fd3c149a2..923295069d 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -29,13 +29,6 @@ owner_func: ?*Module.Fn,
/// This starts out the same as `owner_func` and then diverges in the case of
/// an inline or comptime function call.
func: ?*Module.Fn,
-/// For now, AIR requires arg instructions to be the first N instructions in the
-/// AIR code. We store references here for the purpose of `resolveInst`.
-/// This can get reworked with AIR memory layout changes, into simply:
-/// > Denormalized data to make `resolveInst` faster. This is 0 if not inside a function,
-/// > otherwise it is the number of parameters of the function.
-/// > param_count: u32
-param_inst_list: []const Air.Inst.Ref,
branch_quota: u32 = 1000,
branch_count: u32 = 0,
/// This field is updated when a new source location becomes active, so that
@@ -85,43 +78,10 @@ pub fn deinit(sema: *Sema) void {
sema.air_values.deinit(gpa);
sema.inst_map.deinit(gpa);
sema.decl_val_table.deinit(gpa);
+ sema.params.deinit(gpa);
sema.* = undefined;
}
-pub fn analyzeFnBody(
- sema: *Sema,
- block: *Scope.Block,
- fn_body_inst: Zir.Inst.Index,
-) SemaError!void {
- const tags = sema.code.instructions.items(.tag);
- const datas = sema.code.instructions.items(.data);
- const body: []const Zir.Inst.Index = switch (tags[fn_body_inst]) {
- .func, .func_inferred => blk: {
- const inst_data = datas[fn_body_inst].pl_node;
- const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
- const body = sema.code.extra[extra.end..][0..extra.data.body_len];
- break :blk body;
- },
- .extended => blk: {
- const extended = datas[fn_body_inst].extended;
- assert(extended.opcode == .func);
- const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand);
- const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
- var extra_index: usize = extra.end;
- extra_index += @boolToInt(small.has_lib_name);
- extra_index += @boolToInt(small.has_cc);
- extra_index += @boolToInt(small.has_align);
- const body = sema.code.extra[extra_index..][0..extra.data.body_len];
- break :blk body;
- },
- else => unreachable,
- };
- _ = sema.analyzeBody(block, body) catch |err| switch (err) {
- error.NeededSourceLocation => unreachable,
- else => |e| return e,
- };
-}
-
/// Returns only the result from the body that is specified.
/// Only appropriate to call when it is determined at comptime that this body
/// has no peers.
@@ -1066,7 +1026,6 @@ fn zirEnumDecl(
.namespace = &enum_obj.namespace,
.owner_func = null,
.func = null,
- .param_inst_list = &.{},
.branch_quota = sema.branch_quota,
.branch_count = sema.branch_count,
};
@@ -2538,10 +2497,6 @@ fn analyzeCall(
sema.func = module_fn;
defer sema.func = parent_func;
- const parent_param_inst_list = sema.param_inst_list;
- sema.param_inst_list = args;
- defer sema.param_inst_list = parent_param_inst_list;
-
const parent_next_arg_index = sema.next_arg_index;
sema.next_arg_index = 0;
defer sema.next_arg_index = parent_next_arg_index;
@@ -2565,12 +2520,23 @@ fn analyzeCall(
try sema.emitBackwardBranch(&child_block, call_src);
// This will have return instructions analyzed as break instructions to
- // the block_inst above.
- try sema.analyzeFnBody(&child_block, module_fn.zir_body_inst);
-
- const result = try sema.analyzeBlockBody(block, call_src, &child_block, merges);
-
- break :res result;
+ // the block_inst above. Here we are performing "comptime/inline semantic analysis"
+ // for a function body, which means we must map the parameter ZIR instructions to
+ // the AIR instructions of the callsite.
+ const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst);
+ const zir_tags = sema.code.instructions.items(.tag);
+ var arg_i: usize = 0;
+ try sema.inst_map.ensureUnusedCapacity(gpa, @intCast(u32, args.len));
+ for (fn_info.param_body) |inst| {
+ switch (zir_tags[inst]) {
+ .param, .param_comptime, .param_anytype, .param_anytype_comptime => {},
+ else => continue,
+ }
+ sema.inst_map.putAssumeCapacityNoClobber(inst, args[arg_i]);
+ arg_i += 1;
+ }
+ _ = try sema.analyzeBody(&child_block, fn_info.body);
+ break :res try sema.analyzeBlockBody(block, call_src, &child_block, merges);
} else if (func_ty_info.is_generic) {
const func_val = try sema.resolveConstValue(block, func_src, func);
const module_fn = func_val.castTag(.function).?.data;
@@ -2601,7 +2567,7 @@ fn analyzeCall(
// TODO
// Queue up a `codegen_func` work item for the new Fn, making sure it will have
- // `analyzeFnBody` called with the Scope which contains the comptime parameters.
+ // `analyzeBody` called with the ZIR parameters mapped appropriately.
// TODO
// Save it into the Module's generic function map.
@@ -3344,11 +3310,12 @@ fn funcCommon(
// `resolveSwitchItemVal` to avoid resolving the source location unless
// we actually need to report an error.
const param_src = src;
- param_types[i] = try sema.resolveType(block, param_src, param.ty);
+ param_types[i] = try sema.analyzeAsType(block, param_src, param.ty);
}
comptime_params[i] = param.is_comptime;
any_are_comptime = any_are_comptime or param.is_comptime;
}
+ sema.params.clearRetainingCapacity();
if (align_val.tag() != .null_value) {
return mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{});
diff --git a/src/Zir.zig b/src/Zir.zig
index 6445d73af5..b7f4c28161 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -61,7 +61,7 @@ pub const ExtraIndex = enum(u32) {
_,
};
-pub fn getMainStruct(zir: Zir) Zir.Inst.Index {
+pub fn getMainStruct(zir: Zir) Inst.Index {
return zir.extra[@enumToInt(ExtraIndex.main_struct)] -
@intCast(u32, Inst.Ref.typed_value_map.len);
}
@@ -2260,6 +2260,8 @@ pub const Inst = struct {
pub const ExtendedFunc = struct {
src_node: i32,
return_type: Ref,
+ /// Points to the block that contains the param instructions for this function.
+ param_block: Index,
body_len: u32,
pub const Small = packed struct {
@@ -2297,6 +2299,8 @@ pub const Inst = struct {
/// 1. src_locs: SrcLocs // if body_len != 0
pub const Func = struct {
return_type: Ref,
+ /// Points to the block that contains the param instructions for this function.
+ param_block: Index,
body_len: u32,
pub const SrcLocs = struct {
@@ -4894,10 +4898,54 @@ fn findDeclsSwitchMulti(
fn findDeclsBody(
zir: Zir,
- list: *std.ArrayList(Zir.Inst.Index),
- body: []const Zir.Inst.Index,
+ list: *std.ArrayList(Inst.Index),
+ body: []const Inst.Index,
) Allocator.Error!void {
for (body) |member| {
try zir.findDeclsInner(list, member);
}
}
+
+pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) struct {
+ param_body: []const Inst.Index,
+ body: []const Inst.Index,
+} {
+ const tags = zir.instructions.items(.tag);
+ const datas = zir.instructions.items(.data);
+ const info: struct {
+ param_block: Inst.Index,
+ body: []const Inst.Index,
+ } = switch (tags[fn_inst]) {
+ .func, .func_inferred => blk: {
+ const inst_data = datas[fn_inst].pl_node;
+ const extra = zir.extraData(Inst.Func, inst_data.payload_index);
+ const body = zir.extra[extra.end..][0..extra.data.body_len];
+ break :blk .{
+ .param_block = extra.data.param_block,
+ .body = body,
+ };
+ },
+ .extended => blk: {
+ const extended = datas[fn_inst].extended;
+ assert(extended.opcode == .func);
+ const extra = zir.extraData(Inst.ExtendedFunc, extended.operand);
+ const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);
+ var extra_index: usize = extra.end;
+ extra_index += @boolToInt(small.has_lib_name);
+ extra_index += @boolToInt(small.has_cc);
+ extra_index += @boolToInt(small.has_align);
+ const body = zir.extra[extra_index..][0..extra.data.body_len];
+ break :blk .{
+ .param_block = extra.data.param_block,
+ .body = body,
+ };
+ },
+ else => unreachable,
+ };
+ assert(tags[info.param_block] == .block or tags[info.param_block] == .block_inline);
+ const param_block = zir.extraData(Inst.Block, datas[info.param_block].pl_node.payload_index);
+ return .{
+ .param_body = zir.extra[param_block.end..][0..param_block.data.body_len],
+ .body = info.body,
+ };
+}
From 382d201781eb57d9e950ad07ce814adc5a68b329 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 3 Aug 2021 22:34:22 -0700
Subject: [PATCH 73/96] stage2: basic generic functions are working
The general strategy is that Sema will pre-map comptime arguments into
the inst_map, and then re-run the block body that contains the `param`
and `func` instructions. This re-runs all the parameter type expressions
except with comptime values populated.
In Sema, param instructions are now handled specially: they detect
whether they are comptime-elided or not. If so, they skip putting a
value in the inst_map, since it is already pre-populated. If not, then
they append to the `fields` field of `Sema` for use with the `func`
instruction.
So when the block body is re-run, a new function is generated with
all the comptime arguments elided, and the new function type has only
runtime parameters in it. TODO: give the generated Decls better names
than "foo__anon_x".
The new function is then added to the work queue to have its body
analyzed and a runtime call AIR instruction to the new function is
emitted.
When the new function gets semantically analyzed, comptime parameters are
pre-mapped to the corresponding `comptime_args` values rather than
mapped to an `arg` AIR instruction. `comptime_args` is a new field that
`Fn` has which is a `TypedValue` for each parameter. This field is non-null
for generic function instantiations only. The values are the comptime
arguments. For non-comptime parameters, a sentinel value is used. This is
because we need to know the information of which parameters are
comptime-known.
Additionally:
* AstGen: align and section expressions are evaluated in the scope that
has comptime parameters in it.
There are still some TODO items left; see the BRANCH_TODO file.
---
BRANCH_TODO | 7 +-
src/AstGen.zig | 16 +--
src/Module.zig | 27 +++-
src/Sema.zig | 346 ++++++++++++++++++++++++++++++++++---------------
src/Zir.zig | 14 +-
src/type.zig | 3 +-
6 files changed, 287 insertions(+), 126 deletions(-)
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 1cdd8362e7..e8606332d7 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,7 +1,4 @@
-* update arg instructions:
- - generic instantiation inserts Sema map items for the comptime args only, re-runs the
- Decl ZIR to get the new Fn.
-* generic function call where it makes a new function
* memoize the instantiation in a table
-* anytype with next parameter expression using it
+* expressions that depend on comptime stuff need a poison value to use for
+ types when generating the generic function type
* comptime anytype
diff --git a/src/AstGen.zig b/src/AstGen.zig
index f88b59d211..7534afe961 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -2906,14 +2906,7 @@ fn fnDecl(
const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
break :blk token_tags[maybe_inline_token] == .keyword_inline;
};
- const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
- break :inst try expr(&decl_gz, &decl_gz.base, align_rl, fn_proto.ast.align_expr);
- };
- const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
- break :inst try comptimeExpr(&decl_gz, &decl_gz.base, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
- };
-
- try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, section_inst != .none);
+ try wip_decls.next(gpa, is_pub, is_export, fn_proto.ast.align_expr != 0, fn_proto.ast.section_expr != 0);
var params_scope = &fn_gz.base;
const is_var_args = is_var_args: {
@@ -2994,6 +2987,13 @@ fn fnDecl(
const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
const is_inferred_error = token_tags[maybe_bang] == .bang;
+ const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
+ break :inst try expr(&decl_gz, params_scope, align_rl, fn_proto.ast.align_expr);
+ };
+ const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
+ break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
+ };
+
const return_type_inst = try AstGen.expr(
&decl_gz,
params_scope,
diff --git a/src/Module.zig b/src/Module.zig
index 6253e2808d..184ea617b1 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -757,6 +757,10 @@ pub const Union = struct {
pub const Fn = struct {
/// The Decl that corresponds to the function itself.
owner_decl: *Decl,
+ /// If this is not null, this function is a generic function instantiation, and
+ /// there is a `Value` here for each parameter of the function. Non-comptime
+ /// parameters are marked with an `unreachable_value`.
+ comptime_args: ?[*]TypedValue = null,
/// The ZIR instruction that is a function instruction. Use this to find
/// the body. We store this rather than the body directly so that when ZIR
/// is regenerated on update(), we can map this to the new corresponding
@@ -3657,10 +3661,13 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air {
// Here we are performing "runtime semantic analysis" for a function body, which means
// we must map the parameter ZIR instructions to `arg` AIR instructions.
// AIR requires the `arg` parameters to be the first N instructions.
- const params_len = @intCast(u32, fn_ty.fnParamLen());
- try inner_block.instructions.ensureTotalCapacity(gpa, params_len);
- try sema.air_instructions.ensureUnusedCapacity(gpa, params_len * 2); // * 2 for the `addType`
- try sema.inst_map.ensureUnusedCapacity(gpa, params_len);
+ // This could be a generic function instantiation, however, in which case we need to
+ // map the comptime parameters to constant values and only emit arg AIR instructions
+ // for the runtime ones.
+ const runtime_params_len = @intCast(u32, fn_ty.fnParamLen());
+ try inner_block.instructions.ensureTotalCapacity(gpa, runtime_params_len);
+ try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
+ try sema.inst_map.ensureUnusedCapacity(gpa, fn_info.total_params_len);
var param_index: usize = 0;
for (fn_info.param_body) |inst| {
@@ -3678,8 +3685,17 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air {
else => continue,
};
+ if (func.comptime_args) |comptime_args| {
+ const arg_tv = comptime_args[param_index];
+ if (arg_tv.val.tag() != .unreachable_value) {
+ // We have a comptime value for this parameter.
+ const arg = try sema.addConstant(arg_tv.ty, arg_tv.val);
+ sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
+ param_index += 1;
+ continue;
+ }
+ }
const param_type = fn_ty.fnParamType(param_index);
- param_index += 1;
const ty_ref = try sema.addType(param_type);
const arg_index = @intCast(u32, sema.air_instructions.len);
inner_block.instructions.appendAssumeCapacity(arg_index);
@@ -3691,6 +3707,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air {
} },
});
sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
+ param_index += 1;
}
func.state = .in_progress;
diff --git a/src/Sema.zig b/src/Sema.zig
index 923295069d..9a7eb6fc40 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -36,9 +36,14 @@ branch_count: u32 = 0,
/// access to the source location set by the previous instruction which did
/// contain a mapped source location.
src: LazySrcLoc = .{ .token_offset = 0 },
-next_arg_index: usize = 0,
-params: std.ArrayListUnmanaged(Param) = .{},
decl_val_table: std.AutoHashMapUnmanaged(*Decl, Air.Inst.Ref) = .{},
+/// `param` instructions are collected here to be used by the `func` instruction.
+params: std.ArrayListUnmanaged(Param) = .{},
+/// When doing a generic function instantiation, this array collects a `Value` object for
+/// each parameter that is comptime known and thus elided from the generated function.
+/// This memory is allocated by a parent `Sema` and owned by the values arena of the owner_decl.
+comptime_args: []TypedValue = &.{},
+next_arg_index: usize = 0,
const std = @import("std");
const mem = std.mem;
@@ -64,8 +69,8 @@ const target_util = @import("target.zig");
const Param = struct {
name: [:0]const u8,
- /// `none` means `anytype`.
- ty: Air.Inst.Ref,
+ /// `noreturn` means `anytype`.
+ ty: Type,
is_comptime: bool,
};
@@ -366,26 +371,6 @@ pub fn analyzeBody(
// continue the loop.
// We also know that they cannot be referenced later, so we avoid
// putting them into the map.
- .param => {
- try sema.zirParam(inst, false);
- i += 1;
- continue;
- },
- .param_comptime => {
- try sema.zirParam(inst, true);
- i += 1;
- continue;
- },
- .param_anytype => {
- try sema.zirParamAnytype(inst, false);
- i += 1;
- continue;
- },
- .param_anytype_comptime => {
- try sema.zirParamAnytype(inst, true);
- i += 1;
- continue;
- },
.breakpoint => {
try sema.zirBreakpoint(block, inst);
i += 1;
@@ -519,6 +504,88 @@ pub fn analyzeBody(
return break_inst;
}
},
+ .param => blk: {
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
+ const src = inst_data.src();
+ const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data;
+ const param_name = sema.code.nullTerminatedString(extra.name);
+
+ if (sema.nextArgIsComptimeElided()) {
+ i += 1;
+ continue;
+ }
+
+ // TODO check if param_name shadows a Decl. This only needs to be done if
+ // usingnamespace is implemented.
+
+ const param_ty = try sema.resolveType(block, src, extra.ty);
+ try sema.params.append(sema.gpa, .{
+ .name = param_name,
+ .ty = param_ty,
+ .is_comptime = false,
+ });
+ break :blk try sema.addConstUndef(param_ty);
+ },
+ .param_comptime => blk: {
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
+ const src = inst_data.src();
+ const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data;
+ const param_name = sema.code.nullTerminatedString(extra.name);
+
+ if (sema.nextArgIsComptimeElided()) {
+ i += 1;
+ continue;
+ }
+
+ // TODO check if param_name shadows a Decl. This only needs to be done if
+ // usingnamespace is implemented.
+
+ const param_ty = try sema.resolveType(block, src, extra.ty);
+ try sema.params.append(sema.gpa, .{
+ .name = param_name,
+ .ty = param_ty,
+ .is_comptime = true,
+ });
+ break :blk try sema.addConstUndef(param_ty);
+ },
+ .param_anytype => blk: {
+ const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
+ const param_name = inst_data.get(sema.code);
+
+ if (sema.nextArgIsComptimeElided()) {
+ i += 1;
+ continue;
+ }
+
+ // TODO check if param_name shadows a Decl. This only needs to be done if
+ // usingnamespace is implemented.
+
+ try sema.params.append(sema.gpa, .{
+ .name = param_name,
+ .ty = Type.initTag(.noreturn),
+ .is_comptime = false,
+ });
+ break :blk try sema.addConstUndef(Type.initTag(.@"undefined"));
+ },
+ .param_anytype_comptime => blk: {
+ const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
+ const param_name = inst_data.get(sema.code);
+
+ if (sema.nextArgIsComptimeElided()) {
+ i += 1;
+ continue;
+ }
+
+ // TODO check if param_name shadows a Decl. This only needs to be done if
+ // usingnamespace is implemented.
+
+ try sema.params.append(sema.gpa, .{
+ .name = param_name,
+ .ty = Type.initTag(.noreturn),
+ .is_comptime = true,
+ });
+ break :blk try sema.addConstUndef(Type.initTag(.@"undefined"));
+ },
};
if (sema.typeOf(air_inst).isNoReturn())
return always_noreturn;
@@ -1339,36 +1406,6 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
return sema.analyzeLoad(block, src, result_ptr, result_ptr_src);
}
-fn zirParam(sema: *Sema, inst: Zir.Inst.Index, is_comptime: bool) CompileError!void {
- const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
- const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data;
- const param_name = sema.code.nullTerminatedString(extra.name);
-
- // TODO check if param_name shadows a Decl. This only needs to be done if
- // usingnamespace is implemented.
-
- const param_ty = sema.resolveInst(extra.ty);
- try sema.params.append(sema.gpa, .{
- .name = param_name,
- .ty = param_ty,
- .is_comptime = is_comptime,
- });
-}
-
-fn zirParamAnytype(sema: *Sema, inst: Zir.Inst.Index, is_comptime: bool) CompileError!void {
- const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
- const param_name = inst_data.get(sema.code);
-
- // TODO check if param_name shadows a Decl. This only needs to be done if
- // usingnamespace is implemented.
-
- try sema.params.append(sema.gpa, .{
- .name = param_name,
- .ty = .none,
- .is_comptime = is_comptime,
- });
-}
-
fn zirAllocExtended(
sema: *Sema,
block: *Scope.Block,
@@ -2497,10 +2534,6 @@ fn analyzeCall(
sema.func = module_fn;
defer sema.func = parent_func;
- const parent_next_arg_index = sema.next_arg_index;
- sema.next_arg_index = 0;
- defer sema.next_arg_index = parent_next_arg_index;
-
var child_block: Scope.Block = .{
.parent = null,
.sema = sema,
@@ -2537,7 +2570,7 @@ fn analyzeCall(
}
_ = try sema.analyzeBody(&child_block, fn_info.body);
break :res try sema.analyzeBlockBody(block, call_src, &child_block, merges);
- } else if (func_ty_info.is_generic) {
+ } else if (func_ty_info.is_generic) res: {
const func_val = try sema.resolveConstValue(block, func_src, func);
const module_fn = func_val.castTag(.function).?.data;
// Check the Module's generic function map with an adapted context, so that we
@@ -2545,37 +2578,142 @@ fn analyzeCall(
// only to junk it if it matches an existing instantiation.
// TODO
- // Create a Decl for the new function.
- const generic_namespace = try sema.arena.create(Module.Scope.Namespace);
- generic_namespace.* = .{
- .parent = block.src_decl.namespace,
- .file_scope = block.src_decl.namespace.file_scope,
- .ty = func_ty,
+ const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst);
+ const zir_tags = sema.code.instructions.items(.tag);
+ var non_comptime_args_len: u32 = 0;
+ const new_func = new_func: {
+ const namespace = module_fn.owner_decl.namespace;
+ try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
+
+ // Create a Decl for the new function.
+ const new_decl = try mod.allocateNewDecl(namespace, module_fn.owner_decl.src_node);
+ // TODO better names for generic function instantiations
+ const name_index = mod.getNextAnonNameIndex();
+ new_decl.name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{
+ module_fn.owner_decl.name, name_index,
+ });
+ new_decl.src_line = module_fn.owner_decl.src_line;
+ new_decl.is_pub = module_fn.owner_decl.is_pub;
+ new_decl.is_exported = module_fn.owner_decl.is_exported;
+ new_decl.has_align = module_fn.owner_decl.has_align;
+ new_decl.has_linksection = module_fn.owner_decl.has_linksection;
+ new_decl.zir_decl_index = module_fn.owner_decl.zir_decl_index;
+ new_decl.alive = true; // This Decl is called at runtime.
+ new_decl.has_tv = true;
+ new_decl.owns_tv = true;
+ new_decl.analysis = .in_progress;
+ new_decl.generation = mod.generation;
+
+ namespace.anon_decls.putAssumeCapacityNoClobber(new_decl, {});
+
+ var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
+ errdefer new_decl_arena.deinit();
+
+ // Re-run the block that creates the function, with the comptime parameters
+ // pre-populated inside `inst_map`. This causes `param_comptime` and
+ // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a
+ // new, monomorphized function, with the comptime parameters elided.
+ var child_sema: Sema = .{
+ .mod = mod,
+ .gpa = gpa,
+ .arena = sema.arena,
+ .code = sema.code,
+ .owner_decl = new_decl,
+ .namespace = namespace,
+ .func = null,
+ .owner_func = null,
+ .comptime_args = try new_decl_arena.allocator.alloc(TypedValue, args.len),
+ };
+ defer child_sema.deinit();
+
+ var child_block: Scope.Block = .{
+ .parent = null,
+ .sema = &child_sema,
+ .src_decl = new_decl,
+ .instructions = .{},
+ .inlining = null,
+ .is_comptime = true,
+ };
+ defer child_block.instructions.deinit(gpa);
+
+ try child_sema.inst_map.ensureUnusedCapacity(gpa, @intCast(u32, args.len));
+ var arg_i: usize = 0;
+ for (fn_info.param_body) |inst| {
+ const is_comptime = switch (zir_tags[inst]) {
+ .param_comptime, .param_anytype_comptime => true,
+ .param, .param_anytype => false, // TODO make true for always comptime types
+ else => continue,
+ };
+ if (is_comptime) {
+ // TODO: pass .unneeded to resolveConstValue and then if we get
+ // error.NeededSourceLocation resolve the arg source location and
+ // try again.
+ const arg_src = call_src;
+ const arg = args[arg_i];
+ const arg_val = try sema.resolveConstValue(block, arg_src, arg);
+ child_sema.comptime_args[arg_i] = .{
+ .ty = try sema.typeOf(arg).copy(&new_decl_arena.allocator),
+ .val = try arg_val.copy(&new_decl_arena.allocator),
+ };
+ const child_arg = try child_sema.addConstant(sema.typeOf(arg), arg_val);
+ child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
+ } else {
+ non_comptime_args_len += 1;
+ child_sema.comptime_args[arg_i] = .{
+ .ty = Type.initTag(.noreturn),
+ .val = Value.initTag(.unreachable_value),
+ };
+ }
+ arg_i += 1;
+ }
+ const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body);
+ const new_func_val = try child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst);
+ const new_func = new_func_val.castTag(.function).?.data;
+
+ // Populate the Decl ty/val with the function and its type.
+ new_decl.ty = try child_sema.typeOf(new_func_inst).copy(&new_decl_arena.allocator);
+ new_decl.val = try Value.Tag.function.create(&new_decl_arena.allocator, new_func);
+ new_decl.analysis = .complete;
+
+ // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field
+ // will be populated, ensuring it will have `analyzeBody` called with the ZIR
+ // parameters mapped appropriately.
+ try mod.comp.bin_file.allocateDeclIndexes(new_decl);
+ try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func });
+
+ try new_decl.finalizeNewArena(&new_decl_arena);
+ break :new_func try sema.analyzeDeclVal(block, func_src, new_decl);
};
- const new_decl = try mod.allocateNewDecl(generic_namespace, module_fn.owner_decl.src_node);
- _ = new_decl;
-
- // Iterate over the parameters that are comptime, evaluating their type expressions
- // inside a Scope which contains the previous parameters.
- //for (args) |arg, arg_i| {
- //}
-
- // Create a new Fn with only the runtime-known parameters.
- // TODO
-
- // Populate the Decl ty/val with the function and its type.
- // TODO
-
- // Queue up a `codegen_func` work item for the new Fn, making sure it will have
- // `analyzeBody` called with the ZIR parameters mapped appropriately.
- // TODO
// Save it into the Module's generic function map.
// TODO
- // Call it the same as a runtime function.
- // TODO
- return mod.fail(&block.base, func_src, "TODO implement generic fn call", .{});
+ // Make a runtime call to the new function, making sure to omit the comptime args.
+ try sema.requireRuntimeBlock(block, call_src);
+ try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +
+ non_comptime_args_len);
+ const func_inst = try block.addInst(.{
+ .tag = .call,
+ .data = .{ .pl_op = .{
+ .operand = new_func,
+ .payload = sema.addExtraAssumeCapacity(Air.Call{
+ .args_len = non_comptime_args_len,
+ }),
+ } },
+ });
+ var arg_i: usize = 0;
+ for (fn_info.param_body) |inst| {
+ const is_comptime = switch (zir_tags[inst]) {
+ .param_comptime, .param_anytype_comptime => true,
+ .param, .param_anytype => false, // TODO make true for always comptime types
+ else => continue,
+ };
+ if (is_comptime) {
+ sema.air_extra.appendAssumeCapacity(@enumToInt(args[arg_i]));
+ }
+ arg_i += 1;
+ }
+ break :res func_inst;
} else res: {
try sema.requireRuntimeBlock(block, call_src);
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +
@@ -3302,15 +3440,10 @@ fn funcCommon(
const param_types = try sema.arena.alloc(Type, sema.params.items.len);
const comptime_params = try sema.arena.alloc(bool, sema.params.items.len);
for (sema.params.items) |param, i| {
- if (param.ty == .none) {
+ if (param.ty.tag() == .noreturn) {
param_types[i] = Type.initTag(.noreturn); // indicates anytype
} else {
- // TODO make a compile error from `resolveType` report the source location
- // of the specific parameter. Will need to take a similar strategy as
- // `resolveSwitchItemVal` to avoid resolving the source location unless
- // we actually need to report an error.
- const param_src = src;
- param_types[i] = try sema.analyzeAsType(block, param_src, param.ty);
+ param_types[i] = param.ty;
}
comptime_params[i] = param.is_comptime;
any_are_comptime = any_are_comptime or param.is_comptime;
@@ -3402,6 +3535,7 @@ fn funcCommon(
.state = anal_state,
.zir_body_inst = body_inst,
.owner_decl = sema.owner_decl,
+ .comptime_args = if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr,
.lbrace_line = src_locs.lbrace_line,
.rbrace_line = src_locs.rbrace_line,
.lbrace_column = @truncate(u16, src_locs.columns),
@@ -6819,19 +6953,12 @@ fn safetyPanic(
const msg_inst = msg_inst: {
// TODO instead of making a new decl for every panic in the entire compilation,
// introduce the concept of a reference-counted decl for these
- var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
- errdefer new_decl_arena.deinit();
-
- const decl_ty = try Type.Tag.array_u8.create(&new_decl_arena.allocator, msg.len);
- const decl_val = try Value.Tag.bytes.create(&new_decl_arena.allocator, msg);
-
- const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{
- .ty = decl_ty,
- .val = decl_val,
- });
- errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
- try new_decl.finalizeNewArena(&new_decl_arena);
- break :msg_inst try sema.analyzeDeclRef(new_decl);
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
+ break :msg_inst try sema.analyzeDeclRef(try anon_decl.finish(
+ try Type.Tag.array_u8.create(anon_decl.arena(), msg.len),
+ try Value.Tag.bytes.create(anon_decl.arena(), msg),
+ ));
};
const casted_msg_inst = try sema.coerce(block, Type.initTag(.const_slice_u8), msg_inst, src);
@@ -8832,7 +8959,7 @@ fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref {
return sema.addConstant(ty, Value.initTag(.undef));
}
-fn addConstant(sema: *Sema, ty: Type, val: Value) CompileError!Air.Inst.Ref {
+pub fn addConstant(sema: *Sema, ty: Type, val: Value) SemaError!Air.Inst.Ref {
const gpa = sema.gpa;
const ty_inst = try sema.addType(ty);
try sema.air_values.append(gpa, val);
@@ -8888,3 +9015,10 @@ fn isComptimeKnown(
) !bool {
return (try sema.resolveMaybeUndefVal(block, src, inst)) != null;
}
+
+fn nextArgIsComptimeElided(sema: *Sema) bool {
+ if (sema.comptime_args.len == 0) return false;
+ const result = sema.comptime_args[sema.next_arg_index].val.tag() != .unreachable_value;
+ sema.next_arg_index += 1;
+ return result;
+}
diff --git a/src/Zir.zig b/src/Zir.zig
index b7f4c28161..0b93208564 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -4909,6 +4909,7 @@ fn findDeclsBody(
pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) struct {
param_body: []const Inst.Index,
body: []const Inst.Index,
+ total_params_len: u32,
} {
const tags = zir.instructions.items(.tag);
const datas = zir.instructions.items(.data);
@@ -4944,8 +4945,19 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) struct {
};
assert(tags[info.param_block] == .block or tags[info.param_block] == .block_inline);
const param_block = zir.extraData(Inst.Block, datas[info.param_block].pl_node.payload_index);
+ const param_body = zir.extra[param_block.end..][0..param_block.data.body_len];
+ var total_params_len: u32 = 0;
+ for (param_body) |inst| {
+ switch (tags[inst]) {
+ .param, .param_comptime, .param_anytype, .param_anytype_comptime => {
+ total_params_len += 1;
+ },
+ else => continue,
+ }
+ }
return .{
- .param_body = zir.extra[param_block.end..][0..param_block.data.body_len],
+ .param_body = param_body,
.body = info.body,
+ .total_params_len = total_params_len,
};
}
diff --git a/src/type.zig b/src/type.zig
index feb16fd47c..237614e372 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -1182,7 +1182,6 @@ pub const Type = extern union {
.fn_void_no_args,
.fn_naked_noreturn_no_args,
.fn_ccc_void_no_args,
- .function,
.single_const_pointer_to_comptime_int,
.const_slice_u8,
.array_u8_sentinel_0,
@@ -1207,6 +1206,8 @@ pub const Type = extern union {
.anyframe_T,
=> true,
+ .function => !self.castTag(.function).?.data.is_generic,
+
.@"struct" => {
// TODO introduce lazy value mechanism
const struct_obj = self.castTag(.@"struct").?.data;
From ee6f7fee2900ea18bfd056e57952aba606158d7b Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Wed, 4 Aug 2021 00:29:39 +0200
Subject: [PATCH 74/96] libstd: add ArrayHashMap.popOrNull function
which internally calls `ArrayHashMap.pop`, however, returns `?KV`
instead and performs the bounds checking automatically.
This function correponds to `ArrayList.popOrNull` and is meant
to fill the gap for situations where we want the quick lookup offered
by the hash map with elegant ability to iterate and pop of the
container with automatic bound checking that plugs in well with
a `while`-loop such as
```zig
var map = std.ArrayHashMap(K, V).init(allocator);
map.deinit();
while (map.popOrNull()) |entry| {
// ... do something
}
assert(map.count() == 0);
```
---
lib/std/array_hash_map.zig | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/lib/std/array_hash_map.zig b/lib/std/array_hash_map.zig
index 9bcecab47e..4ca603d2e8 100644
--- a/lib/std/array_hash_map.zig
+++ b/lib/std/array_hash_map.zig
@@ -414,6 +414,12 @@ pub fn ArrayHashMap(
pub fn pop(self: *Self) KV {
return self.unmanaged.popContext(self.ctx);
}
+
+ /// Removes the last inserted `Entry` in the hash map and returns it if count is nonzero.
+ /// Otherwise returns null.
+ pub fn popOrNull(self: *Self) ?KV {
+ return self.unmanaged.popOrNullContext(self.ctx);
+ }
};
}
@@ -1181,6 +1187,17 @@ pub fn ArrayHashMapUnmanaged(
};
}
+ /// Removes the last inserted `Entry` in the hash map and returns it if count is nonzero.
+ /// Otherwise returns null.
+ pub fn popOrNull(self: *Self) ?KV {
+ if (@sizeOf(ByIndexContext) != 0)
+ @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call popContext instead.");
+ return self.popOrNullContext(undefined);
+ }
+ pub fn popOrNullContext(self: *Self, ctx: Context) ?KV {
+ return if (self.entries.len == 0) null else self.popContext(ctx);
+ }
+
// ------------------ No pub fns below this point ------------------
fn fetchRemoveByKey(self: *Self, key: anytype, key_ctx: anytype, ctx: ByIndexContext, comptime removal_type: RemovalType) ?KV {
@@ -2094,6 +2111,26 @@ test "pop" {
}
}
+test "popOrNull" {
+ var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
+ defer map.deinit();
+
+ // Insert just enough entries so that the map expands. Afterwards,
+ // pop all entries out of the map.
+
+ var i: i32 = 0;
+ while (i < 9) : (i += 1) {
+ try testing.expect((try map.fetchPut(i, i)) == null);
+ }
+
+ while (map.popOrNull()) |pop| {
+ try testing.expect(pop.key == i - 1 and pop.value == i - 1);
+ i -= 1;
+ }
+
+ try testing.expect(map.count() == 0);
+}
+
test "reIndex" {
var map = ArrayHashMap(i32, i32, AutoContext(i32), true).init(std.testing.allocator);
defer map.deinit();
From bd8baefaaad97d3ec3c47163113e4b5778ef83b4 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Wed, 4 Aug 2021 18:20:06 +0200
Subject: [PATCH 75/96] Update x86_64-macos headers
---
.../Availability.h | 0
.../CommonCrypto/CommonDigest.h | 0
.../TargetConditionals.h | 0
.../_ctermid.h | 0
.../{aarch64-macos-gnu => any-macos-any}/ar.h | 0
.../bsm/audit.h | 0
.../dispatch/block.h | 0
.../dispatch/dispatch.h | 0
.../dispatch/group.h | 0
.../dispatch/object.h | 0
.../dispatch/queue.h | 0
.../dispatch/semaphore.h | 0
.../dispatch/source.h | 0
.../dispatch/workloop.h | 0
.../libkern/OSByteOrder.h | 0
.../libkern/_OSByteOrder.h | 0
.../libproc.h | 0
.../mach-o/arch.h | 0
.../mach-o/arm64/reloc.h | 0
.../mach-o/compact_unwind_encoding.h | 0
.../mach-o/dyld.h | 0
.../mach-o/fat.h | 0
.../mach-o/loader.h | 0
.../mach-o/nlist.h | 0
.../mach-o/ranlib.h | 0
.../mach-o/reloc.h | 0
.../mach-o/stab.h | 0
.../mach-o/x86_64/reloc.h | 0
.../mach/kern_return.h | 0
.../mach/mach_port.h | 0
.../mach/mach_traps.h | 0
.../mach/mach_types.h | 0
.../mach/machine.h | 0
.../mach/machine/_structs.h | 0
.../mach/machine/boolean.h | 0
.../mach/machine/exception.h | 0
.../mach/machine/kern_return.h | 0
.../mach/machine/processor_info.h | 0
.../mach/machine/rpc.h | 0
.../mach/machine/thread_state.h | 0
.../mach/machine/thread_status.h | 0
.../mach/machine/vm_param.h | 0
.../mach/machine/vm_types.h | 0
.../mach/message.h | 0
.../mach/port.h | 0
.../mach/processor_set.h | 0
.../mach/task.h | 0
.../mach/task_info.h | 0
.../mach/task_policy.h | 0
.../mach/task_special_ports.h | 0
.../mach/thread_act.h | 0
.../mach/thread_special_ports.h | 0
.../mach/thread_status.h | 0
.../mach/vm_prot.h | 0
.../mach/vm_statistics.h | 0
.../mach/vm_types.h | 0
.../machine/_mcontext.h | 0
.../machine/_param.h | 0
.../machine/_types.h | 0
.../machine/endian.h | 0
.../machine/limits.h | 0
.../machine/param.h | 0
.../machine/signal.h | 0
.../machine/types.h | 0
.../malloc/_malloc.h | 0
.../malloc/malloc.h | 0
.../math.h | 0
.../net/if.h | 0
.../net/if_var.h | 0
.../net/route.h | 0
.../netinet/in.h | 0
.../netinet/tcp.h | 0
.../netinet6/in6.h | 0
.../objc/objc-api.h | 0
.../objc/runtime.h | 0
.../os/base.h | 0
.../os/clock.h | 0
.../os/object.h | 0
.../os/workgroup.h | 0
.../os/workgroup_base.h | 0
.../os/workgroup_interval.h | 0
.../os/workgroup_object.h | 0
.../os/workgroup_parallel.h | 0
.../pthread.h | 0
.../pthread/sched.h | 0
.../sched.h | 0
.../signal.h | 0
.../simd/common.h | 0
.../simd/conversion.h | 0
.../simd/logic.h | 0
.../simd/math.h | 0
.../simd/packed.h | 0
.../simd/quaternion.h | 0
.../spawn.h | 0
.../stdio.h | 0
.../stdlib.h | 0
.../string.h | 0
.../sys/_pthread/_pthread_attr_t.h | 0
.../sys/_pthread/_pthread_cond_t.h | 0
.../sys/_pthread/_pthread_condattr_t.h | 0
.../sys/_pthread/_pthread_rwlock_t.h | 0
.../sys/_pthread/_pthread_rwlockattr_t.h | 0
.../sys/_pthread/_pthread_t.h | 0
.../sys/_pthread/_pthread_types.h | 0
.../sys/_select.h | 0
.../sys/_symbol_aliasing.h | 0
.../sys/_types/_fd_def.h | 0
.../sys/_types/_int8_t.h | 0
.../sys/_types/_ucontext.h | 0
.../sys/acl.h | 0
.../sys/attr.h | 0
.../sys/cdefs.h | 0
.../sys/event.h | 0
.../sys/fcntl.h | 0
.../sys/ioccom.h | 0
.../sys/kauth.h | 0
.../sys/kern_control.h | 0
.../sys/mman.h | 0
.../sys/mount.h | 0
.../sys/param.h | 0
.../sys/proc.h | 0
.../sys/proc_info.h | 0
.../sys/random.h | 0
.../sys/resource.h | 0
.../sys/shm.h | 0
.../sys/socket.h | 0
.../sys/sockio.h | 0
.../sys/spawn.h | 0
.../sys/stat.h | 0
.../sys/sysctl.h | 0
.../sys/syslimits.h | 0
.../sys/ucontext.h | 0
.../sys/uio.h | 0
.../sys/un.h | 0
.../ucontext.h | 0
.../xlocale/_inttypes.h | 0
.../xlocale/_wchar.h | 0
.../xpc/availability.h | 0
.../xpc/base.h | 0
.../xpc/connection.h | 0
.../xpc/xpc.h | 0
.../include/x86_64-macos-gnu/Availability.h | 605 --
.../x86_64-macos-gnu/AvailabilityInternal.h | 17 +-
.../x86_64-macos-gnu/AvailabilityMacros.h | 10 +-
.../x86_64-macos-gnu/AvailabilityVersions.h | 216 +
.../x86_64-macos-gnu/TargetConditionals.h | 502 --
lib/libc/include/x86_64-macos-gnu/_ctermid.h | 27 -
lib/libc/include/x86_64-macos-gnu/bsm/audit.h | 378 --
.../include/x86_64-macos-gnu/dispatch/block.h | 428 --
.../x86_64-macos-gnu/dispatch/dispatch.h | 75 -
.../include/x86_64-macos-gnu/dispatch/group.h | 279 -
.../x86_64-macos-gnu/dispatch/object.h | 606 --
.../include/x86_64-macos-gnu/dispatch/queue.h | 1674 -----
.../x86_64-macos-gnu/dispatch/semaphore.h | 117 -
.../x86_64-macos-gnu/dispatch/source.h | 780 ---
.../x86_64-macos-gnu/dispatch/workloop.h | 136 -
.../include/x86_64-macos-gnu/i386/_param.h | 4 +-
.../libkern/OSAtomicDeprecated.h | 113 +-
.../x86_64-macos-gnu/libkern/OSAtomicQueue.h | 78 +-
.../x86_64-macos-gnu/libkern/OSByteOrder.h | 305 -
.../x86_64-macos-gnu/libkern/_OSByteOrder.h | 130 -
lib/libc/include/x86_64-macos-gnu/libproc.h | 187 -
.../include/x86_64-macos-gnu/mach-o/dyld.h | 263 -
.../include/x86_64-macos-gnu/mach-o/loader.h | 1577 -----
.../x86_64-macos-gnu/mach/exception_types.h | 204 -
.../mach/host_special_ports.h | 281 -
.../x86_64-macos-gnu/mach/i386/_structs.h | 80 +
.../x86_64-macos-gnu/mach/i386/thread_state.h | 2 +-
.../mach/i386/thread_status.h | 19 +-
.../x86_64-macos-gnu/mach/i386/vm_param.h | 53 +-
.../x86_64-macos-gnu/mach/i386/vm_types.h | 1 -
.../x86_64-macos-gnu/mach/kern_return.h | 330 -
.../include/x86_64-macos-gnu/mach/mach_init.h | 110 -
.../include/x86_64-macos-gnu/mach/mach_port.h | 1808 ------
.../x86_64-macos-gnu/mach/mach_traps.h | 303 -
.../x86_64-macos-gnu/mach/mach_types.h | 254 -
.../include/x86_64-macos-gnu/mach/machine.h | 395 --
.../x86_64-macos-gnu/mach/machine/_structs.h | 38 -
.../x86_64-macos-gnu/mach/machine/boolean.h | 38 -
.../x86_64-macos-gnu/mach/machine/exception.h | 38 -
.../mach/machine/kern_return.h | 38 -
.../mach/machine/processor_info.h | 38 -
.../x86_64-macos-gnu/mach/machine/rpc.h | 38 -
.../mach/machine/thread_state.h | 38 -
.../mach/machine/thread_status.h | 38 -
.../x86_64-macos-gnu/mach/machine/vm_param.h | 38 -
.../x86_64-macos-gnu/mach/machine/vm_types.h | 38 -
.../mach/memory_object_types.h | 299 -
.../include/x86_64-macos-gnu/mach/message.h | 902 ---
lib/libc/include/x86_64-macos-gnu/mach/port.h | 422 --
.../x86_64-macos-gnu/mach/processor_set.h | 540 --
lib/libc/include/x86_64-macos-gnu/mach/task.h | 2523 --------
.../include/x86_64-macos-gnu/mach/task_info.h | 478 --
.../x86_64-macos-gnu/mach/task_policy.h | 189 -
.../mach/task_special_ports.h | 132 -
.../x86_64-macos-gnu/mach/thread_act.h | 1336 ----
.../mach/thread_special_ports.h | 83 -
.../x86_64-macos-gnu/mach/thread_status.h | 97 -
.../include/x86_64-macos-gnu/mach/vm_map.h | 1440 -----
.../include/x86_64-macos-gnu/mach/vm_prot.h | 152 -
.../x86_64-macos-gnu/mach/vm_statistics.h | 523 --
.../include/x86_64-macos-gnu/mach/vm_types.h | 95 -
.../x86_64-macos-gnu/mach_debug/ipc_info.h | 116 -
.../x86_64-macos-gnu/machine/_mcontext.h | 32 -
.../include/x86_64-macos-gnu/machine/_param.h | 32 -
.../include/x86_64-macos-gnu/machine/_types.h | 37 -
.../include/x86_64-macos-gnu/machine/endian.h | 40 -
.../include/x86_64-macos-gnu/machine/limits.h | 9 -
.../include/x86_64-macos-gnu/machine/param.h | 40 -
.../include/x86_64-macos-gnu/machine/signal.h | 37 -
.../include/x86_64-macos-gnu/machine/types.h | 40 -
.../include/x86_64-macos-gnu/malloc/_malloc.h | 56 -
.../include/x86_64-macos-gnu/malloc/malloc.h | 314 -
lib/libc/include/x86_64-macos-gnu/math.h | 771 ---
lib/libc/include/x86_64-macos-gnu/net/if.h | 442 --
.../include/x86_64-macos-gnu/net/if_var.h | 242 -
lib/libc/include/x86_64-macos-gnu/net/route.h | 257 -
.../include/x86_64-macos-gnu/netinet/in.h | 671 --
.../include/x86_64-macos-gnu/netinet/tcp.h | 283 -
.../include/x86_64-macos-gnu/netinet6/in6.h | 667 --
.../include/x86_64-macos-gnu/objc/objc-api.h | 280 -
.../include/x86_64-macos-gnu/objc/runtime.h | 2169 -------
lib/libc/include/x86_64-macos-gnu/os/base.h | 325 -
lib/libc/include/x86_64-macos-gnu/os/clock.h | 18 -
lib/libc/include/x86_64-macos-gnu/os/object.h | 271 -
.../include/x86_64-macos-gnu/os/workgroup.h | 37 -
.../x86_64-macos-gnu/os/workgroup_base.h | 78 -
.../x86_64-macos-gnu/os/workgroup_interval.h | 155 -
.../x86_64-macos-gnu/os/workgroup_object.h | 357 --
.../x86_64-macos-gnu/os/workgroup_parallel.h | 74 -
lib/libc/include/x86_64-macos-gnu/pthread.h | 568 --
.../include/x86_64-macos-gnu/pthread/sched.h | 43 -
.../include/x86_64-macos-gnu/pthread_impl.h | 66 -
lib/libc/include/x86_64-macos-gnu/sched.h | 43 -
lib/libc/include/x86_64-macos-gnu/signal.h | 129 -
.../include/x86_64-macos-gnu/simd/common.h | 4458 --------------
.../x86_64-macos-gnu/simd/conversion.h | 1876 ------
.../include/x86_64-macos-gnu/simd/logic.h | 1315 ----
lib/libc/include/x86_64-macos-gnu/simd/math.h | 5379 -----------------
.../include/x86_64-macos-gnu/simd/packed.h | 1031 ----
.../x86_64-macos-gnu/simd/quaternion.h | 1192 ----
lib/libc/include/x86_64-macos-gnu/spawn.h | 165 -
lib/libc/include/x86_64-macos-gnu/stdio.h | 410 --
lib/libc/include/x86_64-macos-gnu/stdlib.h | 370 --
lib/libc/include/x86_64-macos-gnu/string.h | 193 -
.../sys/_pthread/_pthread_attr_t.h | 32 -
.../sys/_pthread/_pthread_cond_t.h | 32 -
.../sys/_pthread/_pthread_condattr_t.h | 32 -
.../sys/_pthread/_pthread_rwlock_t.h | 32 -
.../sys/_pthread/_pthread_rwlockattr_t.h | 32 -
.../sys/_pthread/_pthread_t.h | 32 -
.../sys/_pthread/_pthread_types.h | 120 -
.../include/x86_64-macos-gnu/sys/_select.h | 52 -
.../x86_64-macos-gnu/sys/_symbol_aliasing.h | 498 --
.../x86_64-macos-gnu/sys/_types/_fd_def.h | 114 -
.../x86_64-macos-gnu/sys/_types/_int8_t.h | 31 -
.../x86_64-macos-gnu/sys/_types/_ucontext.h | 58 -
lib/libc/include/x86_64-macos-gnu/sys/acl.h | 211 -
lib/libc/include/x86_64-macos-gnu/sys/attr.h | 579 --
lib/libc/include/x86_64-macos-gnu/sys/cdefs.h | 855 ---
lib/libc/include/x86_64-macos-gnu/sys/event.h | 396 --
lib/libc/include/x86_64-macos-gnu/sys/fcntl.h | 557 --
.../include/x86_64-macos-gnu/sys/ioccom.h | 99 -
lib/libc/include/x86_64-macos-gnu/sys/kauth.h | 407 --
.../x86_64-macos-gnu/sys/kern_control.h | 151 -
lib/libc/include/x86_64-macos-gnu/sys/mman.h | 250 -
lib/libc/include/x86_64-macos-gnu/sys/mount.h | 423 --
lib/libc/include/x86_64-macos-gnu/sys/param.h | 253 -
lib/libc/include/x86_64-macos-gnu/sys/proc.h | 223 -
.../include/x86_64-macos-gnu/sys/proc_info.h | 799 ---
.../include/x86_64-macos-gnu/sys/resource.h | 458 --
lib/libc/include/x86_64-macos-gnu/sys/shm.h | 186 -
.../include/x86_64-macos-gnu/sys/socket.h | 732 ---
.../include/x86_64-macos-gnu/sys/sockio.h | 180 -
lib/libc/include/x86_64-macos-gnu/sys/spawn.h | 77 -
lib/libc/include/x86_64-macos-gnu/sys/stat.h | 430 --
.../include/x86_64-macos-gnu/sys/sysctl.h | 775 ---
.../include/x86_64-macos-gnu/sys/syslimits.h | 117 -
.../include/x86_64-macos-gnu/sys/ucontext.h | 41 -
lib/libc/include/x86_64-macos-gnu/sys/uio.h | 100 -
lib/libc/include/x86_64-macos-gnu/sys/un.h | 105 -
lib/libc/include/x86_64-macos-gnu/time.h | 208 -
lib/libc/include/x86_64-macos-gnu/ucontext.h | 54 -
.../x86_64-macos-gnu/xlocale/_inttypes.h | 47 -
.../include/x86_64-macos-gnu/xlocale/_wchar.h | 145 -
.../x86_64-macos-gnu/xpc/availability.h | 120 -
lib/libc/include/x86_64-macos-gnu/xpc/base.h | 211 -
.../include/x86_64-macos-gnu/xpc/connection.h | 747 ---
lib/libc/include/x86_64-macos-gnu/xpc/xpc.h | 2663 --------
289 files changed, 455 insertions(+), 60235 deletions(-)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/Availability.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/CommonCrypto/CommonDigest.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/TargetConditionals.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/_ctermid.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/ar.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/bsm/audit.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/dispatch/block.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/dispatch/dispatch.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/dispatch/group.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/dispatch/object.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/dispatch/queue.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/dispatch/semaphore.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/dispatch/source.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/dispatch/workloop.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/libkern/OSByteOrder.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/libkern/_OSByteOrder.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/libproc.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/arch.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/arm64/reloc.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/compact_unwind_encoding.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/dyld.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/fat.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/loader.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/nlist.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/ranlib.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/reloc.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/stab.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach-o/x86_64/reloc.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/kern_return.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/mach_port.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/mach_traps.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/mach_types.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/_structs.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/boolean.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/exception.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/kern_return.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/processor_info.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/rpc.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/thread_state.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/thread_status.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/vm_param.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/machine/vm_types.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/message.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/port.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/processor_set.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/task.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/task_info.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/task_policy.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/task_special_ports.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/thread_act.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/thread_special_ports.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/thread_status.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/vm_prot.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/vm_statistics.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/mach/vm_types.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/machine/_mcontext.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/machine/_param.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/machine/_types.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/machine/endian.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/machine/limits.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/machine/param.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/machine/signal.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/machine/types.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/malloc/_malloc.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/malloc/malloc.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/math.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/net/if.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/net/if_var.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/net/route.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/netinet/in.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/netinet/tcp.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/netinet6/in6.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/objc/objc-api.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/objc/runtime.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/os/base.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/os/clock.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/os/object.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/os/workgroup.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/os/workgroup_base.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/os/workgroup_interval.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/os/workgroup_object.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/os/workgroup_parallel.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/pthread.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/pthread/sched.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sched.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/signal.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/simd/common.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/simd/conversion.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/simd/logic.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/simd/math.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/simd/packed.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/simd/quaternion.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/spawn.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/stdio.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/stdlib.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/string.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_pthread/_pthread_attr_t.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_pthread/_pthread_cond_t.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_pthread/_pthread_condattr_t.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_pthread/_pthread_rwlock_t.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_pthread/_pthread_rwlockattr_t.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_pthread/_pthread_t.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_pthread/_pthread_types.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_select.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_symbol_aliasing.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_types/_fd_def.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_types/_int8_t.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/_types/_ucontext.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/acl.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/attr.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/cdefs.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/event.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/fcntl.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/ioccom.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/kauth.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/kern_control.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/mman.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/mount.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/param.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/proc.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/proc_info.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/random.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/resource.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/shm.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/socket.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/sockio.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/spawn.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/stat.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/sysctl.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/syslimits.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/ucontext.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/uio.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/sys/un.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/ucontext.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/xlocale/_inttypes.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/xlocale/_wchar.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/xpc/availability.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/xpc/base.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/xpc/connection.h (100%)
rename lib/libc/include/{aarch64-macos-gnu => any-macos-any}/xpc/xpc.h (100%)
delete mode 100644 lib/libc/include/x86_64-macos-gnu/Availability.h
create mode 100644 lib/libc/include/x86_64-macos-gnu/AvailabilityVersions.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/TargetConditionals.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/_ctermid.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/bsm/audit.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/dispatch/block.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/dispatch/dispatch.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/dispatch/group.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/dispatch/object.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/dispatch/queue.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/dispatch/semaphore.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/dispatch/source.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/dispatch/workloop.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/libkern/OSByteOrder.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/libkern/_OSByteOrder.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/libproc.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach-o/dyld.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach-o/loader.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/exception_types.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/host_special_ports.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/kern_return.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/mach_init.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/mach_port.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/mach_traps.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/mach_types.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/_structs.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/boolean.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/exception.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/kern_return.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/processor_info.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/rpc.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/thread_state.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/thread_status.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/vm_param.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/machine/vm_types.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/memory_object_types.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/message.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/port.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/processor_set.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/task.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/task_info.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/task_policy.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/task_special_ports.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/thread_act.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/thread_special_ports.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/thread_status.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/vm_map.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/vm_prot.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/vm_statistics.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach/vm_types.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/mach_debug/ipc_info.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/machine/_mcontext.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/machine/_param.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/machine/_types.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/machine/endian.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/machine/limits.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/machine/param.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/machine/signal.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/machine/types.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/malloc/_malloc.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/malloc/malloc.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/math.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/net/if.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/net/if_var.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/net/route.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/netinet/in.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/netinet/tcp.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/netinet6/in6.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/objc/objc-api.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/objc/runtime.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/os/base.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/os/clock.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/os/object.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/os/workgroup.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/os/workgroup_base.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/os/workgroup_interval.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/os/workgroup_object.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/os/workgroup_parallel.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/pthread.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/pthread/sched.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/pthread_impl.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sched.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/signal.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/simd/common.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/simd/conversion.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/simd/logic.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/simd/math.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/simd/packed.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/simd/quaternion.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/spawn.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/stdio.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/stdlib.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/string.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_pthread/_pthread_attr_t.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_pthread/_pthread_cond_t.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_pthread/_pthread_condattr_t.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_pthread/_pthread_rwlock_t.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_pthread/_pthread_rwlockattr_t.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_pthread/_pthread_t.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_pthread/_pthread_types.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_select.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_symbol_aliasing.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_types/_fd_def.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_types/_int8_t.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/_types/_ucontext.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/acl.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/attr.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/cdefs.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/event.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/fcntl.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/ioccom.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/kauth.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/kern_control.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/mman.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/mount.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/param.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/proc.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/proc_info.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/resource.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/shm.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/socket.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/sockio.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/spawn.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/stat.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/sysctl.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/syslimits.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/ucontext.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/uio.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/sys/un.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/time.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/ucontext.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/xlocale/_inttypes.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/xlocale/_wchar.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/xpc/availability.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/xpc/base.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/xpc/connection.h
delete mode 100644 lib/libc/include/x86_64-macos-gnu/xpc/xpc.h
diff --git a/lib/libc/include/aarch64-macos-gnu/Availability.h b/lib/libc/include/any-macos-any/Availability.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/Availability.h
rename to lib/libc/include/any-macos-any/Availability.h
diff --git a/lib/libc/include/aarch64-macos-gnu/CommonCrypto/CommonDigest.h b/lib/libc/include/any-macos-any/CommonCrypto/CommonDigest.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/CommonCrypto/CommonDigest.h
rename to lib/libc/include/any-macos-any/CommonCrypto/CommonDigest.h
diff --git a/lib/libc/include/aarch64-macos-gnu/TargetConditionals.h b/lib/libc/include/any-macos-any/TargetConditionals.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/TargetConditionals.h
rename to lib/libc/include/any-macos-any/TargetConditionals.h
diff --git a/lib/libc/include/aarch64-macos-gnu/_ctermid.h b/lib/libc/include/any-macos-any/_ctermid.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/_ctermid.h
rename to lib/libc/include/any-macos-any/_ctermid.h
diff --git a/lib/libc/include/aarch64-macos-gnu/ar.h b/lib/libc/include/any-macos-any/ar.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/ar.h
rename to lib/libc/include/any-macos-any/ar.h
diff --git a/lib/libc/include/aarch64-macos-gnu/bsm/audit.h b/lib/libc/include/any-macos-any/bsm/audit.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/bsm/audit.h
rename to lib/libc/include/any-macos-any/bsm/audit.h
diff --git a/lib/libc/include/aarch64-macos-gnu/dispatch/block.h b/lib/libc/include/any-macos-any/dispatch/block.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/dispatch/block.h
rename to lib/libc/include/any-macos-any/dispatch/block.h
diff --git a/lib/libc/include/aarch64-macos-gnu/dispatch/dispatch.h b/lib/libc/include/any-macos-any/dispatch/dispatch.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/dispatch/dispatch.h
rename to lib/libc/include/any-macos-any/dispatch/dispatch.h
diff --git a/lib/libc/include/aarch64-macos-gnu/dispatch/group.h b/lib/libc/include/any-macos-any/dispatch/group.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/dispatch/group.h
rename to lib/libc/include/any-macos-any/dispatch/group.h
diff --git a/lib/libc/include/aarch64-macos-gnu/dispatch/object.h b/lib/libc/include/any-macos-any/dispatch/object.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/dispatch/object.h
rename to lib/libc/include/any-macos-any/dispatch/object.h
diff --git a/lib/libc/include/aarch64-macos-gnu/dispatch/queue.h b/lib/libc/include/any-macos-any/dispatch/queue.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/dispatch/queue.h
rename to lib/libc/include/any-macos-any/dispatch/queue.h
diff --git a/lib/libc/include/aarch64-macos-gnu/dispatch/semaphore.h b/lib/libc/include/any-macos-any/dispatch/semaphore.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/dispatch/semaphore.h
rename to lib/libc/include/any-macos-any/dispatch/semaphore.h
diff --git a/lib/libc/include/aarch64-macos-gnu/dispatch/source.h b/lib/libc/include/any-macos-any/dispatch/source.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/dispatch/source.h
rename to lib/libc/include/any-macos-any/dispatch/source.h
diff --git a/lib/libc/include/aarch64-macos-gnu/dispatch/workloop.h b/lib/libc/include/any-macos-any/dispatch/workloop.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/dispatch/workloop.h
rename to lib/libc/include/any-macos-any/dispatch/workloop.h
diff --git a/lib/libc/include/aarch64-macos-gnu/libkern/OSByteOrder.h b/lib/libc/include/any-macos-any/libkern/OSByteOrder.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/libkern/OSByteOrder.h
rename to lib/libc/include/any-macos-any/libkern/OSByteOrder.h
diff --git a/lib/libc/include/aarch64-macos-gnu/libkern/_OSByteOrder.h b/lib/libc/include/any-macos-any/libkern/_OSByteOrder.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/libkern/_OSByteOrder.h
rename to lib/libc/include/any-macos-any/libkern/_OSByteOrder.h
diff --git a/lib/libc/include/aarch64-macos-gnu/libproc.h b/lib/libc/include/any-macos-any/libproc.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/libproc.h
rename to lib/libc/include/any-macos-any/libproc.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/arch.h b/lib/libc/include/any-macos-any/mach-o/arch.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/arch.h
rename to lib/libc/include/any-macos-any/mach-o/arch.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/arm64/reloc.h b/lib/libc/include/any-macos-any/mach-o/arm64/reloc.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/arm64/reloc.h
rename to lib/libc/include/any-macos-any/mach-o/arm64/reloc.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/compact_unwind_encoding.h b/lib/libc/include/any-macos-any/mach-o/compact_unwind_encoding.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/compact_unwind_encoding.h
rename to lib/libc/include/any-macos-any/mach-o/compact_unwind_encoding.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/dyld.h b/lib/libc/include/any-macos-any/mach-o/dyld.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/dyld.h
rename to lib/libc/include/any-macos-any/mach-o/dyld.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/fat.h b/lib/libc/include/any-macos-any/mach-o/fat.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/fat.h
rename to lib/libc/include/any-macos-any/mach-o/fat.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/loader.h b/lib/libc/include/any-macos-any/mach-o/loader.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/loader.h
rename to lib/libc/include/any-macos-any/mach-o/loader.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/nlist.h b/lib/libc/include/any-macos-any/mach-o/nlist.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/nlist.h
rename to lib/libc/include/any-macos-any/mach-o/nlist.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/ranlib.h b/lib/libc/include/any-macos-any/mach-o/ranlib.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/ranlib.h
rename to lib/libc/include/any-macos-any/mach-o/ranlib.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/reloc.h b/lib/libc/include/any-macos-any/mach-o/reloc.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/reloc.h
rename to lib/libc/include/any-macos-any/mach-o/reloc.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/stab.h b/lib/libc/include/any-macos-any/mach-o/stab.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/stab.h
rename to lib/libc/include/any-macos-any/mach-o/stab.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach-o/x86_64/reloc.h b/lib/libc/include/any-macos-any/mach-o/x86_64/reloc.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach-o/x86_64/reloc.h
rename to lib/libc/include/any-macos-any/mach-o/x86_64/reloc.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/kern_return.h b/lib/libc/include/any-macos-any/mach/kern_return.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/kern_return.h
rename to lib/libc/include/any-macos-any/mach/kern_return.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/mach_port.h b/lib/libc/include/any-macos-any/mach/mach_port.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/mach_port.h
rename to lib/libc/include/any-macos-any/mach/mach_port.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/mach_traps.h b/lib/libc/include/any-macos-any/mach/mach_traps.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/mach_traps.h
rename to lib/libc/include/any-macos-any/mach/mach_traps.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/mach_types.h b/lib/libc/include/any-macos-any/mach/mach_types.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/mach_types.h
rename to lib/libc/include/any-macos-any/mach/mach_types.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine.h b/lib/libc/include/any-macos-any/mach/machine.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine.h
rename to lib/libc/include/any-macos-any/mach/machine.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/_structs.h b/lib/libc/include/any-macos-any/mach/machine/_structs.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/_structs.h
rename to lib/libc/include/any-macos-any/mach/machine/_structs.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/boolean.h b/lib/libc/include/any-macos-any/mach/machine/boolean.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/boolean.h
rename to lib/libc/include/any-macos-any/mach/machine/boolean.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/exception.h b/lib/libc/include/any-macos-any/mach/machine/exception.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/exception.h
rename to lib/libc/include/any-macos-any/mach/machine/exception.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/kern_return.h b/lib/libc/include/any-macos-any/mach/machine/kern_return.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/kern_return.h
rename to lib/libc/include/any-macos-any/mach/machine/kern_return.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/processor_info.h b/lib/libc/include/any-macos-any/mach/machine/processor_info.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/processor_info.h
rename to lib/libc/include/any-macos-any/mach/machine/processor_info.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/rpc.h b/lib/libc/include/any-macos-any/mach/machine/rpc.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/rpc.h
rename to lib/libc/include/any-macos-any/mach/machine/rpc.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/thread_state.h b/lib/libc/include/any-macos-any/mach/machine/thread_state.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/thread_state.h
rename to lib/libc/include/any-macos-any/mach/machine/thread_state.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/thread_status.h b/lib/libc/include/any-macos-any/mach/machine/thread_status.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/thread_status.h
rename to lib/libc/include/any-macos-any/mach/machine/thread_status.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/vm_param.h b/lib/libc/include/any-macos-any/mach/machine/vm_param.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/vm_param.h
rename to lib/libc/include/any-macos-any/mach/machine/vm_param.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/machine/vm_types.h b/lib/libc/include/any-macos-any/mach/machine/vm_types.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/machine/vm_types.h
rename to lib/libc/include/any-macos-any/mach/machine/vm_types.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/message.h b/lib/libc/include/any-macos-any/mach/message.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/message.h
rename to lib/libc/include/any-macos-any/mach/message.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/port.h b/lib/libc/include/any-macos-any/mach/port.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/port.h
rename to lib/libc/include/any-macos-any/mach/port.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/processor_set.h b/lib/libc/include/any-macos-any/mach/processor_set.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/processor_set.h
rename to lib/libc/include/any-macos-any/mach/processor_set.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/task.h b/lib/libc/include/any-macos-any/mach/task.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/task.h
rename to lib/libc/include/any-macos-any/mach/task.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/task_info.h b/lib/libc/include/any-macos-any/mach/task_info.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/task_info.h
rename to lib/libc/include/any-macos-any/mach/task_info.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/task_policy.h b/lib/libc/include/any-macos-any/mach/task_policy.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/task_policy.h
rename to lib/libc/include/any-macos-any/mach/task_policy.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/task_special_ports.h b/lib/libc/include/any-macos-any/mach/task_special_ports.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/task_special_ports.h
rename to lib/libc/include/any-macos-any/mach/task_special_ports.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/thread_act.h b/lib/libc/include/any-macos-any/mach/thread_act.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/thread_act.h
rename to lib/libc/include/any-macos-any/mach/thread_act.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/thread_special_ports.h b/lib/libc/include/any-macos-any/mach/thread_special_ports.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/thread_special_ports.h
rename to lib/libc/include/any-macos-any/mach/thread_special_ports.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/thread_status.h b/lib/libc/include/any-macos-any/mach/thread_status.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/thread_status.h
rename to lib/libc/include/any-macos-any/mach/thread_status.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/vm_prot.h b/lib/libc/include/any-macos-any/mach/vm_prot.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/vm_prot.h
rename to lib/libc/include/any-macos-any/mach/vm_prot.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/vm_statistics.h b/lib/libc/include/any-macos-any/mach/vm_statistics.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/vm_statistics.h
rename to lib/libc/include/any-macos-any/mach/vm_statistics.h
diff --git a/lib/libc/include/aarch64-macos-gnu/mach/vm_types.h b/lib/libc/include/any-macos-any/mach/vm_types.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/mach/vm_types.h
rename to lib/libc/include/any-macos-any/mach/vm_types.h
diff --git a/lib/libc/include/aarch64-macos-gnu/machine/_mcontext.h b/lib/libc/include/any-macos-any/machine/_mcontext.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/machine/_mcontext.h
rename to lib/libc/include/any-macos-any/machine/_mcontext.h
diff --git a/lib/libc/include/aarch64-macos-gnu/machine/_param.h b/lib/libc/include/any-macos-any/machine/_param.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/machine/_param.h
rename to lib/libc/include/any-macos-any/machine/_param.h
diff --git a/lib/libc/include/aarch64-macos-gnu/machine/_types.h b/lib/libc/include/any-macos-any/machine/_types.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/machine/_types.h
rename to lib/libc/include/any-macos-any/machine/_types.h
diff --git a/lib/libc/include/aarch64-macos-gnu/machine/endian.h b/lib/libc/include/any-macos-any/machine/endian.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/machine/endian.h
rename to lib/libc/include/any-macos-any/machine/endian.h
diff --git a/lib/libc/include/aarch64-macos-gnu/machine/limits.h b/lib/libc/include/any-macos-any/machine/limits.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/machine/limits.h
rename to lib/libc/include/any-macos-any/machine/limits.h
diff --git a/lib/libc/include/aarch64-macos-gnu/machine/param.h b/lib/libc/include/any-macos-any/machine/param.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/machine/param.h
rename to lib/libc/include/any-macos-any/machine/param.h
diff --git a/lib/libc/include/aarch64-macos-gnu/machine/signal.h b/lib/libc/include/any-macos-any/machine/signal.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/machine/signal.h
rename to lib/libc/include/any-macos-any/machine/signal.h
diff --git a/lib/libc/include/aarch64-macos-gnu/machine/types.h b/lib/libc/include/any-macos-any/machine/types.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/machine/types.h
rename to lib/libc/include/any-macos-any/machine/types.h
diff --git a/lib/libc/include/aarch64-macos-gnu/malloc/_malloc.h b/lib/libc/include/any-macos-any/malloc/_malloc.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/malloc/_malloc.h
rename to lib/libc/include/any-macos-any/malloc/_malloc.h
diff --git a/lib/libc/include/aarch64-macos-gnu/malloc/malloc.h b/lib/libc/include/any-macos-any/malloc/malloc.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/malloc/malloc.h
rename to lib/libc/include/any-macos-any/malloc/malloc.h
diff --git a/lib/libc/include/aarch64-macos-gnu/math.h b/lib/libc/include/any-macos-any/math.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/math.h
rename to lib/libc/include/any-macos-any/math.h
diff --git a/lib/libc/include/aarch64-macos-gnu/net/if.h b/lib/libc/include/any-macos-any/net/if.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/net/if.h
rename to lib/libc/include/any-macos-any/net/if.h
diff --git a/lib/libc/include/aarch64-macos-gnu/net/if_var.h b/lib/libc/include/any-macos-any/net/if_var.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/net/if_var.h
rename to lib/libc/include/any-macos-any/net/if_var.h
diff --git a/lib/libc/include/aarch64-macos-gnu/net/route.h b/lib/libc/include/any-macos-any/net/route.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/net/route.h
rename to lib/libc/include/any-macos-any/net/route.h
diff --git a/lib/libc/include/aarch64-macos-gnu/netinet/in.h b/lib/libc/include/any-macos-any/netinet/in.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/netinet/in.h
rename to lib/libc/include/any-macos-any/netinet/in.h
diff --git a/lib/libc/include/aarch64-macos-gnu/netinet/tcp.h b/lib/libc/include/any-macos-any/netinet/tcp.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/netinet/tcp.h
rename to lib/libc/include/any-macos-any/netinet/tcp.h
diff --git a/lib/libc/include/aarch64-macos-gnu/netinet6/in6.h b/lib/libc/include/any-macos-any/netinet6/in6.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/netinet6/in6.h
rename to lib/libc/include/any-macos-any/netinet6/in6.h
diff --git a/lib/libc/include/aarch64-macos-gnu/objc/objc-api.h b/lib/libc/include/any-macos-any/objc/objc-api.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/objc/objc-api.h
rename to lib/libc/include/any-macos-any/objc/objc-api.h
diff --git a/lib/libc/include/aarch64-macos-gnu/objc/runtime.h b/lib/libc/include/any-macos-any/objc/runtime.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/objc/runtime.h
rename to lib/libc/include/any-macos-any/objc/runtime.h
diff --git a/lib/libc/include/aarch64-macos-gnu/os/base.h b/lib/libc/include/any-macos-any/os/base.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/os/base.h
rename to lib/libc/include/any-macos-any/os/base.h
diff --git a/lib/libc/include/aarch64-macos-gnu/os/clock.h b/lib/libc/include/any-macos-any/os/clock.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/os/clock.h
rename to lib/libc/include/any-macos-any/os/clock.h
diff --git a/lib/libc/include/aarch64-macos-gnu/os/object.h b/lib/libc/include/any-macos-any/os/object.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/os/object.h
rename to lib/libc/include/any-macos-any/os/object.h
diff --git a/lib/libc/include/aarch64-macos-gnu/os/workgroup.h b/lib/libc/include/any-macos-any/os/workgroup.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/os/workgroup.h
rename to lib/libc/include/any-macos-any/os/workgroup.h
diff --git a/lib/libc/include/aarch64-macos-gnu/os/workgroup_base.h b/lib/libc/include/any-macos-any/os/workgroup_base.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/os/workgroup_base.h
rename to lib/libc/include/any-macos-any/os/workgroup_base.h
diff --git a/lib/libc/include/aarch64-macos-gnu/os/workgroup_interval.h b/lib/libc/include/any-macos-any/os/workgroup_interval.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/os/workgroup_interval.h
rename to lib/libc/include/any-macos-any/os/workgroup_interval.h
diff --git a/lib/libc/include/aarch64-macos-gnu/os/workgroup_object.h b/lib/libc/include/any-macos-any/os/workgroup_object.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/os/workgroup_object.h
rename to lib/libc/include/any-macos-any/os/workgroup_object.h
diff --git a/lib/libc/include/aarch64-macos-gnu/os/workgroup_parallel.h b/lib/libc/include/any-macos-any/os/workgroup_parallel.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/os/workgroup_parallel.h
rename to lib/libc/include/any-macos-any/os/workgroup_parallel.h
diff --git a/lib/libc/include/aarch64-macos-gnu/pthread.h b/lib/libc/include/any-macos-any/pthread.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/pthread.h
rename to lib/libc/include/any-macos-any/pthread.h
diff --git a/lib/libc/include/aarch64-macos-gnu/pthread/sched.h b/lib/libc/include/any-macos-any/pthread/sched.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/pthread/sched.h
rename to lib/libc/include/any-macos-any/pthread/sched.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sched.h b/lib/libc/include/any-macos-any/sched.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sched.h
rename to lib/libc/include/any-macos-any/sched.h
diff --git a/lib/libc/include/aarch64-macos-gnu/signal.h b/lib/libc/include/any-macos-any/signal.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/signal.h
rename to lib/libc/include/any-macos-any/signal.h
diff --git a/lib/libc/include/aarch64-macos-gnu/simd/common.h b/lib/libc/include/any-macos-any/simd/common.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/simd/common.h
rename to lib/libc/include/any-macos-any/simd/common.h
diff --git a/lib/libc/include/aarch64-macos-gnu/simd/conversion.h b/lib/libc/include/any-macos-any/simd/conversion.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/simd/conversion.h
rename to lib/libc/include/any-macos-any/simd/conversion.h
diff --git a/lib/libc/include/aarch64-macos-gnu/simd/logic.h b/lib/libc/include/any-macos-any/simd/logic.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/simd/logic.h
rename to lib/libc/include/any-macos-any/simd/logic.h
diff --git a/lib/libc/include/aarch64-macos-gnu/simd/math.h b/lib/libc/include/any-macos-any/simd/math.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/simd/math.h
rename to lib/libc/include/any-macos-any/simd/math.h
diff --git a/lib/libc/include/aarch64-macos-gnu/simd/packed.h b/lib/libc/include/any-macos-any/simd/packed.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/simd/packed.h
rename to lib/libc/include/any-macos-any/simd/packed.h
diff --git a/lib/libc/include/aarch64-macos-gnu/simd/quaternion.h b/lib/libc/include/any-macos-any/simd/quaternion.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/simd/quaternion.h
rename to lib/libc/include/any-macos-any/simd/quaternion.h
diff --git a/lib/libc/include/aarch64-macos-gnu/spawn.h b/lib/libc/include/any-macos-any/spawn.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/spawn.h
rename to lib/libc/include/any-macos-any/spawn.h
diff --git a/lib/libc/include/aarch64-macos-gnu/stdio.h b/lib/libc/include/any-macos-any/stdio.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/stdio.h
rename to lib/libc/include/any-macos-any/stdio.h
diff --git a/lib/libc/include/aarch64-macos-gnu/stdlib.h b/lib/libc/include/any-macos-any/stdlib.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/stdlib.h
rename to lib/libc/include/any-macos-any/stdlib.h
diff --git a/lib/libc/include/aarch64-macos-gnu/string.h b/lib/libc/include/any-macos-any/string.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/string.h
rename to lib/libc/include/any-macos-any/string.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_attr_t.h b/lib/libc/include/any-macos-any/sys/_pthread/_pthread_attr_t.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_attr_t.h
rename to lib/libc/include/any-macos-any/sys/_pthread/_pthread_attr_t.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_cond_t.h b/lib/libc/include/any-macos-any/sys/_pthread/_pthread_cond_t.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_cond_t.h
rename to lib/libc/include/any-macos-any/sys/_pthread/_pthread_cond_t.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_condattr_t.h b/lib/libc/include/any-macos-any/sys/_pthread/_pthread_condattr_t.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_condattr_t.h
rename to lib/libc/include/any-macos-any/sys/_pthread/_pthread_condattr_t.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_rwlock_t.h b/lib/libc/include/any-macos-any/sys/_pthread/_pthread_rwlock_t.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_rwlock_t.h
rename to lib/libc/include/any-macos-any/sys/_pthread/_pthread_rwlock_t.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_rwlockattr_t.h b/lib/libc/include/any-macos-any/sys/_pthread/_pthread_rwlockattr_t.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_rwlockattr_t.h
rename to lib/libc/include/any-macos-any/sys/_pthread/_pthread_rwlockattr_t.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_t.h b/lib/libc/include/any-macos-any/sys/_pthread/_pthread_t.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_t.h
rename to lib/libc/include/any-macos-any/sys/_pthread/_pthread_t.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_types.h b/lib/libc/include/any-macos-any/sys/_pthread/_pthread_types.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_pthread/_pthread_types.h
rename to lib/libc/include/any-macos-any/sys/_pthread/_pthread_types.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_select.h b/lib/libc/include/any-macos-any/sys/_select.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_select.h
rename to lib/libc/include/any-macos-any/sys/_select.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_symbol_aliasing.h b/lib/libc/include/any-macos-any/sys/_symbol_aliasing.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_symbol_aliasing.h
rename to lib/libc/include/any-macos-any/sys/_symbol_aliasing.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_types/_fd_def.h b/lib/libc/include/any-macos-any/sys/_types/_fd_def.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_types/_fd_def.h
rename to lib/libc/include/any-macos-any/sys/_types/_fd_def.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_types/_int8_t.h b/lib/libc/include/any-macos-any/sys/_types/_int8_t.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_types/_int8_t.h
rename to lib/libc/include/any-macos-any/sys/_types/_int8_t.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/_types/_ucontext.h b/lib/libc/include/any-macos-any/sys/_types/_ucontext.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/_types/_ucontext.h
rename to lib/libc/include/any-macos-any/sys/_types/_ucontext.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/acl.h b/lib/libc/include/any-macos-any/sys/acl.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/acl.h
rename to lib/libc/include/any-macos-any/sys/acl.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/attr.h b/lib/libc/include/any-macos-any/sys/attr.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/attr.h
rename to lib/libc/include/any-macos-any/sys/attr.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/cdefs.h b/lib/libc/include/any-macos-any/sys/cdefs.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/cdefs.h
rename to lib/libc/include/any-macos-any/sys/cdefs.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/event.h b/lib/libc/include/any-macos-any/sys/event.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/event.h
rename to lib/libc/include/any-macos-any/sys/event.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/fcntl.h b/lib/libc/include/any-macos-any/sys/fcntl.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/fcntl.h
rename to lib/libc/include/any-macos-any/sys/fcntl.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/ioccom.h b/lib/libc/include/any-macos-any/sys/ioccom.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/ioccom.h
rename to lib/libc/include/any-macos-any/sys/ioccom.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/kauth.h b/lib/libc/include/any-macos-any/sys/kauth.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/kauth.h
rename to lib/libc/include/any-macos-any/sys/kauth.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/kern_control.h b/lib/libc/include/any-macos-any/sys/kern_control.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/kern_control.h
rename to lib/libc/include/any-macos-any/sys/kern_control.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/mman.h b/lib/libc/include/any-macos-any/sys/mman.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/mman.h
rename to lib/libc/include/any-macos-any/sys/mman.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/mount.h b/lib/libc/include/any-macos-any/sys/mount.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/mount.h
rename to lib/libc/include/any-macos-any/sys/mount.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/param.h b/lib/libc/include/any-macos-any/sys/param.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/param.h
rename to lib/libc/include/any-macos-any/sys/param.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/proc.h b/lib/libc/include/any-macos-any/sys/proc.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/proc.h
rename to lib/libc/include/any-macos-any/sys/proc.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/proc_info.h b/lib/libc/include/any-macos-any/sys/proc_info.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/proc_info.h
rename to lib/libc/include/any-macos-any/sys/proc_info.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/random.h b/lib/libc/include/any-macos-any/sys/random.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/random.h
rename to lib/libc/include/any-macos-any/sys/random.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/resource.h b/lib/libc/include/any-macos-any/sys/resource.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/resource.h
rename to lib/libc/include/any-macos-any/sys/resource.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/shm.h b/lib/libc/include/any-macos-any/sys/shm.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/shm.h
rename to lib/libc/include/any-macos-any/sys/shm.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/socket.h b/lib/libc/include/any-macos-any/sys/socket.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/socket.h
rename to lib/libc/include/any-macos-any/sys/socket.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/sockio.h b/lib/libc/include/any-macos-any/sys/sockio.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/sockio.h
rename to lib/libc/include/any-macos-any/sys/sockio.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/spawn.h b/lib/libc/include/any-macos-any/sys/spawn.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/spawn.h
rename to lib/libc/include/any-macos-any/sys/spawn.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/stat.h b/lib/libc/include/any-macos-any/sys/stat.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/stat.h
rename to lib/libc/include/any-macos-any/sys/stat.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/sysctl.h b/lib/libc/include/any-macos-any/sys/sysctl.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/sysctl.h
rename to lib/libc/include/any-macos-any/sys/sysctl.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/syslimits.h b/lib/libc/include/any-macos-any/sys/syslimits.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/syslimits.h
rename to lib/libc/include/any-macos-any/sys/syslimits.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/ucontext.h b/lib/libc/include/any-macos-any/sys/ucontext.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/ucontext.h
rename to lib/libc/include/any-macos-any/sys/ucontext.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/uio.h b/lib/libc/include/any-macos-any/sys/uio.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/uio.h
rename to lib/libc/include/any-macos-any/sys/uio.h
diff --git a/lib/libc/include/aarch64-macos-gnu/sys/un.h b/lib/libc/include/any-macos-any/sys/un.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/sys/un.h
rename to lib/libc/include/any-macos-any/sys/un.h
diff --git a/lib/libc/include/aarch64-macos-gnu/ucontext.h b/lib/libc/include/any-macos-any/ucontext.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/ucontext.h
rename to lib/libc/include/any-macos-any/ucontext.h
diff --git a/lib/libc/include/aarch64-macos-gnu/xlocale/_inttypes.h b/lib/libc/include/any-macos-any/xlocale/_inttypes.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/xlocale/_inttypes.h
rename to lib/libc/include/any-macos-any/xlocale/_inttypes.h
diff --git a/lib/libc/include/aarch64-macos-gnu/xlocale/_wchar.h b/lib/libc/include/any-macos-any/xlocale/_wchar.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/xlocale/_wchar.h
rename to lib/libc/include/any-macos-any/xlocale/_wchar.h
diff --git a/lib/libc/include/aarch64-macos-gnu/xpc/availability.h b/lib/libc/include/any-macos-any/xpc/availability.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/xpc/availability.h
rename to lib/libc/include/any-macos-any/xpc/availability.h
diff --git a/lib/libc/include/aarch64-macos-gnu/xpc/base.h b/lib/libc/include/any-macos-any/xpc/base.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/xpc/base.h
rename to lib/libc/include/any-macos-any/xpc/base.h
diff --git a/lib/libc/include/aarch64-macos-gnu/xpc/connection.h b/lib/libc/include/any-macos-any/xpc/connection.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/xpc/connection.h
rename to lib/libc/include/any-macos-any/xpc/connection.h
diff --git a/lib/libc/include/aarch64-macos-gnu/xpc/xpc.h b/lib/libc/include/any-macos-any/xpc/xpc.h
similarity index 100%
rename from lib/libc/include/aarch64-macos-gnu/xpc/xpc.h
rename to lib/libc/include/any-macos-any/xpc/xpc.h
diff --git a/lib/libc/include/x86_64-macos-gnu/Availability.h b/lib/libc/include/x86_64-macos-gnu/Availability.h
deleted file mode 100644
index bdfd794d89..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/Availability.h
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * Copyright (c) 2007-2016 by Apple Inc.. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __AVAILABILITY__
-#define __AVAILABILITY__
- /*
- These macros are for use in OS header files. They enable function prototypes
- and Objective-C methods to be tagged with the OS version in which they
- were first available; and, if applicable, the OS version in which they
- became deprecated.
-
- The desktop Mac OS X and iOS each have different version numbers.
- The __OSX_AVAILABLE_STARTING() macro allows you to specify both the desktop
- and iOS version numbers. For instance:
- __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_2_0)
- means the function/method was first available on Mac OS X 10.2 on the desktop
- and first available in iOS 2.0 on the iPhone.
-
- If a function is available on one platform, but not the other a _NA (not
- applicable) parameter is used. For instance:
- __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_NA)
- means that the function/method was first available on Mac OS X 10.3, and it
- currently not implemented on the iPhone.
-
- At some point, a function/method may be deprecated. That means Apple
- recommends applications stop using the function, either because there is a
- better replacement or the functionality is being phased out. Deprecated
- functions/methods can be tagged with a __OSX_AVAILABLE_BUT_DEPRECATED()
- macro which specifies the OS version where the function became available
- as well as the OS version in which it became deprecated. For instance:
- __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5,__IPHONE_NA,__IPHONE_NA)
- means that the function/method was introduced in Mac OS X 10.0, then
- became deprecated beginning in Mac OS X 10.5. On iOS the function
- has never been available.
-
- For these macros to function properly, a program must specify the OS version range
- it is targeting. The min OS version is specified as an option to the compiler:
- -mmacosx-version-min=10.x when building for Mac OS X, and -miphoneos-version-min=y.z
- when building for the iPhone. The upper bound for the OS version is rarely needed,
- but it can be set on the command line via: -D__MAC_OS_X_VERSION_MAX_ALLOWED=10x0 for
- Mac OS X and __IPHONE_OS_VERSION_MAX_ALLOWED = y0z00 for iOS.
-
- Examples:
-
- A function available in Mac OS X 10.5 and later, but not on the phone:
-
- extern void mymacfunc() __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_NA);
-
-
- An Objective-C method in Mac OS X 10.5 and later, but not on the phone:
-
- @interface MyClass : NSObject
- -(void) mymacmethod __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_NA);
- @end
-
-
- An enum available on the phone, but not available on Mac OS X:
-
- #if __IPHONE_OS_VERSION_MIN_REQUIRED
- enum { myEnum = 1 };
- #endif
- Note: this works when targeting the Mac OS X platform because
- __IPHONE_OS_VERSION_MIN_REQUIRED is undefined which evaluates to zero.
-
-
- An enum with values added in different iPhoneOS versions:
-
- enum {
- myX = 1, // Usable on iPhoneOS 2.1 and later
- myY = 2, // Usable on iPhoneOS 3.0 and later
- myZ = 3, // Usable on iPhoneOS 3.0 and later
- ...
- Note: you do not want to use #if with enumeration values
- when a client needs to see all values at compile time
- and use runtime logic to only use the viable values.
-
-
- It is also possible to use the *_VERSION_MIN_REQUIRED in source code to make one
- source base that can be compiled to target a range of OS versions. It is best
- to not use the _MAC_* and __IPHONE_* macros for comparisons, but rather their values.
- That is because you might get compiled on an old OS that does not define a later
- OS version macro, and in the C preprocessor undefined values evaluate to zero
- in expresssions, which could cause the #if expression to evaluate in an unexpected
- way.
-
- #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
- // code only compiled when targeting Mac OS X and not iPhone
- // note use of 1050 instead of __MAC_10_5
- #if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050
- // code in here might run on pre-Leopard OS
- #else
- // code here can assume Leopard or later
- #endif
- #endif
-
-
-*/
-
-/*
- * __API_TO_BE_DEPRECATED is used as a version number in API that will be deprecated
- * in an upcoming release. This soft deprecation is an intermediate step before formal
- * deprecation to notify developers about the API before compiler warnings are generated.
- * You can find all places in your code that use soft deprecated API by redefining the
- * value of this macro to your current minimum deployment target, for example:
- * (macOS)
- * clang -D__API_TO_BE_DEPRECATED=10.12
- * (iOS)
- * clang -D__API_TO_BE_DEPRECATED=11.0
- */
-
-#ifndef __API_TO_BE_DEPRECATED
-#define __API_TO_BE_DEPRECATED 100000
-#endif
-
-#ifndef __MAC_10_0
-#define __MAC_10_0 1000
-#define __MAC_10_1 1010
-#define __MAC_10_2 1020
-#define __MAC_10_3 1030
-#define __MAC_10_4 1040
-#define __MAC_10_5 1050
-#define __MAC_10_6 1060
-#define __MAC_10_7 1070
-#define __MAC_10_8 1080
-#define __MAC_10_9 1090
-#define __MAC_10_10 101000
-#define __MAC_10_10_2 101002
-#define __MAC_10_10_3 101003
-#define __MAC_10_11 101100
-#define __MAC_10_11_2 101102
-#define __MAC_10_11_3 101103
-#define __MAC_10_11_4 101104
-#define __MAC_10_12 101200
-#define __MAC_10_12_1 101201
-#define __MAC_10_12_2 101202
-#define __MAC_10_12_4 101204
-#define __MAC_10_13 101300
-#define __MAC_10_13_1 101301
-#define __MAC_10_13_2 101302
-#define __MAC_10_13_4 101304
-#define __MAC_10_14 101400
-#define __MAC_10_14_1 101401
-#define __MAC_10_14_4 101404
-#define __MAC_10_15 101500
-#define __MAC_10_15_1 101501
-#define __MAC_10_15_4 101504
-/* __MAC_NA is not defined to a value but is uses as a token by macros to indicate that the API is unavailable */
-
-#define __IPHONE_2_0 20000
-#define __IPHONE_2_1 20100
-#define __IPHONE_2_2 20200
-#define __IPHONE_3_0 30000
-#define __IPHONE_3_1 30100
-#define __IPHONE_3_2 30200
-#define __IPHONE_4_0 40000
-#define __IPHONE_4_1 40100
-#define __IPHONE_4_2 40200
-#define __IPHONE_4_3 40300
-#define __IPHONE_5_0 50000
-#define __IPHONE_5_1 50100
-#define __IPHONE_6_0 60000
-#define __IPHONE_6_1 60100
-#define __IPHONE_7_0 70000
-#define __IPHONE_7_1 70100
-#define __IPHONE_8_0 80000
-#define __IPHONE_8_1 80100
-#define __IPHONE_8_2 80200
-#define __IPHONE_8_3 80300
-#define __IPHONE_8_4 80400
-#define __IPHONE_9_0 90000
-#define __IPHONE_9_1 90100
-#define __IPHONE_9_2 90200
-#define __IPHONE_9_3 90300
-#define __IPHONE_10_0 100000
-#define __IPHONE_10_1 100100
-#define __IPHONE_10_2 100200
-#define __IPHONE_10_3 100300
-#define __IPHONE_11_0 110000
-#define __IPHONE_11_1 110100
-#define __IPHONE_11_2 110200
-#define __IPHONE_11_3 110300
-#define __IPHONE_11_4 110400
-#define __IPHONE_12_0 120000
-#define __IPHONE_12_1 120100
-#define __IPHONE_12_2 120200
-#define __IPHONE_12_3 120300
-#define __IPHONE_13_0 130000
-#define __IPHONE_13_1 130100
-#define __IPHONE_13_2 130200
-#define __IPHONE_13_3 130300
-#define __IPHONE_13_4 130400
-#define __IPHONE_13_5 130500
-#define __IPHONE_13_6 130600
-/* __IPHONE_NA is not defined to a value but is uses as a token by macros to indicate that the API is unavailable */
-
-#define __TVOS_9_0 90000
-#define __TVOS_9_1 90100
-#define __TVOS_9_2 90200
-#define __TVOS_10_0 100000
-#define __TVOS_10_0_1 100001
-#define __TVOS_10_1 100100
-#define __TVOS_10_2 100200
-#define __TVOS_11_0 110000
-#define __TVOS_11_1 110100
-#define __TVOS_11_2 110200
-#define __TVOS_11_3 110300
-#define __TVOS_11_4 110400
-#define __TVOS_12_0 120000
-#define __TVOS_12_1 120100
-#define __TVOS_12_2 120200
-#define __TVOS_12_3 120300
-#define __TVOS_13_0 130000
-#define __TVOS_13_2 130200
-#define __TVOS_13_3 130300
-#define __TVOS_13_4 130400
-
-#define __WATCHOS_1_0 10000
-#define __WATCHOS_2_0 20000
-#define __WATCHOS_2_1 20100
-#define __WATCHOS_2_2 20200
-#define __WATCHOS_3_0 30000
-#define __WATCHOS_3_1 30100
-#define __WATCHOS_3_1_1 30101
-#define __WATCHOS_3_2 30200
-#define __WATCHOS_4_0 40000
-#define __WATCHOS_4_1 40100
-#define __WATCHOS_4_2 40200
-#define __WATCHOS_4_3 40300
-#define __WATCHOS_5_0 50000
-#define __WATCHOS_5_1 50100
-#define __WATCHOS_5_2 50200
-#define __WATCHOS_6_0 60000
-#define __WATCHOS_6_1 60100
-#define __WATCHOS_6_2 60200
-
-#define __DRIVERKIT_19_0 190000
-#endif /* __MAC_10_0 */
-
-#include
-
-#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
- #define __OSX_AVAILABLE_STARTING(_osx, _ios) __AVAILABILITY_INTERNAL##_ios
- #define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep) \
- __AVAILABILITY_INTERNAL##_iosIntro##_DEP##_iosDep
- #define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg) \
- __AVAILABILITY_INTERNAL##_iosIntro##_DEP##_iosDep##_MSG(_msg)
-
-#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
-
- #if defined(__has_builtin)
- #if __has_builtin(__is_target_arch)
- #if __has_builtin(__is_target_vendor)
- #if __has_builtin(__is_target_os)
- #if __has_builtin(__is_target_environment)
- #if __has_builtin(__is_target_variant_os)
- #if __has_builtin(__is_target_variant_environment)
- #if (__is_target_arch(x86_64) && __is_target_vendor(apple) && ((__is_target_os(ios) && __is_target_environment(macabi)) || (__is_target_variant_os(ios) && __is_target_variant_environment(macabi))))
- #define __OSX_AVAILABLE_STARTING(_osx, _ios) __AVAILABILITY_INTERNAL##_osx __AVAILABILITY_INTERNAL##_ios
- #define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep) \
- __AVAILABILITY_INTERNAL##_osxIntro##_DEP##_osxDep __AVAILABILITY_INTERNAL##_iosIntro##_DEP##_iosDep
- #define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg) \
- __AVAILABILITY_INTERNAL##_osxIntro##_DEP##_osxDep##_MSG(_msg) __AVAILABILITY_INTERNAL##_iosIntro##_DEP##_iosDep##_MSG(_msg)
- #endif /* # if __is_target_arch... */
- #endif /* #if __has_builtin(__is_target_variant_environment) */
- #endif /* #if __has_builtin(__is_target_variant_os) */
- #endif /* #if __has_builtin(__is_target_environment) */
- #endif /* #if __has_builtin(__is_target_os) */
- #endif /* #if __has_builtin(__is_target_vendor) */
- #endif /* #if __has_builtin(__is_target_arch) */
- #endif /* #if defined(__has_builtin) */
-
- #ifndef __OSX_AVAILABLE_STARTING
- #if defined(__has_attribute) && defined(__has_feature)
- #if __has_attribute(availability)
- #define __OSX_AVAILABLE_STARTING(_osx, _ios) __AVAILABILITY_INTERNAL##_osx
- #define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep) \
- __AVAILABILITY_INTERNAL##_osxIntro##_DEP##_osxDep
- #define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg) \
- __AVAILABILITY_INTERNAL##_osxIntro##_DEP##_osxDep##_MSG(_msg)
- #else
- #define __OSX_AVAILABLE_STARTING(_osx, _ios)
- #define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep)
- #define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg)
- #endif
- #else
- #define __OSX_AVAILABLE_STARTING(_osx, _ios)
- #define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep)
- #define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg)
- #endif
-#endif /* __OSX_AVAILABLE_STARTING */
-
-#else
- #define __OSX_AVAILABLE_STARTING(_osx, _ios)
- #define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep)
- #define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg)
-#endif
-
-
-#if defined(__has_feature)
- #if __has_feature(attribute_availability_with_message)
- #define __OS_AVAILABILITY(_target, _availability) __attribute__((availability(_target,_availability)))
- #define __OS_AVAILABILITY_MSG(_target, _availability, _msg) __attribute__((availability(_target,_availability,message=_msg)))
- #elif __has_feature(attribute_availability)
- #define __OS_AVAILABILITY(_target, _availability) __attribute__((availability(_target,_availability)))
- #define __OS_AVAILABILITY_MSG(_target, _availability, _msg) __attribute__((availability(_target,_availability)))
- #else
- #define __OS_AVAILABILITY(_target, _availability)
- #define __OS_AVAILABILITY_MSG(_target, _availability, _msg)
- #endif
-#else
- #define __OS_AVAILABILITY(_target, _availability)
- #define __OS_AVAILABILITY_MSG(_target, _availability, _msg)
-#endif
-
-
-/* for use to document app extension usage */
-#if defined(__has_feature)
- #if __has_feature(attribute_availability_app_extension)
- #define __OSX_EXTENSION_UNAVAILABLE(_msg) __OS_AVAILABILITY_MSG(macosx_app_extension,unavailable,_msg)
- #define __IOS_EXTENSION_UNAVAILABLE(_msg) __OS_AVAILABILITY_MSG(ios_app_extension,unavailable,_msg)
- #else
- #define __OSX_EXTENSION_UNAVAILABLE(_msg)
- #define __IOS_EXTENSION_UNAVAILABLE(_msg)
- #endif
-#else
- #define __OSX_EXTENSION_UNAVAILABLE(_msg)
- #define __IOS_EXTENSION_UNAVAILABLE(_msg)
-#endif
-
-#define __OS_EXTENSION_UNAVAILABLE(_msg) __OSX_EXTENSION_UNAVAILABLE(_msg) __IOS_EXTENSION_UNAVAILABLE(_msg)
-
-
-
-/* for use marking APIs available info for Mac OSX */
-#if defined(__has_attribute)
- #if __has_attribute(availability)
- #define __OSX_UNAVAILABLE __OS_AVAILABILITY(macosx,unavailable)
- #define __OSX_AVAILABLE(_vers) __OS_AVAILABILITY(macosx,introduced=_vers)
- #define __OSX_DEPRECATED(_start, _dep, _msg) __OSX_AVAILABLE(_start) __OS_AVAILABILITY_MSG(macosx,deprecated=_dep,_msg)
- #endif
-#endif
-
-#ifndef __OSX_UNAVAILABLE
- #define __OSX_UNAVAILABLE
-#endif
-
-#ifndef __OSX_AVAILABLE
- #define __OSX_AVAILABLE(_vers)
-#endif
-
-#ifndef __OSX_DEPRECATED
- #define __OSX_DEPRECATED(_start, _dep, _msg)
-#endif
-
-
-/* for use marking APIs available info for iOS */
-#if defined(__has_attribute)
- #if __has_attribute(availability)
- #define __IOS_UNAVAILABLE __OS_AVAILABILITY(ios,unavailable)
- #define __IOS_PROHIBITED __OS_AVAILABILITY(ios,unavailable)
- #define __IOS_AVAILABLE(_vers) __OS_AVAILABILITY(ios,introduced=_vers)
- #define __IOS_DEPRECATED(_start, _dep, _msg) __IOS_AVAILABLE(_start) __OS_AVAILABILITY_MSG(ios,deprecated=_dep,_msg)
- #endif
-#endif
-
-#ifndef __IOS_UNAVAILABLE
- #define __IOS_UNAVAILABLE
-#endif
-
-#ifndef __IOS_PROHIBITED
- #define __IOS_PROHIBITED
-#endif
-
-#ifndef __IOS_AVAILABLE
- #define __IOS_AVAILABLE(_vers)
-#endif
-
-#ifndef __IOS_DEPRECATED
- #define __IOS_DEPRECATED(_start, _dep, _msg)
-#endif
-
-
-/* for use marking APIs available info for tvOS */
-#if defined(__has_feature)
- #if __has_feature(attribute_availability_tvos)
- #define __TVOS_UNAVAILABLE __OS_AVAILABILITY(tvos,unavailable)
- #define __TVOS_PROHIBITED __OS_AVAILABILITY(tvos,unavailable)
- #define __TVOS_AVAILABLE(_vers) __OS_AVAILABILITY(tvos,introduced=_vers)
- #define __TVOS_DEPRECATED(_start, _dep, _msg) __TVOS_AVAILABLE(_start) __OS_AVAILABILITY_MSG(tvos,deprecated=_dep,_msg)
- #endif
-#endif
-
-#ifndef __TVOS_UNAVAILABLE
- #define __TVOS_UNAVAILABLE
-#endif
-
-#ifndef __TVOS_PROHIBITED
- #define __TVOS_PROHIBITED
-#endif
-
-#ifndef __TVOS_AVAILABLE
- #define __TVOS_AVAILABLE(_vers)
-#endif
-
-#ifndef __TVOS_DEPRECATED
- #define __TVOS_DEPRECATED(_start, _dep, _msg)
-#endif
-
-
-/* for use marking APIs available info for Watch OS */
-#if defined(__has_feature)
- #if __has_feature(attribute_availability_watchos)
- #define __WATCHOS_UNAVAILABLE __OS_AVAILABILITY(watchos,unavailable)
- #define __WATCHOS_PROHIBITED __OS_AVAILABILITY(watchos,unavailable)
- #define __WATCHOS_AVAILABLE(_vers) __OS_AVAILABILITY(watchos,introduced=_vers)
- #define __WATCHOS_DEPRECATED(_start, _dep, _msg) __WATCHOS_AVAILABLE(_start) __OS_AVAILABILITY_MSG(watchos,deprecated=_dep,_msg)
- #endif
-#endif
-
-#ifndef __WATCHOS_UNAVAILABLE
- #define __WATCHOS_UNAVAILABLE
-#endif
-
-#ifndef __WATCHOS_PROHIBITED
- #define __WATCHOS_PROHIBITED
-#endif
-
-#ifndef __WATCHOS_AVAILABLE
- #define __WATCHOS_AVAILABLE(_vers)
-#endif
-
-#ifndef __WATCHOS_DEPRECATED
- #define __WATCHOS_DEPRECATED(_start, _dep, _msg)
-#endif
-
-
-/* for use marking APIs unavailable for swift */
-#if defined(__has_feature)
- #if __has_feature(attribute_availability_swift)
- #define __SWIFT_UNAVAILABLE __OS_AVAILABILITY(swift,unavailable)
- #define __SWIFT_UNAVAILABLE_MSG(_msg) __OS_AVAILABILITY_MSG(swift,unavailable,_msg)
- #endif
-#endif
-
-#ifndef __SWIFT_UNAVAILABLE
- #define __SWIFT_UNAVAILABLE
-#endif
-
-#ifndef __SWIFT_UNAVAILABLE_MSG
- #define __SWIFT_UNAVAILABLE_MSG(_msg)
-#endif
-
-/*
- Macros for defining which versions/platform a given symbol can be used.
-
- @see http://clang.llvm.org/docs/AttributeReference.html#availability
-
- * Note that these macros are only compatible with clang compilers that
- * support the following target selection options:
- *
- * -mmacosx-version-min
- * -miphoneos-version-min
- * -mwatchos-version-min
- * -mtvos-version-min
- */
-
-#if defined(__has_feature) && defined(__has_attribute)
- #if __has_attribute(availability)
-
- /*
- * API Introductions
- *
- * Use to specify the release that a particular API became available.
- *
- * Platform names:
- * macos, ios, tvos, watchos
- *
- * Examples:
- * __API_AVAILABLE(macos(10.10))
- * __API_AVAILABLE(macos(10.9), ios(10.0))
- * __API_AVAILABLE(macos(10.4), ios(8.0), watchos(2.0), tvos(10.0))
- * __API_AVAILABLE(driverkit(19.0))
- */
- #define __API_AVAILABLE(...) __API_AVAILABLE_GET_MACRO(__VA_ARGS__,__API_AVAILABLE7, __API_AVAILABLE6, __API_AVAILABLE5, __API_AVAILABLE4, __API_AVAILABLE3, __API_AVAILABLE2, __API_AVAILABLE1, 0)(__VA_ARGS__)
-
- #define __API_AVAILABLE_BEGIN(...) _Pragma("clang attribute push") __API_AVAILABLE_BEGIN_GET_MACRO(__VA_ARGS__,__API_AVAILABLE_BEGIN7, __API_AVAILABLE_BEGIN6, __API_AVAILABLE_BEGIN5, __API_AVAILABLE_BEGIN4, __API_AVAILABLE_BEGIN3, __API_AVAILABLE_BEGIN2, __API_AVAILABLE_BEGIN1, 0)(__VA_ARGS__)
- #define __API_AVAILABLE_END _Pragma("clang attribute pop")
-
- /*
- * API Deprecations
- *
- * Use to specify the release that a particular API became unavailable.
- *
- * Platform names:
- * macos, ios, tvos, watchos
- *
- * Examples:
- *
- * __API_DEPRECATED("No longer supported", macos(10.4, 10.8))
- * __API_DEPRECATED("No longer supported", macos(10.4, 10.8), ios(2.0, 3.0), watchos(2.0, 3.0), tvos(9.0, 10.0))
- *
- * __API_DEPRECATED_WITH_REPLACEMENT("-setName:", tvos(10.0, 10.4), ios(9.0, 10.0))
- * __API_DEPRECATED_WITH_REPLACEMENT("SomeClassName", macos(10.4, 10.6), watchos(2.0, 3.0))
- */
- #define __API_DEPRECATED(...) __API_DEPRECATED_MSG_GET_MACRO(__VA_ARGS__,__API_DEPRECATED_MSG8,__API_DEPRECATED_MSG7,__API_DEPRECATED_MSG6,__API_DEPRECATED_MSG5,__API_DEPRECATED_MSG4,__API_DEPRECATED_MSG3,__API_DEPRECATED_MSG2,__API_DEPRECATED_MSG1, 0)(__VA_ARGS__)
- #define __API_DEPRECATED_WITH_REPLACEMENT(...) __API_DEPRECATED_REP_GET_MACRO(__VA_ARGS__,__API_DEPRECATED_REP8,__API_DEPRECATED_REP7,__API_DEPRECATED_REP6,__API_DEPRECATED_REP5,__API_DEPRECATED_REP4,__API_DEPRECATED_REP3,__API_DEPRECATED_REP2,__API_DEPRECATED_REP1, 0)(__VA_ARGS__)
-
- #define __API_DEPRECATED_BEGIN(...) _Pragma("clang attribute push") __API_DEPRECATED_BEGIN_MSG_GET_MACRO(__VA_ARGS__,__API_DEPRECATED_BEGIN_MSG8,__API_DEPRECATED_BEGIN_MSG7, __API_DEPRECATED_BEGIN_MSG6, __API_DEPRECATED_BEGIN_MSG5, __API_DEPRECATED_BEGIN_MSG4, __API_DEPRECATED_BEGIN_MSG3, __API_DEPRECATED_BEGIN_MSG2, __API_DEPRECATED_BEGIN_MSG1, 0)(__VA_ARGS__)
- #define __API_DEPRECATED_END _Pragma("clang attribute pop")
-
- #define __API_DEPRECATED_WITH_REPLACEMENT_BEGIN(...) _Pragma("clang attribute push") __API_DEPRECATED_BEGIN_REP_GET_MACRO(__VA_ARGS__,__API_DEPRECATED_BEGIN_REP8,__API_DEPRECATED_BEGIN_REP7, __API_DEPRECATED_BEGIN_REP6, __API_DEPRECATED_BEGIN_REP5, __API_DEPRECATED_BEGIN_REP4, __API_DEPRECATED_BEGIN_REP3, __API_DEPRECATED_BEGIN_REP2, __API_DEPRECATED_BEGIN_REP1, 0)(__VA_ARGS__)
- #define __API_DEPRECATED_WITH_REPLACEMENT_END _Pragma("clang attribute pop")
-
- /*
- * API Unavailability
- * Use to specify that an API is unavailable for a particular platform.
- *
- * Example:
- * __API_UNAVAILABLE(macos)
- * __API_UNAVAILABLE(watchos, tvos)
- */
- #define __API_UNAVAILABLE(...) __API_UNAVAILABLE_GET_MACRO(__VA_ARGS__,__API_UNAVAILABLE7,__API_UNAVAILABLE6,__API_UNAVAILABLE5,__API_UNAVAILABLE4,__API_UNAVAILABLE3,__API_UNAVAILABLE2,__API_UNAVAILABLE1, 0)(__VA_ARGS__)
-
- #define __API_UNAVAILABLE_BEGIN(...) _Pragma("clang attribute push") __API_UNAVAILABLE_BEGIN_GET_MACRO(__VA_ARGS__,__API_UNAVAILABLE_BEGIN7,__API_UNAVAILABLE_BEGIN6, __API_UNAVAILABLE_BEGIN5, __API_UNAVAILABLE_BEGIN4, __API_UNAVAILABLE_BEGIN3, __API_UNAVAILABLE_BEGIN2, __API_UNAVAILABLE_BEGIN1, 0)(__VA_ARGS__)
- #define __API_UNAVAILABLE_END _Pragma("clang attribute pop")
- #else
-
- /*
- * Evaluate to nothing for compilers that don't support availability.
- */
-
- #define __API_AVAILABLE(...)
- #define __API_AVAILABLE_BEGIN(...)
- #define __API_AVAILABLE_END
- #define __API_DEPRECATED(...)
- #define __API_DEPRECATED_WITH_REPLACEMENT(...)
- #define __API_DEPRECATED_BEGIN(...)
- #define __API_DEPRECATED_END
- #define __API_DEPRECATED_WITH_REPLACEMENT_BEGIN(...)
- #define __API_DEPRECATED_WITH_REPLACEMENT_END
- #define __API_UNAVAILABLE(...)
- #define __API_UNAVAILABLE_BEGIN(...)
- #define __API_UNAVAILABLE_END
- #endif /* __has_attribute(availability) */
-#else
-
- /*
- * Evaluate to nothing for compilers that don't support clang language extensions.
- */
-
- #define __API_AVAILABLE(...)
- #define __API_AVAILABLE_BEGIN(...)
- #define __API_AVAILABLE_END
- #define __API_DEPRECATED(...)
- #define __API_DEPRECATED_WITH_REPLACEMENT(...)
- #define __API_DEPRECATED_BEGIN(...)
- #define __API_DEPRECATED_END
- #define __API_DEPRECATED_WITH_REPLACEMENT_BEGIN(...)
- #define __API_DEPRECATED_WITH_REPLACEMENT_END
- #define __API_UNAVAILABLE(...)
- #define __API_UNAVAILABLE_BEGIN(...)
- #define __API_UNAVAILABLE_END
-#endif /* #if defined(__has_feature) && defined(__has_attribute) */
-
-#if __has_include()
- #include
-#endif
-
-/*
- * If SPI decorations have not been defined elsewhere, disable them.
- */
-
-#ifndef __SPI_AVAILABLE
- #define __SPI_AVAILABLE(...)
-#endif
-
-#ifndef __SPI_DEPRECATED
- #define __SPI_DEPRECATED(...)
-#endif
-
-#ifndef __SPI_DEPRECATED_WITH_REPLACEMENT
- #define __SPI_DEPRECATED_WITH_REPLACEMENT(...)
-#endif
-
-#endif /* __AVAILABILITY__ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/AvailabilityInternal.h b/lib/libc/include/x86_64-macos-gnu/AvailabilityInternal.h
index 11e6d1ed17..6a35a16782 100644
--- a/lib/libc/include/x86_64-macos-gnu/AvailabilityInternal.h
+++ b/lib/libc/include/x86_64-macos-gnu/AvailabilityInternal.h
@@ -45,6 +45,9 @@
#ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
/* compiler sets __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ when -miphoneos-version-min is used */
#define __IPHONE_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
+ /* set to 1 when RC_FALLBACK_PLATFORM=iphoneos */
+ #elif 0
+ #define __IPHONE_OS_VERSION_MIN_REQUIRED __IPHONE_14_0
#endif
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED */
@@ -52,7 +55,7 @@
#ifdef __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__
/* compiler sets __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ when -mtvos-version-min is used */
#define __TV_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__
- #define __TV_OS_VERSION_MAX_ALLOWED __TVOS_13_0
+ #define __TV_OS_VERSION_MAX_ALLOWED __TVOS_14_5
/* for compatibility with existing code. New code should use platform specific checks */
#define __IPHONE_OS_VERSION_MIN_REQUIRED 90000
#endif
@@ -62,7 +65,7 @@
#ifdef __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__
/* compiler sets __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ when -mwatchos-version-min is used */
#define __WATCH_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__
- #define __WATCH_OS_VERSION_MAX_ALLOWED 60000
+ #define __WATCH_OS_VERSION_MAX_ALLOWED __WATCHOS_7_4
/* for compatibility with existing code. New code should use platform specific checks */
#define __IPHONE_OS_VERSION_MIN_REQUIRED 90000
#endif
@@ -72,7 +75,7 @@
#ifdef __ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__
#define __BRIDGE_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__
- #define __BRIDGE_OS_VERSION_MAX_ALLOWED 20000
+ #define __BRIDGE_OS_VERSION_MAX_ALLOWED 50300
/* for compatibility with existing code. New code should use platform specific checks */
#define __IPHONE_OS_VERSION_MIN_REQUIRED 110000
#endif
@@ -87,14 +90,14 @@
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
/* make sure a default max version is set */
#ifndef __MAC_OS_X_VERSION_MAX_ALLOWED
- #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_10_15
+ #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_11_3
#endif
#endif /* __MAC_OS_X_VERSION_MIN_REQUIRED */
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
/* make sure a default max version is set */
#ifndef __IPHONE_OS_VERSION_MAX_ALLOWED
- #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_13_0
+ #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_14_5
#endif
/* make sure a valid min is set */
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_0
@@ -2887,7 +2890,7 @@
#if __has_builtin(__is_target_environment)
#if __has_builtin(__is_target_variant_os)
#if __has_builtin(__is_target_variant_environment)
- #if (__is_target_arch(x86_64) && __is_target_vendor(apple) && __is_target_os(ios) && __is_target_environment(macabi))
+ #if ((__is_target_arch(x86_64) || __is_target_arch(arm64) || __is_target_arch(arm64e)) && __is_target_vendor(apple) && __is_target_os(ios) && __is_target_environment(macabi))
#define __AVAILABILITY_INTERNAL__IPHONE_COMPAT_VERSION __attribute__((availability(ios,introduced=4.0)))
#define __AVAILABILITY_INTERNAL__IPHONE_COMPAT_VERSION_DEP__IPHONE_COMPAT_VERSION __attribute__((availability(ios,unavailable)))
#define __AVAILABILITY_INTERNAL__IPHONE_COMPAT_VERSION_DEP__IPHONE_COMPAT_VERSION_MSG(_msg) __attribute__((availability(ios,unavailable)))
@@ -4643,7 +4646,7 @@
/*
* Swift compiler version
- * Allows for project-agnostic “epochs” for frameworks imported into Swift via the Clang importer, like #if _compiler_version for Swift
+ * Allows for project-agnostic "epochs" for frameworks imported into Swift via the Clang importer, like #if _compiler_version for Swift
* Example:
*
* #if __swift_compiler_version_at_least(800, 2, 20)
diff --git a/lib/libc/include/x86_64-macos-gnu/AvailabilityMacros.h b/lib/libc/include/x86_64-macos-gnu/AvailabilityMacros.h
index 9cc7100ffe..74537c5bd8 100644
--- a/lib/libc/include/x86_64-macos-gnu/AvailabilityMacros.h
+++ b/lib/libc/include/x86_64-macos-gnu/AvailabilityMacros.h
@@ -117,9 +117,11 @@
#define MAC_OS_X_VERSION_10_14_1 101401
#define MAC_OS_X_VERSION_10_14_4 101404
#define MAC_OS_X_VERSION_10_15 101500
-#define MAC_OS_X_VERSION_10_15_1 101501
+#define MAC_OS_VERSION_11_0 110000
+#define MAC_OS_VERSION_11_1 110100
+#define MAC_OS_VERSION_11_3 110300
-/*
+/*
* If min OS not specified, assume 10.4 for intel
* Note: compiler driver may set _ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED_ based on MACOSX_DEPLOYMENT_TARGET environment variable
*/
@@ -144,10 +146,10 @@
* if max OS not specified, assume larger of (10.15, min)
*/
#ifndef MAC_OS_X_VERSION_MAX_ALLOWED
- #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_15
+ #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_VERSION_11_3
#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_MIN_REQUIRED
#else
- #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_15
+ #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_VERSION_11_3
#endif
#endif
diff --git a/lib/libc/include/x86_64-macos-gnu/AvailabilityVersions.h b/lib/libc/include/x86_64-macos-gnu/AvailabilityVersions.h
new file mode 100644
index 0000000000..591e541d7f
--- /dev/null
+++ b/lib/libc/include/x86_64-macos-gnu/AvailabilityVersions.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2019 by Apple Inc.. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __AVAILABILITY_VERSIONS__
+#define __AVAILABILITY_VERSIONS__
+
+#define __MAC_10_0 1000
+#define __MAC_10_1 1010
+#define __MAC_10_2 1020
+#define __MAC_10_3 1030
+#define __MAC_10_4 1040
+#define __MAC_10_5 1050
+#define __MAC_10_6 1060
+#define __MAC_10_7 1070
+#define __MAC_10_8 1080
+#define __MAC_10_9 1090
+#define __MAC_10_10 101000
+#define __MAC_10_10_2 101002
+#define __MAC_10_10_3 101003
+#define __MAC_10_11 101100
+#define __MAC_10_11_2 101102
+#define __MAC_10_11_3 101103
+#define __MAC_10_11_4 101104
+#define __MAC_10_12 101200
+#define __MAC_10_12_1 101201
+#define __MAC_10_12_2 101202
+#define __MAC_10_12_4 101204
+#define __MAC_10_13 101300
+#define __MAC_10_13_1 101301
+#define __MAC_10_13_2 101302
+#define __MAC_10_13_4 101304
+#define __MAC_10_14 101400
+#define __MAC_10_14_1 101401
+#define __MAC_10_14_4 101404
+#define __MAC_10_14_6 101406
+#define __MAC_10_15 101500
+#define __MAC_10_15_1 101501
+#define __MAC_10_15_4 101504
+#define __MAC_10_16 101600
+#define __MAC_11_0 110000
+#define __MAC_11_1 110100
+#define __MAC_11_3 110300
+/* __MAC_NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */
+
+#define __IPHONE_2_0 20000
+#define __IPHONE_2_1 20100
+#define __IPHONE_2_2 20200
+#define __IPHONE_3_0 30000
+#define __IPHONE_3_1 30100
+#define __IPHONE_3_2 30200
+#define __IPHONE_4_0 40000
+#define __IPHONE_4_1 40100
+#define __IPHONE_4_2 40200
+#define __IPHONE_4_3 40300
+#define __IPHONE_5_0 50000
+#define __IPHONE_5_1 50100
+#define __IPHONE_6_0 60000
+#define __IPHONE_6_1 60100
+#define __IPHONE_7_0 70000
+#define __IPHONE_7_1 70100
+#define __IPHONE_8_0 80000
+#define __IPHONE_8_1 80100
+#define __IPHONE_8_2 80200
+#define __IPHONE_8_3 80300
+#define __IPHONE_8_4 80400
+#define __IPHONE_9_0 90000
+#define __IPHONE_9_1 90100
+#define __IPHONE_9_2 90200
+#define __IPHONE_9_3 90300
+#define __IPHONE_10_0 100000
+#define __IPHONE_10_1 100100
+#define __IPHONE_10_2 100200
+#define __IPHONE_10_3 100300
+#define __IPHONE_11_0 110000
+#define __IPHONE_11_1 110100
+#define __IPHONE_11_2 110200
+#define __IPHONE_11_3 110300
+#define __IPHONE_11_4 110400
+#define __IPHONE_12_0 120000
+#define __IPHONE_12_1 120100
+#define __IPHONE_12_2 120200
+#define __IPHONE_12_3 120300
+#define __IPHONE_12_4 120400
+#define __IPHONE_13_0 130000
+#define __IPHONE_13_1 130100
+#define __IPHONE_13_2 130200
+#define __IPHONE_13_3 130300
+#define __IPHONE_13_4 130400
+#define __IPHONE_13_5 130500
+#define __IPHONE_13_6 130600
+#define __IPHONE_13_7 130700
+#define __IPHONE_14_0 140000
+#define __IPHONE_14_1 140100
+#define __IPHONE_14_2 140200
+#define __IPHONE_14_3 140300
+#define __IPHONE_14_5 140500
+/* __IPHONE_NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */
+
+#define __TVOS_9_0 90000
+#define __TVOS_9_1 90100
+#define __TVOS_9_2 90200
+#define __TVOS_10_0 100000
+#define __TVOS_10_0_1 100001
+#define __TVOS_10_1 100100
+#define __TVOS_10_2 100200
+#define __TVOS_11_0 110000
+#define __TVOS_11_1 110100
+#define __TVOS_11_2 110200
+#define __TVOS_11_3 110300
+#define __TVOS_11_4 110400
+#define __TVOS_12_0 120000
+#define __TVOS_12_1 120100
+#define __TVOS_12_2 120200
+#define __TVOS_12_3 120300
+#define __TVOS_12_4 120400
+#define __TVOS_13_0 130000
+#define __TVOS_13_2 130200
+#define __TVOS_13_3 130300
+#define __TVOS_13_4 130400
+#define __TVOS_14_0 140000
+#define __TVOS_14_1 140100
+#define __TVOS_14_2 140200
+#define __TVOS_14_3 140300
+#define __TVOS_14_5 140500
+
+#define __WATCHOS_1_0 10000
+#define __WATCHOS_2_0 20000
+#define __WATCHOS_2_1 20100
+#define __WATCHOS_2_2 20200
+#define __WATCHOS_3_0 30000
+#define __WATCHOS_3_1 30100
+#define __WATCHOS_3_1_1 30101
+#define __WATCHOS_3_2 30200
+#define __WATCHOS_4_0 40000
+#define __WATCHOS_4_1 40100
+#define __WATCHOS_4_2 40200
+#define __WATCHOS_4_3 40300
+#define __WATCHOS_5_0 50000
+#define __WATCHOS_5_1 50100
+#define __WATCHOS_5_2 50200
+#define __WATCHOS_5_3 50300
+#define __WATCHOS_6_0 60000
+#define __WATCHOS_6_1 60100
+#define __WATCHOS_6_2 60200
+#define __WATCHOS_7_0 70000
+#define __WATCHOS_7_1 70100
+#define __WATCHOS_7_2 70200
+#define __WATCHOS_7_3 70300
+#define __WATCHOS_7_4 70400
+
+/*
+ * Set up standard Mac OS X versions
+ */
+
+#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
+
+#define MAC_OS_X_VERSION_10_0 1000
+#define MAC_OS_X_VERSION_10_1 1010
+#define MAC_OS_X_VERSION_10_2 1020
+#define MAC_OS_X_VERSION_10_3 1030
+#define MAC_OS_X_VERSION_10_4 1040
+#define MAC_OS_X_VERSION_10_5 1050
+#define MAC_OS_X_VERSION_10_6 1060
+#define MAC_OS_X_VERSION_10_7 1070
+#define MAC_OS_X_VERSION_10_8 1080
+#define MAC_OS_X_VERSION_10_9 1090
+#define MAC_OS_X_VERSION_10_10 101000
+#define MAC_OS_X_VERSION_10_10_2 101002
+#define MAC_OS_X_VERSION_10_10_3 101003
+#define MAC_OS_X_VERSION_10_11 101100
+#define MAC_OS_X_VERSION_10_11_2 101102
+#define MAC_OS_X_VERSION_10_11_3 101103
+#define MAC_OS_X_VERSION_10_11_4 101104
+#define MAC_OS_X_VERSION_10_12 101200
+#define MAC_OS_X_VERSION_10_12_1 101201
+#define MAC_OS_X_VERSION_10_12_2 101202
+#define MAC_OS_X_VERSION_10_12_4 101204
+#define MAC_OS_X_VERSION_10_13 101300
+#define MAC_OS_X_VERSION_10_13_1 101301
+#define MAC_OS_X_VERSION_10_13_2 101302
+#define MAC_OS_X_VERSION_10_13_4 101304
+#define MAC_OS_X_VERSION_10_14 101400
+#define MAC_OS_X_VERSION_10_14_1 101401
+#define MAC_OS_X_VERSION_10_14_4 101404
+#define MAC_OS_X_VERSION_10_14_6 101406
+#define MAC_OS_X_VERSION_10_15 101500
+#define MAC_OS_X_VERSION_10_15_1 101501
+#define MAC_OS_X_VERSION_10_16 101600
+#define MAC_OS_VERSION_11_0 110000
+
+#endif /* #if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) */
+
+#define __DRIVERKIT_19_0 190000
+#define __DRIVERKIT_20_0 200000
+
+#endif /* __AVAILABILITY_VERSIONS__ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/TargetConditionals.h b/lib/libc/include/x86_64-macos-gnu/TargetConditionals.h
deleted file mode 100644
index 896956f33d..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/TargetConditionals.h
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright (c) 2000-2014 by Apple Inc.. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/*
- File: TargetConditionals.h
-
- Contains: Autoconfiguration of TARGET_ conditionals for Mac OS X and iPhone
-
- Note: TargetConditionals.h in 3.4 Universal Interfaces works
- with all compilers. This header only recognizes compilers
- known to run on Mac OS X.
-
-*/
-
-#ifndef __TARGETCONDITIONALS__
-#define __TARGETCONDITIONALS__
-
-/****************************************************************************************************
-
- TARGET_CPU_*
- These conditionals specify which microprocessor instruction set is being
- generated. At most one of these is true, the rest are false.
-
- TARGET_CPU_PPC - Compiler is generating PowerPC instructions for 32-bit mode
- TARGET_CPU_PPC64 - Compiler is generating PowerPC instructions for 64-bit mode
- TARGET_CPU_68K - Compiler is generating 680x0 instructions
- TARGET_CPU_X86 - Compiler is generating x86 instructions for 32-bit mode
- TARGET_CPU_X86_64 - Compiler is generating x86 instructions for 64-bit mode
- TARGET_CPU_ARM - Compiler is generating ARM instructions for 32-bit mode
- TARGET_CPU_ARM64 - Compiler is generating ARM instructions for 64-bit mode
- TARGET_CPU_MIPS - Compiler is generating MIPS instructions
- TARGET_CPU_SPARC - Compiler is generating Sparc instructions
- TARGET_CPU_ALPHA - Compiler is generating Dec Alpha instructions
-
-
- TARGET_OS_*
- These conditionals specify in which Operating System the generated code will
- run. Indention is used to show which conditionals are evolutionary subclasses.
-
- The MAC/WIN32/UNIX conditionals are mutually exclusive.
- The IOS/TV/WATCH conditionals are mutually exclusive.
-
-
- TARGET_OS_WIN32 - Generated code will run under 32-bit Windows
- TARGET_OS_UNIX - Generated code will run under some Unix (not OSX)
- TARGET_OS_MAC - Generated code will run under Mac OS X variant
- TARGET_OS_OSX - Generated code will run under OS X devices
- TARGET_OS_IPHONE - Generated code for firmware, devices, or simulator
- TARGET_OS_IOS - Generated code will run under iOS
- TARGET_OS_TV - Generated code will run under Apple TV OS
- TARGET_OS_WATCH - Generated code will run under Apple Watch OS
- TARGET_OS_BRIDGE - Generated code will run under Bridge devices
- TARGET_OS_MACCATALYST - Generated code will run under macOS
- TARGET_OS_SIMULATOR - Generated code will run under a simulator
-
- TARGET_OS_EMBEDDED - DEPRECATED: Use TARGET_OS_IPHONE and/or TARGET_OS_SIMULATOR instead
- TARGET_IPHONE_SIMULATOR - DEPRECATED: Same as TARGET_OS_SIMULATOR
- TARGET_OS_NANO - DEPRECATED: Same as TARGET_OS_WATCH
-
- +----------------------------------------------------------------+
- | TARGET_OS_MAC |
- | +---+ +-----------------------------------------------------+ |
- | | | | TARGET_OS_IPHONE | |
- | |OSX| | +-----+ +----+ +-------+ +--------+ +-------------+ | |
- | | | | | IOS | | TV | | WATCH | | BRIDGE | | MACCATALYST | | |
- | | | | +-----+ +----+ +-------+ +--------+ +-------------+ | |
- | +---+ +-----------------------------------------------------+ |
- +----------------------------------------------------------------+
-
- TARGET_RT_*
- These conditionals specify in which runtime the generated code will
- run. This is needed when the OS and CPU support more than one runtime
- (e.g. Mac OS X supports CFM and mach-o).
-
- TARGET_RT_LITTLE_ENDIAN - Generated code uses little endian format for integers
- TARGET_RT_BIG_ENDIAN - Generated code uses big endian format for integers
- TARGET_RT_64_BIT - Generated code uses 64-bit pointers
- TARGET_RT_MAC_CFM - TARGET_OS_MAC is true and CFM68K or PowerPC CFM (TVectors) are used
- TARGET_RT_MAC_MACHO - TARGET_OS_MAC is true and Mach-O/dlyd runtime is used
-
-
-****************************************************************************************************/
-
- /*
- * TARGET_OS conditionals can be enabled via clang preprocessor extensions:
- *
- * __is_target_arch
- * __is_target_vendor
- * __is_target_os
- * __is_target_environment
- *
- * “-target=x86_64-apple-ios12-macabi”
- * TARGET_OS_MAC=1
- * TARGET_OS_IPHONE=1
- * TARGET_OS_IOS=1
- * TARGET_OS_MACCATALYST=1
- *
- * “-target=x86_64-apple-ios12-simulator”
- * TARGET_OS_MAC=1
- * TARGET_OS_IPHONE=1
- * TARGET_OS_IOS=1
- * TARGET_OS_SIMULATOR=1
- *
- * DYNAMIC_TARGETS_ENABLED indicates that the core TARGET_OS macros were enabled via clang preprocessor extensions.
- * If this value is not set, the macro enablements will fall back to the static behavior.
- * It is disabled by default.
- */
-
-#if defined(__has_builtin)
- #if __has_builtin(__is_target_arch)
- #if __has_builtin(__is_target_vendor)
- #if __has_builtin(__is_target_os)
- #if __has_builtin(__is_target_environment)
-
- /* “-target=x86_64-apple-ios12-macabi” */
- #if __is_target_arch(x86_64) && __is_target_vendor(apple) && __is_target_os(ios) && __is_target_environment(macabi)
- #define TARGET_OS_OSX 0
- #define TARGET_OS_IPHONE 1
- #define TARGET_OS_IOS 1
- #define TARGET_OS_WATCH 0
-
- #define TARGET_OS_TV 0
- #define TARGET_OS_SIMULATOR 0
- #define TARGET_OS_EMBEDDED 0
- #define TARGET_OS_RTKIT 0
- #define TARGET_OS_MACCATALYST 1
- #define TARGET_OS_MACCATALYST 1
- #ifndef TARGET_OS_UIKITFORMAC
- #define TARGET_OS_UIKITFORMAC 1
- #endif
- #define TARGET_OS_DRIVERKIT 0
- #define DYNAMIC_TARGETS_ENABLED 1
- #endif
-
- /* “-target=x86_64-apple-ios12-simulator” */
- #if __is_target_arch(x86_64) && __is_target_vendor(apple) && __is_target_os(ios) && __is_target_environment(simulator)
- #define TARGET_OS_OSX 0
- #define TARGET_OS_IPHONE 1
- #define TARGET_OS_IOS 1
- #define TARGET_OS_WATCH 0
-
- #define TARGET_OS_TV 0
- #define TARGET_OS_SIMULATOR 1
- #define TARGET_OS_EMBEDDED 0
- #define TARGET_OS_RTKIT 0
- #define TARGET_OS_MACCATALYST 0
- #define TARGET_OS_MACCATALYST 0
- #ifndef TARGET_OS_UIKITFORMAC
- #define TARGET_OS_UIKITFORMAC 0
- #endif
- #define TARGET_OS_DRIVERKIT 0
- #define DYNAMIC_TARGETS_ENABLED 1
- #endif
-
- /* -target=x86_64-apple-driverkit19.0 */
- #if __is_target_arch(x86_64) && __is_target_vendor(apple) && __is_target_os(driverkit)
- #define TARGET_OS_OSX 0
- #define TARGET_OS_IPHONE 0
- #define TARGET_OS_IOS 0
- #define TARGET_OS_WATCH 0
-
- #define TARGET_OS_TV 0
- #define TARGET_OS_SIMULATOR 0
- #define TARGET_OS_EMBEDDED 0
- #define TARGET_OS_RTKIT 0
- #define TARGET_OS_MACCATALYST 0
- #define TARGET_OS_MACCATALYST 0
- #ifndef TARGET_OS_UIKITFORMAC
- #define TARGET_OS_UIKITFORMAC 0
- #endif
- #define TARGET_OS_DRIVERKIT 1
- #define DYNAMIC_TARGETS_ENABLED 1
- #endif
-
- #endif /* #if __has_builtin(__is_target_environment) */
- #endif /* #if __has_builtin(__is_target_os) */
- #endif /* #if __has_builtin(__is_target_vendor) */
- #endif /* #if __has_builtin(__is_target_arch) */
-#endif /* #if defined(__has_builtin) */
-
-
-#ifndef DYNAMIC_TARGETS_ENABLED
- #define DYNAMIC_TARGETS_ENABLED 0
-#endif /* DYNAMIC_TARGETS_ENABLED */
-
-/*
- * gcc based compiler used on Mac OS X
- */
-#if defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
- #define TARGET_OS_MAC 1
- #define TARGET_OS_WIN32 0
- #define TARGET_OS_UNIX 0
-
- #if !DYNAMIC_TARGETS_ENABLED
- #define TARGET_OS_OSX 1
- #define TARGET_OS_IPHONE 0
- #define TARGET_OS_IOS 0
- #define TARGET_OS_WATCH 0
-
- #define TARGET_OS_TV 0
- #define TARGET_OS_MACCATALYST 0
- #define TARGET_OS_MACCATALYST 0
- #ifndef TARGET_OS_UIKITFORMAC
- #define TARGET_OS_UIKITFORMAC 0
- #endif
- #define TARGET_OS_SIMULATOR 0
- #define TARGET_OS_EMBEDDED 0
- #define TARGET_OS_RTKIT 0
- #define TARGET_OS_DRIVERKIT 0
- #endif
-
- #define TARGET_IPHONE_SIMULATOR TARGET_OS_SIMULATOR /* deprecated */
- #define TARGET_OS_NANO TARGET_OS_WATCH /* deprecated */
- #define TARGET_ABI_USES_IOS_VALUES (TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST)
- #if defined(__ppc__)
- #define TARGET_CPU_PPC 1
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #define TARGET_RT_LITTLE_ENDIAN 0
- #define TARGET_RT_BIG_ENDIAN 1
- #define TARGET_RT_64_BIT 0
- #ifdef __MACOS_CLASSIC__
- #define TARGET_RT_MAC_CFM 1
- #define TARGET_RT_MAC_MACHO 0
- #else
- #define TARGET_RT_MAC_CFM 0
- #define TARGET_RT_MAC_MACHO 1
- #endif
- #elif defined(__ppc64__)
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 1
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #define TARGET_RT_LITTLE_ENDIAN 0
- #define TARGET_RT_BIG_ENDIAN 1
- #define TARGET_RT_64_BIT 1
- #define TARGET_RT_MAC_CFM 0
- #define TARGET_RT_MAC_MACHO 1
- #elif defined(__i386__)
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 1
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #define TARGET_RT_MAC_CFM 0
- #define TARGET_RT_MAC_MACHO 1
- #define TARGET_RT_LITTLE_ENDIAN 1
- #define TARGET_RT_BIG_ENDIAN 0
- #define TARGET_RT_64_BIT 0
- #elif defined(__x86_64__)
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_X86_64 1
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #define TARGET_RT_MAC_CFM 0
- #define TARGET_RT_MAC_MACHO 1
- #define TARGET_RT_LITTLE_ENDIAN 1
- #define TARGET_RT_BIG_ENDIAN 0
- #define TARGET_RT_64_BIT 1
- #elif defined(__arm__)
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_ARM 1
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #define TARGET_RT_MAC_CFM 0
- #define TARGET_RT_MAC_MACHO 1
- #define TARGET_RT_LITTLE_ENDIAN 1
- #define TARGET_RT_BIG_ENDIAN 0
- #define TARGET_RT_64_BIT 0
- #elif defined(__arm64__)
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 1
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #define TARGET_RT_MAC_CFM 0
- #define TARGET_RT_MAC_MACHO 1
- #define TARGET_RT_LITTLE_ENDIAN 1
- #define TARGET_RT_BIG_ENDIAN 0
- #if __LP64__
- #define TARGET_RT_64_BIT 1
- #else
- #define TARGET_RT_64_BIT 0
- #endif
- #else
- #error unrecognized GNU C compiler
- #endif
-
-
-
-/*
- * CodeWarrior compiler from Metrowerks/Motorola
- */
-#elif defined(__MWERKS__)
- #define TARGET_OS_MAC 1
- #define TARGET_OS_WIN32 0
- #define TARGET_OS_UNIX 0
- #define TARGET_OS_EMBEDDED 0
- #if defined(__POWERPC__)
- #define TARGET_CPU_PPC 1
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #define TARGET_RT_LITTLE_ENDIAN 0
- #define TARGET_RT_BIG_ENDIAN 1
- #elif defined(__INTEL__)
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 1
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #define TARGET_RT_LITTLE_ENDIAN 1
- #define TARGET_RT_BIG_ENDIAN 0
- #else
- #error unknown Metrowerks CPU type
- #endif
- #define TARGET_RT_64_BIT 0
- #ifdef __MACH__
- #define TARGET_RT_MAC_CFM 0
- #define TARGET_RT_MAC_MACHO 1
- #else
- #define TARGET_RT_MAC_CFM 1
- #define TARGET_RT_MAC_MACHO 0
- #endif
-
-/*
- * unknown compiler
- */
-#else
- #if defined(TARGET_CPU_PPC) && TARGET_CPU_PPC
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #elif defined(TARGET_CPU_PPC64) && TARGET_CPU_PPC64
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #elif defined(TARGET_CPU_X86) && TARGET_CPU_X86
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #elif defined(TARGET_CPU_X86_64) && TARGET_CPU_X86_64
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #elif defined(TARGET_CPU_ARM) && TARGET_CPU_ARM
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #elif defined(TARGET_CPU_ARM64) && TARGET_CPU_ARM64
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_PPC64 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_X86_64 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #else
- /*
- NOTE: If your compiler errors out here then support for your compiler
- has not yet been added to TargetConditionals.h.
-
- TargetConditionals.h is designed to be plug-and-play. It auto detects
- which compiler is being run and configures the TARGET_ conditionals
- appropriately.
-
- The short term work around is to set the TARGET_CPU_ and TARGET_OS_
- on the command line to the compiler (e.g. -DTARGET_CPU_MIPS=1 -DTARGET_OS_UNIX=1)
-
- The long term solution is to add a new case to this file which
- auto detects your compiler and sets up the TARGET_ conditionals.
- Then submit the changes to Apple Computer.
- */
- #error TargetConditionals.h: unknown compiler (see comment above)
- #define TARGET_CPU_PPC 0
- #define TARGET_CPU_68K 0
- #define TARGET_CPU_X86 0
- #define TARGET_CPU_ARM 0
- #define TARGET_CPU_ARM64 0
- #define TARGET_CPU_MIPS 0
- #define TARGET_CPU_SPARC 0
- #define TARGET_CPU_ALPHA 0
- #endif
- #define TARGET_OS_MAC 1
- #define TARGET_OS_WIN32 0
- #define TARGET_OS_UNIX 0
- #define TARGET_OS_EMBEDDED 0
- #if TARGET_CPU_PPC || TARGET_CPU_PPC64
- #define TARGET_RT_BIG_ENDIAN 1
- #define TARGET_RT_LITTLE_ENDIAN 0
- #else
- #define TARGET_RT_BIG_ENDIAN 0
- #define TARGET_RT_LITTLE_ENDIAN 1
- #endif
- #if TARGET_CPU_PPC64 || TARGET_CPU_X86_64
- #define TARGET_RT_64_BIT 1
- #else
- #define TARGET_RT_64_BIT 0
- #endif
- #ifdef __MACH__
- #define TARGET_RT_MAC_MACHO 1
- #define TARGET_RT_MAC_CFM 0
- #else
- #define TARGET_RT_MAC_MACHO 0
- #define TARGET_RT_MAC_CFM 1
- #endif
-
-#endif
-
-#endif /* __TARGETCONDITIONALS__ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/_ctermid.h b/lib/libc/include/x86_64-macos-gnu/_ctermid.h
deleted file mode 100644
index b941ea10d4..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/_ctermid.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2000, 2002-2006, 2008-2010, 2012 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _CTERMID_H_
-#define _CTERMID_H_
-char *ctermid(char *);
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/bsm/audit.h b/lib/libc/include/x86_64-macos-gnu/bsm/audit.h
deleted file mode 100644
index e65ccbfab6..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/bsm/audit.h
+++ /dev/null
@@ -1,378 +0,0 @@
-/*-
- * Copyright (c) 2005-2009 Apple Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/audit.h#10 $
- */
-
-#ifndef _BSM_AUDIT_H
-#define _BSM_AUDIT_H
-
-#include
-#include
-
-#define AUDIT_RECORD_MAGIC 0x828a0f1b
-#define MAX_AUDIT_RECORDS 20
-#define MAXAUDITDATA (0x8000 - 1)
-#define MAX_AUDIT_RECORD_SIZE MAXAUDITDATA
-#define MIN_AUDIT_FILE_SIZE (512 * 1024)
-
-/*
- * Minimum noumber of free blocks on the filesystem containing the audit
- * log necessary to avoid a hard log rotation. DO NOT SET THIS VALUE TO 0
- * as the kernel does an unsigned compare, plus we want to leave a few blocks
- * free so userspace can terminate the log, etc.
- */
-#define AUDIT_HARD_LIMIT_FREE_BLOCKS 4
-
-/*
- * Triggers for the audit daemon.
- */
-#define AUDIT_TRIGGER_MIN 1
-#define AUDIT_TRIGGER_LOW_SPACE 1 /* Below low watermark. */
-#define AUDIT_TRIGGER_ROTATE_KERNEL 2 /* Kernel requests rotate. */
-#define AUDIT_TRIGGER_READ_FILE 3 /* Re-read config file. */
-#define AUDIT_TRIGGER_CLOSE_AND_DIE 4 /* Terminate audit. */
-#define AUDIT_TRIGGER_NO_SPACE 5 /* Below min free space. */
-#define AUDIT_TRIGGER_ROTATE_USER 6 /* User requests rotate. */
-#define AUDIT_TRIGGER_INITIALIZE 7 /* User initialize of auditd. */
-#define AUDIT_TRIGGER_EXPIRE_TRAILS 8 /* User expiration of trails. */
-#define AUDIT_TRIGGER_MAX 8
-
-/*
- * The special device filename (FreeBSD).
- */
-#define AUDITDEV_FILENAME "audit"
-#define AUDIT_TRIGGER_FILE ("/dev/" AUDITDEV_FILENAME)
-
-/*
- * Pre-defined audit IDs
- */
-#define AU_DEFAUDITID (uid_t)(-1)
-#define AU_DEFAUDITSID 0
-#define AU_ASSIGN_ASID -1
-
-/*
- * IPC types.
- */
-#define AT_IPC_MSG ((unsigned char)1) /* Message IPC id. */
-#define AT_IPC_SEM ((unsigned char)2) /* Semaphore IPC id. */
-#define AT_IPC_SHM ((unsigned char)3) /* Shared mem IPC id. */
-
-/*
- * Audit conditions.
- */
-#define AUC_UNSET 0
-#define AUC_AUDITING 1
-#define AUC_NOAUDIT 2
-#define AUC_DISABLED -1
-
-/*
- * auditon(2) commands.
- */
-#define A_OLDGETPOLICY 2
-#define A_OLDSETPOLICY 3
-#define A_GETKMASK 4
-#define A_SETKMASK 5
-#define A_OLDGETQCTRL 6
-#define A_OLDSETQCTRL 7
-#define A_GETCWD 8
-#define A_GETCAR 9
-#define A_GETSTAT 12
-#define A_SETSTAT 13
-#define A_SETUMASK 14
-#define A_SETSMASK 15
-#define A_OLDGETCOND 20
-#define A_OLDSETCOND 21
-#define A_GETCLASS 22
-#define A_SETCLASS 23
-#define A_GETPINFO 24
-#define A_SETPMASK 25
-#define A_SETFSIZE 26
-#define A_GETFSIZE 27
-#define A_GETPINFO_ADDR 28
-#define A_GETKAUDIT 29
-#define A_SETKAUDIT 30
-#define A_SENDTRIGGER 31
-#define A_GETSINFO_ADDR 32
-#define A_GETPOLICY 33
-#define A_SETPOLICY 34
-#define A_GETQCTRL 35
-#define A_SETQCTRL 36
-#define A_GETCOND 37
-#define A_SETCOND 38
-#define A_GETSFLAGS 39
-#define A_SETSFLAGS 40
-#define A_GETCTLMODE 41
-#define A_SETCTLMODE 42
-#define A_GETEXPAFTER 43
-#define A_SETEXPAFTER 44
-
-/*
- * Audit policy controls.
- */
-#define AUDIT_CNT 0x0001
-#define AUDIT_AHLT 0x0002
-#define AUDIT_ARGV 0x0004
-#define AUDIT_ARGE 0x0008
-#define AUDIT_SEQ 0x0010
-#define AUDIT_WINDATA 0x0020
-#define AUDIT_USER 0x0040
-#define AUDIT_GROUP 0x0080
-#define AUDIT_TRAIL 0x0100
-#define AUDIT_PATH 0x0200
-#define AUDIT_SCNT 0x0400
-#define AUDIT_PUBLIC 0x0800
-#define AUDIT_ZONENAME 0x1000
-#define AUDIT_PERZONE 0x2000
-
-/*
- * Default audit queue control parameters.
- */
-#define AQ_HIWATER 100
-#define AQ_MAXHIGH 10000
-#define AQ_LOWATER 10
-#define AQ_BUFSZ MAXAUDITDATA
-#define AQ_MAXBUFSZ 1048576
-
-/*
- * Default minimum percentage free space on file system.
- */
-#define AU_FS_MINFREE 20
-
-/*
- * Type definitions used indicating the length of variable length addresses
- * in tokens containing addresses, such as header fields.
- */
-#define AU_IPv4 4
-#define AU_IPv6 16
-
-/*
- * Reserved audit class mask indicating which classes are unable to have
- * events added or removed by unentitled processes.
- */
-#define AU_CLASS_MASK_RESERVED 0x10000000
-
-/*
- * Audit control modes
- */
-#define AUDIT_CTLMODE_NORMAL ((unsigned char)1)
-#define AUDIT_CTLMODE_EXTERNAL ((unsigned char)2)
-
-/*
- * Audit file expire_after op modes
- */
-#define AUDIT_EXPIRE_OP_AND ((unsigned char)0)
-#define AUDIT_EXPIRE_OP_OR ((unsigned char)1)
-
-__BEGIN_DECLS
-
-typedef uid_t au_id_t;
-typedef pid_t au_asid_t;
-typedef u_int16_t au_event_t;
-typedef u_int16_t au_emod_t;
-typedef u_int32_t au_class_t;
-typedef u_int64_t au_asflgs_t __attribute__ ((aligned(8)));
-typedef unsigned char au_ctlmode_t;
-
-struct au_tid {
- dev_t port;
- u_int32_t machine;
-};
-typedef struct au_tid au_tid_t;
-
-struct au_tid_addr {
- dev_t at_port;
- u_int32_t at_type;
- u_int32_t at_addr[4];
-};
-typedef struct au_tid_addr au_tid_addr_t;
-
-struct au_mask {
- unsigned int am_success; /* Success bits. */
- unsigned int am_failure; /* Failure bits. */
-};
-typedef struct au_mask au_mask_t;
-
-struct auditinfo {
- au_id_t ai_auid; /* Audit user ID. */
- au_mask_t ai_mask; /* Audit masks. */
- au_tid_t ai_termid; /* Terminal ID. */
- au_asid_t ai_asid; /* Audit session ID. */
-};
-typedef struct auditinfo auditinfo_t;
-
-struct auditinfo_addr {
- au_id_t ai_auid; /* Audit user ID. */
- au_mask_t ai_mask; /* Audit masks. */
- au_tid_addr_t ai_termid; /* Terminal ID. */
- au_asid_t ai_asid; /* Audit session ID. */
- au_asflgs_t ai_flags; /* Audit session flags. */
-};
-typedef struct auditinfo_addr auditinfo_addr_t;
-
-struct auditpinfo {
- pid_t ap_pid; /* ID of target process. */
- au_id_t ap_auid; /* Audit user ID. */
- au_mask_t ap_mask; /* Audit masks. */
- au_tid_t ap_termid; /* Terminal ID. */
- au_asid_t ap_asid; /* Audit session ID. */
-};
-typedef struct auditpinfo auditpinfo_t;
-
-struct auditpinfo_addr {
- pid_t ap_pid; /* ID of target process. */
- au_id_t ap_auid; /* Audit user ID. */
- au_mask_t ap_mask; /* Audit masks. */
- au_tid_addr_t ap_termid; /* Terminal ID. */
- au_asid_t ap_asid; /* Audit session ID. */
- au_asflgs_t ap_flags; /* Audit session flags. */
-};
-typedef struct auditpinfo_addr auditpinfo_addr_t;
-
-struct au_session {
- auditinfo_addr_t *as_aia_p; /* Ptr to full audit info. */
- au_mask_t as_mask; /* Process Audit Masks. */
-};
-typedef struct au_session au_session_t;
-
-struct au_expire_after {
- time_t age; /* Age after which trail files should be expired */
- size_t size; /* Aggregate trail size when files should be expired */
- unsigned char op_type; /* Operator used with the above values to determine when files should be expired */
-};
-typedef struct au_expire_after au_expire_after_t;
-
-/*
- * Contents of token_t are opaque outside of libbsm.
- */
-typedef struct au_token token_t;
-
-/*
- * Kernel audit queue control parameters:
- * Default: Maximum:
- * aq_hiwater: AQ_HIWATER (100) AQ_MAXHIGH (10000)
- * aq_lowater: AQ_LOWATER (10)
-
-/*
- * getaudit()/setaudit() are deprecated and have been replaced with
- * wrappers to the getaudit_addr()/setaudit_addr() syscalls above.
- */
-
-int getaudit(struct auditinfo *)
-__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_8,
- __IPHONE_2_0, __IPHONE_6_0);
-int setaudit(const struct auditinfo *)
-__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_8,
- __IPHONE_2_0, __IPHONE_6_0);
-#else
-
-int getaudit(struct auditinfo *);
-int setaudit(const struct auditinfo *);
-#endif /* !__APPLE__ */
-
-#ifdef __APPLE_API_PRIVATE
-#include
-mach_port_name_t audit_session_self(void);
-au_asid_t audit_session_join(mach_port_name_t port);
-int audit_session_port(au_asid_t asid, mach_port_name_t *portname);
-#endif /* __APPLE_API_PRIVATE */
-
-#endif /* defined(_KERNEL) || defined(KERNEL) */
-
-__END_DECLS
-
-#endif /* !_BSM_AUDIT_H */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/dispatch/block.h b/lib/libc/include/x86_64-macos-gnu/dispatch/block.h
deleted file mode 100644
index 5a28f48ce4..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/dispatch/block.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (c) 2014 Apple Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-
-#ifndef __DISPATCH_BLOCK__
-#define __DISPATCH_BLOCK__
-
-#ifndef __DISPATCH_INDIRECT__
-#error "Please #include instead of this file directly."
-#include // for HeaderDoc
-#endif
-
-#ifdef __BLOCKS__
-
-/*!
- * @group Dispatch block objects
- */
-
-DISPATCH_ASSUME_NONNULL_BEGIN
-
-__BEGIN_DECLS
-
-/*!
- * @typedef dispatch_block_flags_t
- * Flags to pass to the dispatch_block_create* functions.
- *
- * @const DISPATCH_BLOCK_BARRIER
- * Flag indicating that a dispatch block object should act as a barrier block
- * when submitted to a DISPATCH_QUEUE_CONCURRENT queue.
- * See dispatch_barrier_async() for details.
- * This flag has no effect when the dispatch block object is invoked directly.
- *
- * @const DISPATCH_BLOCK_DETACHED
- * Flag indicating that a dispatch block object should execute disassociated
- * from current execution context attributes such as os_activity_t
- * and properties of the current IPC request (if any). With regard to QoS class,
- * the behavior is the same as for DISPATCH_BLOCK_NO_QOS. If invoked directly,
- * the block object will remove the other attributes from the calling thread for
- * the duration of the block body (before applying attributes assigned to the
- * block object, if any). If submitted to a queue, the block object will be
- * executed with the attributes of the queue (or any attributes specifically
- * assigned to the block object).
- *
- * @const DISPATCH_BLOCK_ASSIGN_CURRENT
- * Flag indicating that a dispatch block object should be assigned the execution
- * context attributes that are current at the time the block object is created.
- * This applies to attributes such as QOS class, os_activity_t and properties of
- * the current IPC request (if any). If invoked directly, the block object will
- * apply these attributes to the calling thread for the duration of the block
- * body. If the block object is submitted to a queue, this flag replaces the
- * default behavior of associating the submitted block instance with the
- * execution context attributes that are current at the time of submission.
- * If a specific QOS class is assigned with DISPATCH_BLOCK_NO_QOS_CLASS or
- * dispatch_block_create_with_qos_class(), that QOS class takes precedence over
- * the QOS class assignment indicated by this flag.
- *
- * @const DISPATCH_BLOCK_NO_QOS_CLASS
- * Flag indicating that a dispatch block object should be not be assigned a QOS
- * class. If invoked directly, the block object will be executed with the QOS
- * class of the calling thread. If the block object is submitted to a queue,
- * this replaces the default behavior of associating the submitted block
- * instance with the QOS class current at the time of submission.
- * This flag is ignored if a specific QOS class is assigned with
- * dispatch_block_create_with_qos_class().
- *
- * @const DISPATCH_BLOCK_INHERIT_QOS_CLASS
- * Flag indicating that execution of a dispatch block object submitted to a
- * queue should prefer the QOS class assigned to the queue over the QOS class
- * assigned to the block (resp. associated with the block at the time of
- * submission). The latter will only be used if the queue in question does not
- * have an assigned QOS class, as long as doing so does not result in a QOS
- * class lower than the QOS class inherited from the queue's target queue.
- * This flag is the default when a dispatch block object is submitted to a queue
- * for asynchronous execution and has no effect when the dispatch block object
- * is invoked directly. It is ignored if DISPATCH_BLOCK_ENFORCE_QOS_CLASS is
- * also passed.
- *
- * @const DISPATCH_BLOCK_ENFORCE_QOS_CLASS
- * Flag indicating that execution of a dispatch block object submitted to a
- * queue should prefer the QOS class assigned to the block (resp. associated
- * with the block at the time of submission) over the QOS class assigned to the
- * queue, as long as doing so will not result in a lower QOS class.
- * This flag is the default when a dispatch block object is submitted to a queue
- * for synchronous execution or when the dispatch block object is invoked
- * directly.
- */
-DISPATCH_OPTIONS(dispatch_block_flags, unsigned long,
- DISPATCH_BLOCK_BARRIER
- DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x1,
- DISPATCH_BLOCK_DETACHED
- DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x2,
- DISPATCH_BLOCK_ASSIGN_CURRENT
- DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x4,
- DISPATCH_BLOCK_NO_QOS_CLASS
- DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x8,
- DISPATCH_BLOCK_INHERIT_QOS_CLASS
- DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x10,
- DISPATCH_BLOCK_ENFORCE_QOS_CLASS
- DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x20,
-);
-
-/*!
- * @function dispatch_block_create
- *
- * @abstract
- * Create a new dispatch block object on the heap from an existing block and
- * the given flags.
- *
- * @discussion
- * The provided block is Block_copy'ed to the heap and retained by the newly
- * created dispatch block object.
- *
- * The returned dispatch block object is intended to be submitted to a dispatch
- * queue with dispatch_async() and related functions, but may also be invoked
- * directly. Both operations can be performed an arbitrary number of times but
- * only the first completed execution of a dispatch block object can be waited
- * on with dispatch_block_wait() or observed with dispatch_block_notify().
- *
- * If the returned dispatch block object is submitted to a dispatch queue, the
- * submitted block instance will be associated with the QOS class current at the
- * time of submission, unless one of the following flags assigned a specific QOS
- * class (or no QOS class) at the time of block creation:
- * - DISPATCH_BLOCK_ASSIGN_CURRENT
- * - DISPATCH_BLOCK_NO_QOS_CLASS
- * - DISPATCH_BLOCK_DETACHED
- * The QOS class the block object will be executed with also depends on the QOS
- * class assigned to the queue and which of the following flags was specified or
- * defaulted to:
- * - DISPATCH_BLOCK_INHERIT_QOS_CLASS (default for asynchronous execution)
- * - DISPATCH_BLOCK_ENFORCE_QOS_CLASS (default for synchronous execution)
- * See description of dispatch_block_flags_t for details.
- *
- * If the returned dispatch block object is submitted directly to a serial queue
- * and is configured to execute with a specific QOS class, the system will make
- * a best effort to apply the necessary QOS overrides to ensure that blocks
- * submitted earlier to the serial queue are executed at that same QOS class or
- * higher.
- *
- * @param flags
- * Configuration flags for the block object.
- * Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
- * results in NULL being returned.
- *
- * @param block
- * The block to create the dispatch block object from.
- *
- * @result
- * The newly created dispatch block object, or NULL.
- * When not building with Objective-C ARC, must be released with a -[release]
- * message or the Block_release() function.
- */
-API_AVAILABLE(macos(10.10), ios(8.0))
-DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_RETURNS_RETAINED_BLOCK
-DISPATCH_WARN_RESULT DISPATCH_NOTHROW
-dispatch_block_t
-dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
-
-/*!
- * @function dispatch_block_create_with_qos_class
- *
- * @abstract
- * Create a new dispatch block object on the heap from an existing block and
- * the given flags, and assign it the specified QOS class and relative priority.
- *
- * @discussion
- * The provided block is Block_copy'ed to the heap and retained by the newly
- * created dispatch block object.
- *
- * The returned dispatch block object is intended to be submitted to a dispatch
- * queue with dispatch_async() and related functions, but may also be invoked
- * directly. Both operations can be performed an arbitrary number of times but
- * only the first completed execution of a dispatch block object can be waited
- * on with dispatch_block_wait() or observed with dispatch_block_notify().
- *
- * If invoked directly, the returned dispatch block object will be executed with
- * the assigned QOS class as long as that does not result in a lower QOS class
- * than what is current on the calling thread.
- *
- * If the returned dispatch block object is submitted to a dispatch queue, the
- * QOS class it will be executed with depends on the QOS class assigned to the
- * block, the QOS class assigned to the queue and which of the following flags
- * was specified or defaulted to:
- * - DISPATCH_BLOCK_INHERIT_QOS_CLASS: default for asynchronous execution
- * - DISPATCH_BLOCK_ENFORCE_QOS_CLASS: default for synchronous execution
- * See description of dispatch_block_flags_t for details.
- *
- * If the returned dispatch block object is submitted directly to a serial queue
- * and is configured to execute with a specific QOS class, the system will make
- * a best effort to apply the necessary QOS overrides to ensure that blocks
- * submitted earlier to the serial queue are executed at that same QOS class or
- * higher.
- *
- * @param flags
- * Configuration flags for the new block object.
- * Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
- * results in NULL being returned.
- *
- * @param qos_class
- * A QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * - QOS_CLASS_UNSPECIFIED
- * Passing QOS_CLASS_UNSPECIFIED is equivalent to specifying the
- * DISPATCH_BLOCK_NO_QOS_CLASS flag. Passing any other value results in NULL
- * being returned.
- *
- * @param relative_priority
- * A relative priority within the QOS class. This value is a negative
- * offset from the maximum supported scheduler priority for the given class.
- * Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
- * results in NULL being returned.
- *
- * @param block
- * The block to create the dispatch block object from.
- *
- * @result
- * The newly created dispatch block object, or NULL.
- * When not building with Objective-C ARC, must be released with a -[release]
- * message or the Block_release() function.
- */
-API_AVAILABLE(macos(10.10), ios(8.0))
-DISPATCH_EXPORT DISPATCH_NONNULL4 DISPATCH_RETURNS_RETAINED_BLOCK
-DISPATCH_WARN_RESULT DISPATCH_NOTHROW
-dispatch_block_t
-dispatch_block_create_with_qos_class(dispatch_block_flags_t flags,
- dispatch_qos_class_t qos_class, int relative_priority,
- dispatch_block_t block);
-
-/*!
- * @function dispatch_block_perform
- *
- * @abstract
- * Create, synchronously execute and release a dispatch block object from the
- * specified block and flags.
- *
- * @discussion
- * Behaves identically to the sequence
- *
- * dispatch_block_t b = dispatch_block_create(flags, block);
- * b();
- * Block_release(b);
- *
- * but may be implemented more efficiently internally by not requiring a copy
- * to the heap of the specified block or the allocation of a new block object.
- *
- * @param flags
- * Configuration flags for the temporary block object.
- * The result of passing a value that is not a bitwise OR of flags from
- * dispatch_block_flags_t is undefined.
- *
- * @param block
- * The block to create the temporary block object from.
- */
-API_AVAILABLE(macos(10.10), ios(8.0))
-DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW
-void
-dispatch_block_perform(dispatch_block_flags_t flags,
- DISPATCH_NOESCAPE dispatch_block_t block);
-
-/*!
- * @function dispatch_block_wait
- *
- * @abstract
- * Wait synchronously until execution of the specified dispatch block object has
- * completed or until the specified timeout has elapsed.
- *
- * @discussion
- * This function will return immediately if execution of the block object has
- * already completed.
- *
- * It is not possible to wait for multiple executions of the same block object
- * with this interface; use dispatch_group_wait() for that purpose. A single
- * dispatch block object may either be waited on once and executed once,
- * or it may be executed any number of times. The behavior of any other
- * combination is undefined. Submission to a dispatch queue counts as an
- * execution, even if cancellation (dispatch_block_cancel) means the block's
- * code never runs.
- *
- * The result of calling this function from multiple threads simultaneously
- * with the same dispatch block object is undefined, but note that doing so
- * would violate the rules described in the previous paragraph.
- *
- * If this function returns indicating that the specified timeout has elapsed,
- * then that invocation does not count as the one allowed wait.
- *
- * If at the time this function is called, the specified dispatch block object
- * has been submitted directly to a serial queue, the system will make a best
- * effort to apply the necessary QOS overrides to ensure that the block and any
- * blocks submitted earlier to that serial queue are executed at the QOS class
- * (or higher) of the thread calling dispatch_block_wait().
- *
- * @param block
- * The dispatch block object to wait on.
- * The result of passing NULL or a block object not returned by one of the
- * dispatch_block_create* functions is undefined.
- *
- * @param timeout
- * When to timeout (see dispatch_time). As a convenience, there are the
- * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
- *
- * @result
- * Returns zero on success (the dispatch block object completed within the
- * specified timeout) or non-zero on error (i.e. timed out).
- */
-API_AVAILABLE(macos(10.10), ios(8.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-long
-dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);
-
-/*!
- * @function dispatch_block_notify
- *
- * @abstract
- * Schedule a notification block to be submitted to a queue when the execution
- * of a specified dispatch block object has completed.
- *
- * @discussion
- * This function will submit the notification block immediately if execution of
- * the observed block object has already completed.
- *
- * It is not possible to be notified of multiple executions of the same block
- * object with this interface, use dispatch_group_notify() for that purpose.
- *
- * A single dispatch block object may either be observed one or more times
- * and executed once, or it may be executed any number of times. The behavior
- * of any other combination is undefined. Submission to a dispatch queue
- * counts as an execution, even if cancellation (dispatch_block_cancel) means
- * the block's code never runs.
- *
- * If multiple notification blocks are scheduled for a single block object,
- * there is no defined order in which the notification blocks will be submitted
- * to their associated queues.
- *
- * @param block
- * The dispatch block object to observe.
- * The result of passing NULL or a block object not returned by one of the
- * dispatch_block_create* functions is undefined.
- *
- * @param queue
- * The queue to which the supplied notification block will be submitted when
- * the observed block completes.
- *
- * @param notification_block
- * The notification block to submit when the observed block object completes.
- */
-API_AVAILABLE(macos(10.10), ios(8.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue,
- dispatch_block_t notification_block);
-
-/*!
- * @function dispatch_block_cancel
- *
- * @abstract
- * Asynchronously cancel the specified dispatch block object.
- *
- * @discussion
- * Cancellation causes any future execution of the dispatch block object to
- * return immediately, but does not affect any execution of the block object
- * that is already in progress.
- *
- * Release of any resources associated with the block object will be delayed
- * until execution of the block object is next attempted (or any execution
- * already in progress completes).
- *
- * NOTE: care needs to be taken to ensure that a block object that may be
- * canceled does not capture any resources that require execution of the
- * block body in order to be released (e.g. memory allocated with
- * malloc(3) that the block body calls free(3) on). Such resources will
- * be leaked if the block body is never executed due to cancellation.
- *
- * @param block
- * The dispatch block object to cancel.
- * The result of passing NULL or a block object not returned by one of the
- * dispatch_block_create* functions is undefined.
- */
-API_AVAILABLE(macos(10.10), ios(8.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_block_cancel(dispatch_block_t block);
-
-/*!
- * @function dispatch_block_testcancel
- *
- * @abstract
- * Tests whether the given dispatch block object has been canceled.
- *
- * @param block
- * The dispatch block object to test.
- * The result of passing NULL or a block object not returned by one of the
- * dispatch_block_create* functions is undefined.
- *
- * @result
- * Non-zero if canceled and zero if not canceled.
- */
-API_AVAILABLE(macos(10.10), ios(8.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
-DISPATCH_NOTHROW
-long
-dispatch_block_testcancel(dispatch_block_t block);
-
-__END_DECLS
-
-DISPATCH_ASSUME_NONNULL_END
-
-#endif // __BLOCKS__
-
-#endif // __DISPATCH_BLOCK__
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/dispatch/dispatch.h b/lib/libc/include/x86_64-macos-gnu/dispatch/dispatch.h
deleted file mode 100644
index 7d5356aab6..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/dispatch/dispatch.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-
-#ifndef __DISPATCH_PUBLIC__
-#define __DISPATCH_PUBLIC__
-
-#ifdef __APPLE__
-#include
-#include
-#include
-#include
-#elif defined(_WIN32)
-#include
-#elif defined(__unix__)
-#include
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
-#include
-#endif
-#include
-
-#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__has_feature)
-#if __has_feature(modules)
-#if !defined(__arm__)
-#include // for off_t (to match Glibc.modulemap)
-#endif
-#endif
-#endif
-
-#define DISPATCH_API_VERSION 20181008
-
-#ifndef __DISPATCH_INDIRECT__
-#define __DISPATCH_INDIRECT__
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#undef __DISPATCH_INDIRECT__
-
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/dispatch/group.h b/lib/libc/include/x86_64-macos-gnu/dispatch/group.h
deleted file mode 100644
index bb9bad30e3..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/dispatch/group.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-
-#ifndef __DISPATCH_GROUP__
-#define __DISPATCH_GROUP__
-
-#ifndef __DISPATCH_INDIRECT__
-#error "Please #include instead of this file directly."
-#include // for HeaderDoc
-#endif
-
-DISPATCH_ASSUME_NONNULL_BEGIN
-
-/*!
- * @typedef dispatch_group_t
- * @abstract
- * A group of blocks submitted to queues for asynchronous invocation.
- */
-DISPATCH_DECL(dispatch_group);
-
-__BEGIN_DECLS
-
-/*!
- * @function dispatch_group_create
- *
- * @abstract
- * Creates new group with which blocks may be associated.
- *
- * @discussion
- * This function creates a new group with which blocks may be associated.
- * The dispatch group may be used to wait for the completion of the blocks it
- * references. The group object memory is freed with dispatch_release().
- *
- * @result
- * The newly created group, or NULL on failure.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
-DISPATCH_NOTHROW
-dispatch_group_t
-dispatch_group_create(void);
-
-/*!
- * @function dispatch_group_async
- *
- * @abstract
- * Submits a block to a dispatch queue and associates the block with the given
- * dispatch group.
- *
- * @discussion
- * Submits a block to a dispatch queue and associates the block with the given
- * dispatch group. The dispatch group may be used to wait for the completion
- * of the blocks it references.
- *
- * @param group
- * A dispatch group to associate with the submitted block.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param queue
- * The dispatch queue to which the block will be submitted for asynchronous
- * invocation.
- *
- * @param block
- * The block to perform asynchronously.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_group_async(dispatch_group_t group,
- dispatch_queue_t queue,
- dispatch_block_t block);
-#endif /* __BLOCKS__ */
-
-/*!
- * @function dispatch_group_async_f
- *
- * @abstract
- * Submits a function to a dispatch queue and associates the block with the
- * given dispatch group.
- *
- * @discussion
- * See dispatch_group_async() for details.
- *
- * @param group
- * A dispatch group to associate with the submitted function.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param queue
- * The dispatch queue to which the function will be submitted for asynchronous
- * invocation.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the target queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_group_async_f().
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_NONNULL4
-DISPATCH_NOTHROW
-void
-dispatch_group_async_f(dispatch_group_t group,
- dispatch_queue_t queue,
- void *_Nullable context,
- dispatch_function_t work);
-
-/*!
- * @function dispatch_group_wait
- *
- * @abstract
- * Wait synchronously until all the blocks associated with a group have
- * completed or until the specified timeout has elapsed.
- *
- * @discussion
- * This function waits for the completion of the blocks associated with the
- * given dispatch group, and returns after all blocks have completed or when
- * the specified timeout has elapsed.
- *
- * This function will return immediately if there are no blocks associated
- * with the dispatch group (i.e. the group is empty).
- *
- * The result of calling this function from multiple threads simultaneously
- * with the same dispatch group is undefined.
- *
- * After the successful return of this function, the dispatch group is empty.
- * It may either be released with dispatch_release() or re-used for additional
- * blocks. See dispatch_group_async() for more information.
- *
- * @param group
- * The dispatch group to wait on.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param timeout
- * When to timeout (see dispatch_time). As a convenience, there are the
- * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
- *
- * @result
- * Returns zero on success (all blocks associated with the group completed
- * within the specified timeout) or non-zero on error (i.e. timed out).
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-long
-dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);
-
-/*!
- * @function dispatch_group_notify
- *
- * @abstract
- * Schedule a block to be submitted to a queue when all the blocks associated
- * with a group have completed.
- *
- * @discussion
- * This function schedules a notification block to be submitted to the specified
- * queue once all blocks associated with the dispatch group have completed.
- *
- * If no blocks are associated with the dispatch group (i.e. the group is empty)
- * then the notification block will be submitted immediately.
- *
- * The group will be empty at the time the notification block is submitted to
- * the target queue. The group may either be released with dispatch_release()
- * or reused for additional operations.
- * See dispatch_group_async() for more information.
- *
- * @param group
- * The dispatch group to observe.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param queue
- * The queue to which the supplied block will be submitted when the group
- * completes.
- *
- * @param block
- * The block to submit when the group completes.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_group_notify(dispatch_group_t group,
- dispatch_queue_t queue,
- dispatch_block_t block);
-#endif /* __BLOCKS__ */
-
-/*!
- * @function dispatch_group_notify_f
- *
- * @abstract
- * Schedule a function to be submitted to a queue when all the blocks
- * associated with a group have completed.
- *
- * @discussion
- * See dispatch_group_notify() for details.
- *
- * @param group
- * The dispatch group to observe.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the target queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_group_notify_f().
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_NONNULL4
-DISPATCH_NOTHROW
-void
-dispatch_group_notify_f(dispatch_group_t group,
- dispatch_queue_t queue,
- void *_Nullable context,
- dispatch_function_t work);
-
-/*!
- * @function dispatch_group_enter
- *
- * @abstract
- * Manually indicate a block has entered the group
- *
- * @discussion
- * Calling this function indicates another block has joined the group through
- * a means other than dispatch_group_async(). Calls to this function must be
- * balanced with dispatch_group_leave().
- *
- * @param group
- * The dispatch group to update.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_group_enter(dispatch_group_t group);
-
-/*!
- * @function dispatch_group_leave
- *
- * @abstract
- * Manually indicate a block in the group has completed
- *
- * @discussion
- * Calling this function indicates block has completed and left the dispatch
- * group by a means other than dispatch_group_async().
- *
- * @param group
- * The dispatch group to update.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_group_leave(dispatch_group_t group);
-
-__END_DECLS
-
-DISPATCH_ASSUME_NONNULL_END
-
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/dispatch/object.h b/lib/libc/include/x86_64-macos-gnu/dispatch/object.h
deleted file mode 100644
index 3d89eb1fe6..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/dispatch/object.h
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-
-#ifndef __DISPATCH_OBJECT__
-#define __DISPATCH_OBJECT__
-
-#ifndef __DISPATCH_INDIRECT__
-#error "Please #include instead of this file directly."
-#include // for HeaderDoc
-#endif
-
-#if __has_include()
-#include
-#endif
-
-DISPATCH_ASSUME_NONNULL_BEGIN
-
-/*!
- * @typedef dispatch_object_t
- *
- * @abstract
- * Abstract base type for all dispatch objects.
- * The details of the type definition are language-specific.
- *
- * @discussion
- * Dispatch objects are reference counted via calls to dispatch_retain() and
- * dispatch_release().
- */
-
-#if OS_OBJECT_USE_OBJC
-/*
- * By default, dispatch objects are declared as Objective-C types when building
- * with an Objective-C compiler. This allows them to participate in ARC, in RR
- * management by the Blocks runtime and in leaks checking by the static
- * analyzer, and enables them to be added to Cocoa collections.
- * See for details.
- */
-OS_OBJECT_DECL_CLASS(dispatch_object);
-
-#if OS_OBJECT_SWIFT3
-#define DISPATCH_DECL(name) OS_OBJECT_DECL_SUBCLASS_SWIFT(name, dispatch_object)
-#define DISPATCH_DECL_SUBCLASS(name, base) OS_OBJECT_DECL_SUBCLASS_SWIFT(name, base)
-#else // OS_OBJECT_SWIFT3
-#define DISPATCH_DECL(name) OS_OBJECT_DECL_SUBCLASS(name, dispatch_object)
-#define DISPATCH_DECL_SUBCLASS(name, base) OS_OBJECT_DECL_SUBCLASS(name, base)
-
-DISPATCH_INLINE DISPATCH_ALWAYS_INLINE DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-_dispatch_object_validate(dispatch_object_t object)
-{
- void *isa = *(void *volatile*)(OS_OBJECT_BRIDGE void*)object;
- (void)isa;
-}
-#endif // OS_OBJECT_SWIFT3
-
-#define DISPATCH_GLOBAL_OBJECT(type, object) ((OS_OBJECT_BRIDGE type)&(object))
-#define DISPATCH_RETURNS_RETAINED OS_OBJECT_RETURNS_RETAINED
-#elif defined(__cplusplus) && !defined(__DISPATCH_BUILDING_DISPATCH__)
-/*
- * Dispatch objects are NOT C++ objects. Nevertheless, we can at least keep C++
- * aware of type compatibility.
- */
-typedef struct dispatch_object_s {
-private:
- dispatch_object_s();
- ~dispatch_object_s();
- dispatch_object_s(const dispatch_object_s &);
- void operator=(const dispatch_object_s &);
-} *dispatch_object_t;
-#define DISPATCH_DECL(name) \
- typedef struct name##_s : public dispatch_object_s {} *name##_t
-#define DISPATCH_DECL_SUBCLASS(name, base) \
- typedef struct name##_s : public base##_s {} *name##_t
-#define DISPATCH_GLOBAL_OBJECT(type, object) (static_cast(&(object)))
-#define DISPATCH_RETURNS_RETAINED
-#else /* Plain C */
-typedef union {
- struct _os_object_s *_os_obj;
- struct dispatch_object_s *_do;
- struct dispatch_queue_s *_dq;
- struct dispatch_queue_attr_s *_dqa;
- struct dispatch_group_s *_dg;
- struct dispatch_source_s *_ds;
- struct dispatch_channel_s *_dch;
- struct dispatch_mach_s *_dm;
- struct dispatch_mach_msg_s *_dmsg;
- struct dispatch_semaphore_s *_dsema;
- struct dispatch_data_s *_ddata;
- struct dispatch_io_s *_dchannel;
-} dispatch_object_t DISPATCH_TRANSPARENT_UNION;
-#define DISPATCH_DECL(name) typedef struct name##_s *name##_t
-#define DISPATCH_DECL_SUBCLASS(name, base) typedef base##_t name##_t
-#define DISPATCH_GLOBAL_OBJECT(type, object) ((type)&(object))
-#define DISPATCH_RETURNS_RETAINED
-#endif
-
-#if OS_OBJECT_SWIFT3 && OS_OBJECT_USE_OBJC
-#define DISPATCH_SOURCE_TYPE_DECL(name) \
- DISPATCH_EXPORT struct dispatch_source_type_s \
- _dispatch_source_type_##name; \
- OS_OBJECT_DECL_PROTOCOL(dispatch_source_##name, ); \
- OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL( \
- dispatch_source, dispatch_source_##name)
-#define DISPATCH_SOURCE_DECL(name) \
- DISPATCH_DECL(name); \
- OS_OBJECT_DECL_PROTOCOL(name, ); \
- OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL(name, name)
-#ifndef DISPATCH_DATA_DECL
-#define DISPATCH_DATA_DECL(name) OS_OBJECT_DECL_SWIFT(name)
-#endif // DISPATCH_DATA_DECL
-#else
-#define DISPATCH_SOURCE_DECL(name) \
- DISPATCH_DECL(name);
-#define DISPATCH_DATA_DECL(name) DISPATCH_DECL(name)
-#define DISPATCH_SOURCE_TYPE_DECL(name) \
- DISPATCH_EXPORT const struct dispatch_source_type_s \
- _dispatch_source_type_##name
-#endif
-
-#ifdef __BLOCKS__
-/*!
- * @typedef dispatch_block_t
- *
- * @abstract
- * The type of blocks submitted to dispatch queues, which take no arguments
- * and have no return value.
- *
- * @discussion
- * When not building with Objective-C ARC, a block object allocated on or
- * copied to the heap must be released with a -[release] message or the
- * Block_release() function.
- *
- * The declaration of a block literal allocates storage on the stack.
- * Therefore, this is an invalid construct:
- *
- * dispatch_block_t block;
- * if (x) {
- * block = ^{ printf("true\n"); };
- * } else {
- * block = ^{ printf("false\n"); };
- * }
- * block(); // unsafe!!!
- *
- *
- * What is happening behind the scenes:
- *
- * if (x) {
- * struct Block __tmp_1 = ...; // setup details
- * block = &__tmp_1;
- * } else {
- * struct Block __tmp_2 = ...; // setup details
- * block = &__tmp_2;
- * }
- *
- *
- * As the example demonstrates, the address of a stack variable is escaping the
- * scope in which it is allocated. That is a classic C bug.
- *
- * Instead, the block literal must be copied to the heap with the Block_copy()
- * function or by sending it a -[copy] message.
- */
-typedef void (^dispatch_block_t)(void);
-#endif // __BLOCKS__
-
-__BEGIN_DECLS
-
-/*!
- * @typedef dispatch_qos_class_t
- * Alias for qos_class_t type.
- */
-#if __has_include()
-typedef qos_class_t dispatch_qos_class_t;
-#else
-typedef unsigned int dispatch_qos_class_t;
-#endif
-
-/*!
- * @function dispatch_retain
- *
- * @abstract
- * Increment the reference count of a dispatch object.
- *
- * @discussion
- * Calls to dispatch_retain() must be balanced with calls to
- * dispatch_release().
- *
- * @param object
- * The object to retain.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-DISPATCH_SWIFT_UNAVAILABLE("Can't be used with ARC")
-void
-dispatch_retain(dispatch_object_t object);
-#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
-#undef dispatch_retain
-#define dispatch_retain(object) \
- __extension__({ dispatch_object_t _o = (object); \
- _dispatch_object_validate(_o); (void)[_o retain]; })
-#endif
-
-/*!
- * @function dispatch_release
- *
- * @abstract
- * Decrement the reference count of a dispatch object.
- *
- * @discussion
- * A dispatch object is asynchronously deallocated once all references are
- * released (i.e. the reference count becomes zero). The system does not
- * guarantee that a given client is the last or only reference to a given
- * object.
- *
- * @param object
- * The object to release.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-DISPATCH_SWIFT_UNAVAILABLE("Can't be used with ARC")
-void
-dispatch_release(dispatch_object_t object);
-#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
-#undef dispatch_release
-#define dispatch_release(object) \
- __extension__({ dispatch_object_t _o = (object); \
- _dispatch_object_validate(_o); [_o release]; })
-#endif
-
-/*!
- * @function dispatch_get_context
- *
- * @abstract
- * Returns the application defined context of the object.
- *
- * @param object
- * The result of passing NULL in this parameter is undefined.
- *
- * @result
- * The context of the object; may be NULL.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_PURE DISPATCH_WARN_RESULT
-DISPATCH_NOTHROW
-void *_Nullable
-dispatch_get_context(dispatch_object_t object);
-
-/*!
- * @function dispatch_set_context
- *
- * @abstract
- * Associates an application defined context with the object.
- *
- * @param object
- * The result of passing NULL in this parameter is undefined.
- *
- * @param context
- * The new client defined context for the object. This may be NULL.
- *
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NOTHROW
-void
-dispatch_set_context(dispatch_object_t object, void *_Nullable context);
-
-/*!
- * @function dispatch_set_finalizer_f
- *
- * @abstract
- * Set the finalizer function for a dispatch object.
- *
- * @param object
- * The dispatch object to modify.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param finalizer
- * The finalizer function pointer.
- *
- * @discussion
- * A dispatch object's finalizer will be invoked on the object's target queue
- * after all references to the object have been released. This finalizer may be
- * used by the application to release any resources associated with the object,
- * such as freeing the object's context.
- * The context parameter passed to the finalizer function is the current
- * context of the dispatch object at the time the finalizer call is made.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NOTHROW
-void
-dispatch_set_finalizer_f(dispatch_object_t object,
- dispatch_function_t _Nullable finalizer);
-
-/*!
- * @function dispatch_activate
- *
- * @abstract
- * Activates the specified dispatch object.
- *
- * @discussion
- * Dispatch objects such as queues and sources may be created in an inactive
- * state. Objects in this state have to be activated before any blocks
- * associated with them will be invoked.
- *
- * The target queue of inactive objects can be changed using
- * dispatch_set_target_queue(). Change of target queue is no longer permitted
- * once an initially inactive object has been activated.
- *
- * Calling dispatch_activate() on an active object has no effect.
- * Releasing the last reference count on an inactive object is undefined.
- *
- * @param object
- * The object to be activated.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_activate(dispatch_object_t object);
-
-/*!
- * @function dispatch_suspend
- *
- * @abstract
- * Suspends the invocation of blocks on a dispatch object.
- *
- * @discussion
- * A suspended object will not invoke any blocks associated with it. The
- * suspension of an object will occur after any running block associated with
- * the object completes.
- *
- * Calls to dispatch_suspend() must be balanced with calls
- * to dispatch_resume().
- *
- * @param object
- * The object to be suspended.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_suspend(dispatch_object_t object);
-
-/*!
- * @function dispatch_resume
- *
- * @abstract
- * Resumes the invocation of blocks on a dispatch object.
- *
- * @discussion
- * Dispatch objects can be suspended with dispatch_suspend(), which increments
- * an internal suspension count. dispatch_resume() is the inverse operation,
- * and consumes suspension counts. When the last suspension count is consumed,
- * blocks associated with the object will be invoked again.
- *
- * For backward compatibility reasons, dispatch_resume() on an inactive and not
- * otherwise suspended dispatch source object has the same effect as calling
- * dispatch_activate(). For new code, using dispatch_activate() is preferred.
- *
- * If the specified object has zero suspension count and is not an inactive
- * source, this function will result in an assertion and the process being
- * terminated.
- *
- * @param object
- * The object to be resumed.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_resume(dispatch_object_t object);
-
-/*!
- * @function dispatch_set_qos_class_floor
- *
- * @abstract
- * Sets the QOS class floor on a dispatch queue, source or workloop.
- *
- * @discussion
- * The QOS class of workitems submitted to this object asynchronously will be
- * elevated to at least the specified QOS class floor. The QOS of the workitem
- * will be used if higher than the floor even when the workitem has been created
- * without "ENFORCE" semantics.
- *
- * Setting the QOS class floor is equivalent to the QOS effects of configuring
- * a queue whose target queue has a QoS class set to the same value.
- *
- * @param object
- * A dispatch queue, workloop, or source to configure.
- * The object must be inactive.
- *
- * Passing another object type or an object that has been activated is undefined
- * and will cause the process to be terminated.
- *
- * @param qos_class
- * A QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * Passing any other value is undefined.
- *
- * @param relative_priority
- * A relative priority within the QOS class. This value is a negative
- * offset from the maximum supported scheduler priority for the given class.
- * Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
- * is undefined.
- */
-API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-DISPATCH_EXPORT DISPATCH_NOTHROW
-void
-dispatch_set_qos_class_floor(dispatch_object_t object,
- dispatch_qos_class_t qos_class, int relative_priority);
-
-#ifdef __BLOCKS__
-/*!
- * @function dispatch_wait
- *
- * @abstract
- * Wait synchronously for an object or until the specified timeout has elapsed.
- *
- * @discussion
- * Type-generic macro that maps to dispatch_block_wait, dispatch_group_wait or
- * dispatch_semaphore_wait, depending on the type of the first argument.
- * See documentation for these functions for more details.
- * This function is unavailable for any other object type.
- *
- * @param object
- * The object to wait on.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param timeout
- * When to timeout (see dispatch_time). As a convenience, there are the
- * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
- *
- * @result
- * Returns zero on success or non-zero on error (i.e. timed out).
- */
-DISPATCH_UNAVAILABLE
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-long
-dispatch_wait(void *object, dispatch_time_t timeout);
-#if __has_extension(c_generic_selections)
-#define dispatch_wait(object, timeout) \
- _Generic((object), \
- dispatch_block_t:dispatch_block_wait, \
- dispatch_group_t:dispatch_group_wait, \
- dispatch_semaphore_t:dispatch_semaphore_wait \
- )((object),(timeout))
-#endif
-
-/*!
- * @function dispatch_notify
- *
- * @abstract
- * Schedule a notification block to be submitted to a queue when the execution
- * of a specified object has completed.
- *
- * @discussion
- * Type-generic macro that maps to dispatch_block_notify or
- * dispatch_group_notify, depending on the type of the first argument.
- * See documentation for these functions for more details.
- * This function is unavailable for any other object type.
- *
- * @param object
- * The object to observe.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param queue
- * The queue to which the supplied notification block will be submitted when
- * the observed object completes.
- *
- * @param notification_block
- * The block to submit when the observed object completes.
- */
-DISPATCH_UNAVAILABLE
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_notify(void *object, dispatch_object_t queue,
- dispatch_block_t notification_block);
-#if __has_extension(c_generic_selections)
-#define dispatch_notify(object, queue, notification_block) \
- _Generic((object), \
- dispatch_block_t:dispatch_block_notify, \
- dispatch_group_t:dispatch_group_notify \
- )((object),(queue), (notification_block))
-#endif
-
-/*!
- * @function dispatch_cancel
- *
- * @abstract
- * Cancel the specified object.
- *
- * @discussion
- * Type-generic macro that maps to dispatch_block_cancel or
- * dispatch_source_cancel, depending on the type of the first argument.
- * See documentation for these functions for more details.
- * This function is unavailable for any other object type.
- *
- * @param object
- * The object to cancel.
- * The result of passing NULL in this parameter is undefined.
- */
-DISPATCH_UNAVAILABLE
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_cancel(void *object);
-#if __has_extension(c_generic_selections)
-#define dispatch_cancel(object) \
- _Generic((object), \
- dispatch_block_t:dispatch_block_cancel, \
- dispatch_source_t:dispatch_source_cancel \
- )((object))
-#endif
-
-/*!
- * @function dispatch_testcancel
- *
- * @abstract
- * Test whether the specified object has been canceled
- *
- * @discussion
- * Type-generic macro that maps to dispatch_block_testcancel or
- * dispatch_source_testcancel, depending on the type of the first argument.
- * See documentation for these functions for more details.
- * This function is unavailable for any other object type.
- *
- * @param object
- * The object to test.
- * The result of passing NULL in this parameter is undefined.
- *
- * @result
- * Non-zero if canceled and zero if not canceled.
- */
-DISPATCH_UNAVAILABLE
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
-DISPATCH_NOTHROW
-long
-dispatch_testcancel(void *object);
-#if __has_extension(c_generic_selections)
-#define dispatch_testcancel(object) \
- _Generic((object), \
- dispatch_block_t:dispatch_block_testcancel, \
- dispatch_source_t:dispatch_source_testcancel \
- )((object))
-#endif
-#endif // __BLOCKS__
-
-/*!
- * @function dispatch_debug
- *
- * @abstract
- * Programmatically log debug information about a dispatch object.
- *
- * @discussion
- * Programmatically log debug information about a dispatch object. By default,
- * the log output is sent to syslog at notice level. In the debug version of
- * the library, the log output is sent to a file in /var/tmp.
- * The log output destination can be configured via the LIBDISPATCH_LOG
- * environment variable, valid values are: YES, NO, syslog, stderr, file.
- *
- * This function is deprecated and will be removed in a future release.
- * Objective-C callers may use -debugDescription instead.
- *
- * @param object
- * The object to introspect.
- *
- * @param message
- * The message to log above and beyond the introspection.
- */
-API_DEPRECATED("unsupported interface", macos(10.6,10.9), ios(4.0,6.0))
-DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW DISPATCH_COLD
-__attribute__((__format__(printf,2,3)))
-void
-dispatch_debug(dispatch_object_t object, const char *message, ...);
-
-API_DEPRECATED("unsupported interface", macos(10.6,10.9), ios(4.0,6.0))
-DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW DISPATCH_COLD
-__attribute__((__format__(printf,2,0)))
-void
-dispatch_debugv(dispatch_object_t object, const char *message, va_list ap);
-
-__END_DECLS
-
-DISPATCH_ASSUME_NONNULL_END
-
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/dispatch/queue.h b/lib/libc/include/x86_64-macos-gnu/dispatch/queue.h
deleted file mode 100644
index f644b0266d..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/dispatch/queue.h
+++ /dev/null
@@ -1,1674 +0,0 @@
-/*
- * Copyright (c) 2008-2014 Apple Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-
-#ifndef __DISPATCH_QUEUE__
-#define __DISPATCH_QUEUE__
-
-#ifndef __DISPATCH_INDIRECT__
-#error "Please #include instead of this file directly."
-#include // for HeaderDoc
-#endif
-
-DISPATCH_ASSUME_NONNULL_BEGIN
-
-/*!
- * @header
- *
- * Dispatch is an abstract model for expressing concurrency via simple but
- * powerful API.
- *
- * At the core, dispatch provides serial FIFO queues to which blocks may be
- * submitted. Blocks submitted to these dispatch queues are invoked on a pool
- * of threads fully managed by the system. No guarantee is made regarding
- * which thread a block will be invoked on; however, it is guaranteed that only
- * one block submitted to the FIFO dispatch queue will be invoked at a time.
- *
- * When multiple queues have blocks to be processed, the system is free to
- * allocate additional threads to invoke the blocks concurrently. When the
- * queues become empty, these threads are automatically released.
- */
-
-/*!
- * @typedef dispatch_queue_t
- *
- * @abstract
- * Dispatch queues invoke workitems submitted to them.
- *
- * @discussion
- * Dispatch queues come in many flavors, the most common one being the dispatch
- * serial queue (See dispatch_queue_serial_t).
- *
- * The system manages a pool of threads which process dispatch queues and invoke
- * workitems submitted to them.
- *
- * Conceptually a dispatch queue may have its own thread of execution, and
- * interaction between queues is highly asynchronous.
- *
- * Dispatch queues are reference counted via calls to dispatch_retain() and
- * dispatch_release(). Pending workitems submitted to a queue also hold a
- * reference to the queue until they have finished. Once all references to a
- * queue have been released, the queue will be deallocated by the system.
- */
-DISPATCH_DECL(dispatch_queue);
-
-/*!
- * @typedef dispatch_queue_global_t
- *
- * @abstract
- * Dispatch global concurrent queues are an abstraction around the system thread
- * pool which invokes workitems that are submitted to dispatch queues.
- *
- * @discussion
- * Dispatch global concurrent queues provide buckets of priorities on top of the
- * thread pool the system manages. The system will decide how many threads
- * to allocate to this pool depending on demand and system load. In particular,
- * the system tries to maintain a good level of concurrency for this resource,
- * and will create new threads when too many existing worker threads block in
- * system calls.
- *
- * The global concurrent queues are a shared resource and as such it is the
- * responsiblity of every user of this resource to not submit an unbounded
- * amount of work to this pool, especially work that may block, as this can
- * cause the system to spawn very large numbers of threads (aka. thread
- * explosion).
- *
- * Work items submitted to the global concurrent queues have no ordering
- * guarantee with respect to the order of submission, and workitems submitted
- * to these queues may be invoked concurrently.
- *
- * Dispatch global concurrent queues are well-known global objects that are
- * returned by dispatch_get_global_queue(). These objects cannot be modified.
- * Calls to dispatch_suspend(), dispatch_resume(), dispatch_set_context(), etc.,
- * will have no effect when used with queues of this type.
- */
-DISPATCH_DECL_SUBCLASS(dispatch_queue_global, dispatch_queue);
-
-/*!
- * @typedef dispatch_queue_serial_t
- *
- * @abstract
- * Dispatch serial queues invoke workitems submitted to them serially in FIFO
- * order.
- *
- * @discussion
- * Dispatch serial queues are lightweight objects to which workitems may be
- * submitted to be invoked in FIFO order. A serial queue will only invoke one
- * workitem at a time, but independent serial queues may each invoke their work
- * items concurrently with respect to each other.
- *
- * Serial queues can target each other (See dispatch_set_target_queue()). The
- * serial queue at the bottom of a queue hierarchy provides an exclusion
- * context: at most one workitem submitted to any of the queues in such
- * a hiearchy will run at any given time.
- *
- * Such hierarchies provide a natural construct to organize an application
- * subsystem around.
- *
- * Serial queues are created by passing a dispatch queue attribute derived from
- * DISPATCH_QUEUE_SERIAL to dispatch_queue_create_with_target().
- */
-DISPATCH_DECL_SUBCLASS(dispatch_queue_serial, dispatch_queue);
-
-/*!
- * @typedef dispatch_queue_main_t
- *
- * @abstract
- * The type of the default queue that is bound to the main thread.
- *
- * @discussion
- * The main queue is a serial queue (See dispatch_queue_serial_t) which is bound
- * to the main thread of an application.
- *
- * In order to invoke workitems submitted to the main queue, the application
- * must call dispatch_main(), NSApplicationMain(), or use a CFRunLoop on the
- * main thread.
- *
- * The main queue is a well known global object that is made automatically on
- * behalf of the main thread during process initialization and is returned by
- * dispatch_get_main_queue(). This object cannot be modified. Calls to
- * dispatch_suspend(), dispatch_resume(), dispatch_set_context(), etc., will
- * have no effect when used on the main queue.
- */
-DISPATCH_DECL_SUBCLASS(dispatch_queue_main, dispatch_queue_serial);
-
-/*!
- * @typedef dispatch_queue_concurrent_t
- *
- * @abstract
- * Dispatch concurrent queues invoke workitems submitted to them concurrently,
- * and admit a notion of barrier workitems.
- *
- * @discussion
- * Dispatch concurrent queues are lightweight objects to which regular and
- * barrier workitems may be submited. Barrier workitems are invoked in
- * exclusion of any other kind of workitem in FIFO order.
- *
- * Regular workitems can be invoked concurrently for the same concurrent queue,
- * in any order. However, regular workitems will not be invoked before any
- * barrier workitem submited ahead of them has been invoked.
- *
- * In other words, if a serial queue is equivalent to a mutex in the Dispatch
- * world, a concurrent queue is equivalent to a reader-writer lock, where
- * regular items are readers and barriers are writers.
- *
- * Concurrent queues are created by passing a dispatch queue attribute derived
- * from DISPATCH_QUEUE_CONCURRENT to dispatch_queue_create_with_target().
- *
- * Caveat:
- * Dispatch concurrent queues at this time do not implement priority inversion
- * avoidance when lower priority regular workitems (readers) are being invoked
- * and are preventing a higher priority barrier (writer) from being invoked.
- */
-DISPATCH_DECL_SUBCLASS(dispatch_queue_concurrent, dispatch_queue);
-
-__BEGIN_DECLS
-
-/*!
- * @function dispatch_async
- *
- * @abstract
- * Submits a block for asynchronous execution on a dispatch queue.
- *
- * @discussion
- * The dispatch_async() function is the fundamental mechanism for submitting
- * blocks to a dispatch queue.
- *
- * Calls to dispatch_async() always return immediately after the block has
- * been submitted, and never wait for the block to be invoked.
- *
- * The target queue determines whether the block will be invoked serially or
- * concurrently with respect to other blocks submitted to that same queue.
- * Serial queues are processed concurrently with respect to each other.
- *
- * @param queue
- * The target dispatch queue to which the block is submitted.
- * The system will hold a reference on the target queue until the block
- * has finished.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param block
- * The block to submit to the target dispatch queue. This function performs
- * Block_copy() and Block_release() on behalf of callers.
- * The result of passing NULL in this parameter is undefined.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
-#endif
-
-/*!
- * @function dispatch_async_f
- *
- * @abstract
- * Submits a function for asynchronous execution on a dispatch queue.
- *
- * @discussion
- * See dispatch_async() for details.
- *
- * @param queue
- * The target dispatch queue to which the function is submitted.
- * The system will hold a reference on the target queue until the function
- * has returned.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the target queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_async_f().
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
-void
-dispatch_async_f(dispatch_queue_t queue,
- void *_Nullable context, dispatch_function_t work);
-
-/*!
- * @function dispatch_sync
- *
- * @abstract
- * Submits a block for synchronous execution on a dispatch queue.
- *
- * @discussion
- * Submits a workitem to a dispatch queue like dispatch_async(), however
- * dispatch_sync() will not return until the workitem has finished.
- *
- * Work items submitted to a queue with dispatch_sync() do not observe certain
- * queue attributes of that queue when invoked (such as autorelease frequency
- * and QOS class).
- *
- * Calls to dispatch_sync() targeting the current queue will result
- * in dead-lock. Use of dispatch_sync() is also subject to the same
- * multi-party dead-lock problems that may result from the use of a mutex.
- * Use of dispatch_async() is preferred.
- *
- * Unlike dispatch_async(), no retain is performed on the target queue. Because
- * calls to this function are synchronous, the dispatch_sync() "borrows" the
- * reference of the caller.
- *
- * As an optimization, dispatch_sync() invokes the workitem on the thread which
- * submitted the workitem, except when the passed queue is the main queue or
- * a queue targetting it (See dispatch_queue_main_t,
- * dispatch_set_target_queue()).
- *
- * @param queue
- * The target dispatch queue to which the block is submitted.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param block
- * The block to be invoked on the target dispatch queue.
- * The result of passing NULL in this parameter is undefined.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
-#endif
-
-/*!
- * @function dispatch_sync_f
- *
- * @abstract
- * Submits a function for synchronous execution on a dispatch queue.
- *
- * @discussion
- * See dispatch_sync() for details.
- *
- * @param queue
- * The target dispatch queue to which the function is submitted.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the target queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_sync_f().
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
-void
-dispatch_sync_f(dispatch_queue_t queue,
- void *_Nullable context, dispatch_function_t work);
-
-/*!
- * @function dispatch_async_and_wait
- *
- * @abstract
- * Submits a block for synchronous execution on a dispatch queue.
- *
- * @discussion
- * Submits a workitem to a dispatch queue like dispatch_async(), however
- * dispatch_async_and_wait() will not return until the workitem has finished.
- *
- * Like functions of the dispatch_sync family, dispatch_async_and_wait() is
- * subject to dead-lock (See dispatch_sync() for details).
- *
- * However, dispatch_async_and_wait() differs from functions of the
- * dispatch_sync family in two fundamental ways: how it respects queue
- * attributes and how it chooses the execution context invoking the workitem.
- *
- * Differences with dispatch_sync()
- *
- * Work items submitted to a queue with dispatch_async_and_wait() observe all
- * queue attributes of that queue when invoked (inluding autorelease frequency
- * or QOS class).
- *
- * When the runtime has brought up a thread to invoke the asynchronous workitems
- * already submitted to the specified queue, that servicing thread will also be
- * used to execute synchronous work submitted to the queue with
- * dispatch_async_and_wait().
- *
- * However, if the runtime has not brought up a thread to service the specified
- * queue (because it has no workitems enqueued, or only synchronous workitems),
- * then dispatch_async_and_wait() will invoke the workitem on the calling thread,
- * similar to the behaviour of functions in the dispatch_sync family.
- *
- * As an exception, if the queue the work is submitted to doesn't target
- * a global concurrent queue (for example because it targets the main queue),
- * then the workitem will never be invoked by the thread calling
- * dispatch_async_and_wait().
- *
- * In other words, dispatch_async_and_wait() is similar to submitting
- * a dispatch_block_create()d workitem to a queue and then waiting on it, as
- * shown in the code example below. However, dispatch_async_and_wait() is
- * significantly more efficient when a new thread is not required to execute
- * the workitem (as it will use the stack of the submitting thread instead of
- * requiring heap allocations).
- *
- *
- * dispatch_block_t b = dispatch_block_create(0, block);
- * dispatch_async(queue, b);
- * dispatch_block_wait(b, DISPATCH_TIME_FOREVER);
- * Block_release(b);
- *
- *
- * @param queue
- * The target dispatch queue to which the block is submitted.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param block
- * The block to be invoked on the target dispatch queue.
- * The result of passing NULL in this parameter is undefined.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_async_and_wait(dispatch_queue_t queue,
- DISPATCH_NOESCAPE dispatch_block_t block);
-#endif
-
-/*!
- * @function dispatch_async_and_wait_f
- *
- * @abstract
- * Submits a function for synchronous execution on a dispatch queue.
- *
- * @discussion
- * See dispatch_async_and_wait() for details.
- *
- * @param queue
- * The target dispatch queue to which the function is submitted.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the target queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_async_and_wait_f().
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
-void
-dispatch_async_and_wait_f(dispatch_queue_t queue,
- void *_Nullable context, dispatch_function_t work);
-
-
-#if defined(__APPLE__) && \
- (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
- __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0) || \
- (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
- __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9)
-#define DISPATCH_APPLY_AUTO_AVAILABLE 0
-#define DISPATCH_APPLY_QUEUE_ARG_NULLABILITY _Nonnull
-#else
-#define DISPATCH_APPLY_AUTO_AVAILABLE 1
-#define DISPATCH_APPLY_QUEUE_ARG_NULLABILITY _Nullable
-#endif
-
-/*!
- * @constant DISPATCH_APPLY_AUTO
- *
- * @abstract
- * Constant to pass to dispatch_apply() or dispatch_apply_f() to request that
- * the system automatically use worker threads that match the configuration of
- * the current thread as closely as possible.
- *
- * @discussion
- * When submitting a block for parallel invocation, passing this constant as the
- * queue argument will automatically use the global concurrent queue that
- * matches the Quality of Service of the caller most closely.
- *
- * No assumptions should be made about which global concurrent queue will
- * actually be used.
- *
- * Using this constant deploys backward to macOS 10.9, iOS 7.0 and any tvOS or
- * watchOS version.
- */
-#if DISPATCH_APPLY_AUTO_AVAILABLE
-#define DISPATCH_APPLY_AUTO ((dispatch_queue_t _Nonnull)0)
-#endif
-
-/*!
- * @function dispatch_apply
- *
- * @abstract
- * Submits a block to a dispatch queue for parallel invocation.
- *
- * @discussion
- * Submits a block to a dispatch queue for parallel invocation. This function
- * waits for the task block to complete before returning. If the specified queue
- * is concurrent, the block may be invoked concurrently, and it must therefore
- * be reentrant safe.
- *
- * Each invocation of the block will be passed the current index of iteration.
- *
- * @param iterations
- * The number of iterations to perform.
- *
- * @param queue
- * The dispatch queue to which the block is submitted.
- * The preferred value to pass is DISPATCH_APPLY_AUTO to automatically use
- * a queue appropriate for the calling thread.
- *
- * @param block
- * The block to be invoked the specified number of iterations.
- * The result of passing NULL in this parameter is undefined.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL3 DISPATCH_NOTHROW
-void
-dispatch_apply(size_t iterations,
- dispatch_queue_t DISPATCH_APPLY_QUEUE_ARG_NULLABILITY queue,
- DISPATCH_NOESCAPE void (^block)(size_t));
-#endif
-
-/*!
- * @function dispatch_apply_f
- *
- * @abstract
- * Submits a function to a dispatch queue for parallel invocation.
- *
- * @discussion
- * See dispatch_apply() for details.
- *
- * @param iterations
- * The number of iterations to perform.
- *
- * @param queue
- * The dispatch queue to which the function is submitted.
- * The preferred value to pass is DISPATCH_APPLY_AUTO to automatically use
- * a queue appropriate for the calling thread.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the specified queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_apply_f(). The second parameter passed to this function is the
- * current index of iteration.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL4 DISPATCH_NOTHROW
-void
-dispatch_apply_f(size_t iterations,
- dispatch_queue_t DISPATCH_APPLY_QUEUE_ARG_NULLABILITY queue,
- void *_Nullable context, void (*work)(void *_Nullable, size_t));
-
-/*!
- * @function dispatch_get_current_queue
- *
- * @abstract
- * Returns the queue on which the currently executing block is running.
- *
- * @discussion
- * Returns the queue on which the currently executing block is running.
- *
- * When dispatch_get_current_queue() is called outside of the context of a
- * submitted block, it will return the default concurrent queue.
- *
- * Recommended for debugging and logging purposes only:
- * The code must not make any assumptions about the queue returned, unless it
- * is one of the global queues or a queue the code has itself created.
- * The code must not assume that synchronous execution onto a queue is safe
- * from deadlock if that queue is not the one returned by
- * dispatch_get_current_queue().
- *
- * When dispatch_get_current_queue() is called on the main thread, it may
- * or may not return the same value as dispatch_get_main_queue(). Comparing
- * the two is not a valid way to test whether code is executing on the
- * main thread (see dispatch_assert_queue() and dispatch_assert_queue_not()).
- *
- * This function is deprecated and will be removed in a future release.
- *
- * @result
- * Returns the current queue.
- */
-API_DEPRECATED("unsupported interface", macos(10.6,10.9), ios(4.0,6.0))
-DISPATCH_EXPORT DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW
-dispatch_queue_t
-dispatch_get_current_queue(void);
-
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT
-struct dispatch_queue_s _dispatch_main_q;
-
-/*!
- * @function dispatch_get_main_queue
- *
- * @abstract
- * Returns the default queue that is bound to the main thread.
- *
- * @discussion
- * In order to invoke blocks submitted to the main queue, the application must
- * call dispatch_main(), NSApplicationMain(), or use a CFRunLoop on the main
- * thread.
- *
- * The main queue is meant to be used in application context to interact with
- * the main thread and the main runloop.
- *
- * Because the main queue doesn't behave entirely like a regular serial queue,
- * it may have unwanted side-effects when used in processes that are not UI apps
- * (daemons). For such processes, the main queue should be avoided.
- *
- * @see dispatch_queue_main_t
- *
- * @result
- * Returns the main queue. This queue is created automatically on behalf of
- * the main thread before main() is called.
- */
-DISPATCH_INLINE DISPATCH_ALWAYS_INLINE DISPATCH_CONST DISPATCH_NOTHROW
-dispatch_queue_main_t
-dispatch_get_main_queue(void)
-{
- return DISPATCH_GLOBAL_OBJECT(dispatch_queue_main_t, _dispatch_main_q);
-}
-
-/*!
- * @typedef dispatch_queue_priority_t
- * Type of dispatch_queue_priority
- *
- * @constant DISPATCH_QUEUE_PRIORITY_HIGH
- * Items dispatched to the queue will run at high priority,
- * i.e. the queue will be scheduled for execution before
- * any default priority or low priority queue.
- *
- * @constant DISPATCH_QUEUE_PRIORITY_DEFAULT
- * Items dispatched to the queue will run at the default
- * priority, i.e. the queue will be scheduled for execution
- * after all high priority queues have been scheduled, but
- * before any low priority queues have been scheduled.
- *
- * @constant DISPATCH_QUEUE_PRIORITY_LOW
- * Items dispatched to the queue will run at low priority,
- * i.e. the queue will be scheduled for execution after all
- * default priority and high priority queues have been
- * scheduled.
- *
- * @constant DISPATCH_QUEUE_PRIORITY_BACKGROUND
- * Items dispatched to the queue will run at background priority, i.e. the queue
- * will be scheduled for execution after all higher priority queues have been
- * scheduled and the system will run items on this queue on a thread with
- * background status as per setpriority(2) (i.e. disk I/O is throttled and the
- * thread's scheduling priority is set to lowest value).
- */
-#define DISPATCH_QUEUE_PRIORITY_HIGH 2
-#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
-#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
-#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
-
-typedef long dispatch_queue_priority_t;
-
-/*!
- * @function dispatch_get_global_queue
- *
- * @abstract
- * Returns a well-known global concurrent queue of a given quality of service
- * class.
- *
- * @discussion
- * See dispatch_queue_global_t.
- *
- * @param identifier
- * A quality of service class defined in qos_class_t or a priority defined in
- * dispatch_queue_priority_t.
- *
- * It is recommended to use quality of service class values to identify the
- * well-known global concurrent queues:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- *
- * The global concurrent queues may still be identified by their priority,
- * which map to the following QOS classes:
- * - DISPATCH_QUEUE_PRIORITY_HIGH: QOS_CLASS_USER_INITIATED
- * - DISPATCH_QUEUE_PRIORITY_DEFAULT: QOS_CLASS_DEFAULT
- * - DISPATCH_QUEUE_PRIORITY_LOW: QOS_CLASS_UTILITY
- * - DISPATCH_QUEUE_PRIORITY_BACKGROUND: QOS_CLASS_BACKGROUND
- *
- * @param flags
- * Reserved for future use. Passing any value other than zero may result in
- * a NULL return value.
- *
- * @result
- * Returns the requested global queue or NULL if the requested global queue
- * does not exist.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_CONST DISPATCH_WARN_RESULT DISPATCH_NOTHROW
-dispatch_queue_global_t
-dispatch_get_global_queue(long identifier, unsigned long flags);
-
-/*!
- * @typedef dispatch_queue_attr_t
- *
- * @abstract
- * Attribute for dispatch queues.
- */
-DISPATCH_DECL(dispatch_queue_attr);
-
-/*!
- * @const DISPATCH_QUEUE_SERIAL
- *
- * @discussion
- * An attribute that can be used to create a dispatch queue that invokes blocks
- * serially in FIFO order.
- *
- * See dispatch_queue_serial_t.
- */
-#define DISPATCH_QUEUE_SERIAL NULL
-
-/*!
- * @const DISPATCH_QUEUE_SERIAL_INACTIVE
- *
- * @discussion
- * An attribute that can be used to create a dispatch queue that invokes blocks
- * serially in FIFO order, and that is initially inactive.
- *
- * See dispatch_queue_attr_make_initially_inactive().
- */
-#define DISPATCH_QUEUE_SERIAL_INACTIVE \
- dispatch_queue_attr_make_initially_inactive(DISPATCH_QUEUE_SERIAL)
-
-/*!
- * @const DISPATCH_QUEUE_CONCURRENT
- *
- * @discussion
- * An attribute that can be used to create a dispatch queue that may invoke
- * blocks concurrently and supports barrier blocks submitted with the dispatch
- * barrier API.
- *
- * See dispatch_queue_concurrent_t.
- */
-#define DISPATCH_QUEUE_CONCURRENT \
- DISPATCH_GLOBAL_OBJECT(dispatch_queue_attr_t, \
- _dispatch_queue_attr_concurrent)
-API_AVAILABLE(macos(10.7), ios(4.3))
-DISPATCH_EXPORT
-struct dispatch_queue_attr_s _dispatch_queue_attr_concurrent;
-
-/*!
- * @const DISPATCH_QUEUE_CONCURRENT_INACTIVE
- *
- * @discussion
- * An attribute that can be used to create a dispatch queue that may invoke
- * blocks concurrently and supports barrier blocks submitted with the dispatch
- * barrier API, and that is initially inactive.
- *
- * See dispatch_queue_attr_make_initially_inactive().
- */
-#define DISPATCH_QUEUE_CONCURRENT_INACTIVE \
- dispatch_queue_attr_make_initially_inactive(DISPATCH_QUEUE_CONCURRENT)
-
-/*!
- * @function dispatch_queue_attr_make_initially_inactive
- *
- * @abstract
- * Returns an attribute value which may be provided to dispatch_queue_create()
- * or dispatch_queue_create_with_target(), in order to make the created queue
- * initially inactive.
- *
- * @discussion
- * Dispatch queues may be created in an inactive state. Queues in this state
- * have to be activated before any blocks associated with them will be invoked.
- *
- * A queue in inactive state cannot be deallocated, dispatch_activate() must be
- * called before the last reference to a queue created with this attribute is
- * released.
- *
- * The target queue of a queue in inactive state can be changed using
- * dispatch_set_target_queue(). Change of target queue is no longer permitted
- * once an initially inactive queue has been activated.
- *
- * @param attr
- * A queue attribute value to be combined with the initially inactive attribute.
- *
- * @return
- * Returns an attribute value which may be provided to dispatch_queue_create()
- * and dispatch_queue_create_with_target().
- * The new value combines the attributes specified by the 'attr' parameter with
- * the initially inactive attribute.
- */
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_PURE DISPATCH_NOTHROW
-dispatch_queue_attr_t
-dispatch_queue_attr_make_initially_inactive(
- dispatch_queue_attr_t _Nullable attr);
-
-/*!
- * @const DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL
- *
- * @discussion
- * A dispatch queue created with this attribute invokes blocks serially in FIFO
- * order, and surrounds execution of any block submitted asynchronously to it
- * with the equivalent of a individual Objective-C @autoreleasepool
- * scope.
- *
- * See dispatch_queue_attr_make_with_autorelease_frequency().
- */
-#define DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL \
- dispatch_queue_attr_make_with_autorelease_frequency(\
- DISPATCH_QUEUE_SERIAL, DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM)
-
-/*!
- * @const DISPATCH_QUEUE_CONCURRENT_WITH_AUTORELEASE_POOL
- *
- * @discussion
- * A dispatch queue created with this attribute may invokes blocks concurrently
- * and supports barrier blocks submitted with the dispatch barrier API. It also
- * surrounds execution of any block submitted asynchronously to it with the
- * equivalent of a individual Objective-C @autoreleasepool
- *
- * See dispatch_queue_attr_make_with_autorelease_frequency().
- */
-#define DISPATCH_QUEUE_CONCURRENT_WITH_AUTORELEASE_POOL \
- dispatch_queue_attr_make_with_autorelease_frequency(\
- DISPATCH_QUEUE_CONCURRENT, DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM)
-
-/*!
- * @typedef dispatch_autorelease_frequency_t
- * Values to pass to the dispatch_queue_attr_make_with_autorelease_frequency()
- * function.
- *
- * @const DISPATCH_AUTORELEASE_FREQUENCY_INHERIT
- * Dispatch queues with this autorelease frequency inherit the behavior from
- * their target queue. This is the default behavior for manually created queues.
- *
- * @const DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM
- * Dispatch queues with this autorelease frequency push and pop an autorelease
- * pool around the execution of every block that was submitted to it
- * asynchronously.
- * @see dispatch_queue_attr_make_with_autorelease_frequency().
- *
- * @const DISPATCH_AUTORELEASE_FREQUENCY_NEVER
- * Dispatch queues with this autorelease frequency never set up an individual
- * autorelease pool around the execution of a block that is submitted to it
- * asynchronously. This is the behavior of the global concurrent queues.
- */
-DISPATCH_ENUM(dispatch_autorelease_frequency, unsigned long,
- DISPATCH_AUTORELEASE_FREQUENCY_INHERIT DISPATCH_ENUM_API_AVAILABLE(
- macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) = 0,
- DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM DISPATCH_ENUM_API_AVAILABLE(
- macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) = 1,
- DISPATCH_AUTORELEASE_FREQUENCY_NEVER DISPATCH_ENUM_API_AVAILABLE(
- macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) = 2,
-);
-
-/*!
- * @function dispatch_queue_attr_make_with_autorelease_frequency
- *
- * @abstract
- * Returns a dispatch queue attribute value with the autorelease frequency
- * set to the specified value.
- *
- * @discussion
- * When a queue uses the per-workitem autorelease frequency (either directly
- * or inherithed from its target queue), any block submitted asynchronously to
- * this queue (via dispatch_async(), dispatch_barrier_async(),
- * dispatch_group_notify(), etc...) is executed as if surrounded by a individual
- * Objective-C @autoreleasepool scope.
- *
- * Autorelease frequency has no effect on blocks that are submitted
- * synchronously to a queue (via dispatch_sync(), dispatch_barrier_sync()).
- *
- * The global concurrent queues have the DISPATCH_AUTORELEASE_FREQUENCY_NEVER
- * behavior. Manually created dispatch queues use
- * DISPATCH_AUTORELEASE_FREQUENCY_INHERIT by default.
- *
- * Queues created with this attribute cannot change target queues after having
- * been activated. See dispatch_set_target_queue() and dispatch_activate().
- *
- * @param attr
- * A queue attribute value to be combined with the specified autorelease
- * frequency or NULL.
- *
- * @param frequency
- * The requested autorelease frequency.
- *
- * @return
- * Returns an attribute value which may be provided to dispatch_queue_create()
- * or NULL if an invalid autorelease frequency was requested.
- * This new value combines the attributes specified by the 'attr' parameter and
- * the chosen autorelease frequency.
- */
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_PURE DISPATCH_NOTHROW
-dispatch_queue_attr_t
-dispatch_queue_attr_make_with_autorelease_frequency(
- dispatch_queue_attr_t _Nullable attr,
- dispatch_autorelease_frequency_t frequency);
-
-/*!
- * @function dispatch_queue_attr_make_with_qos_class
- *
- * @abstract
- * Returns an attribute value which may be provided to dispatch_queue_create()
- * or dispatch_queue_create_with_target(), in order to assign a QOS class and
- * relative priority to the queue.
- *
- * @discussion
- * When specified in this manner, the QOS class and relative priority take
- * precedence over those inherited from the dispatch queue's target queue (if
- * any) as long that does not result in a lower QOS class and relative priority.
- *
- * The global queue priorities map to the following QOS classes:
- * - DISPATCH_QUEUE_PRIORITY_HIGH: QOS_CLASS_USER_INITIATED
- * - DISPATCH_QUEUE_PRIORITY_DEFAULT: QOS_CLASS_DEFAULT
- * - DISPATCH_QUEUE_PRIORITY_LOW: QOS_CLASS_UTILITY
- * - DISPATCH_QUEUE_PRIORITY_BACKGROUND: QOS_CLASS_BACKGROUND
- *
- * Example:
- *
- * dispatch_queue_t queue;
- * dispatch_queue_attr_t attr;
- * attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
- * QOS_CLASS_UTILITY, 0);
- * queue = dispatch_queue_create("com.example.myqueue", attr);
- *
- *
- * The QOS class and relative priority set this way on a queue have no effect on
- * blocks that are submitted synchronously to a queue (via dispatch_sync(),
- * dispatch_barrier_sync()).
- *
- * @param attr
- * A queue attribute value to be combined with the QOS class, or NULL.
- *
- * @param qos_class
- * A QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * Passing any other value results in NULL being returned.
- *
- * @param relative_priority
- * A relative priority within the QOS class. This value is a negative
- * offset from the maximum supported scheduler priority for the given class.
- * Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
- * results in NULL being returned.
- *
- * @return
- * Returns an attribute value which may be provided to dispatch_queue_create()
- * and dispatch_queue_create_with_target(), or NULL if an invalid QOS class was
- * requested.
- * The new value combines the attributes specified by the 'attr' parameter and
- * the new QOS class and relative priority.
- */
-API_AVAILABLE(macos(10.10), ios(8.0))
-DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_PURE DISPATCH_NOTHROW
-dispatch_queue_attr_t
-dispatch_queue_attr_make_with_qos_class(dispatch_queue_attr_t _Nullable attr,
- dispatch_qos_class_t qos_class, int relative_priority);
-
-/*!
- * @const DISPATCH_TARGET_QUEUE_DEFAULT
- * @discussion Constant to pass to the dispatch_queue_create_with_target(),
- * dispatch_set_target_queue() and dispatch_source_create() functions to
- * indicate that the default target queue for the object type in question
- * should be used.
- */
-#define DISPATCH_TARGET_QUEUE_DEFAULT NULL
-
-/*!
- * @function dispatch_queue_create_with_target
- *
- * @abstract
- * Creates a new dispatch queue with a specified target queue.
- *
- * @discussion
- * Dispatch queues created with the DISPATCH_QUEUE_SERIAL or a NULL attribute
- * invoke blocks serially in FIFO order.
- *
- * Dispatch queues created with the DISPATCH_QUEUE_CONCURRENT attribute may
- * invoke blocks concurrently (similarly to the global concurrent queues, but
- * potentially with more overhead), and support barrier blocks submitted with
- * the dispatch barrier API, which e.g. enables the implementation of efficient
- * reader-writer schemes.
- *
- * When a dispatch queue is no longer needed, it should be released with
- * dispatch_release(). Note that any pending blocks submitted asynchronously to
- * a queue will hold a reference to that queue. Therefore a queue will not be
- * deallocated until all pending blocks have finished.
- *
- * When using a dispatch queue attribute @a attr specifying a QoS class (derived
- * from the result of dispatch_queue_attr_make_with_qos_class()), passing the
- * result of dispatch_get_global_queue() in @a target will ignore the QoS class
- * of that global queue and will use the global queue with the QoS class
- * specified by attr instead.
- *
- * Queues created with dispatch_queue_create_with_target() cannot have their
- * target queue changed, unless created inactive (See
- * dispatch_queue_attr_make_initially_inactive()), in which case the target
- * queue can be changed until the newly created queue is activated with
- * dispatch_activate().
- *
- * @param label
- * A string label to attach to the queue.
- * This parameter is optional and may be NULL.
- *
- * @param attr
- * A predefined attribute such as DISPATCH_QUEUE_SERIAL,
- * DISPATCH_QUEUE_CONCURRENT, or the result of a call to
- * a dispatch_queue_attr_make_with_* function.
- *
- * @param target
- * The target queue for the newly created queue. The target queue is retained.
- * If this parameter is DISPATCH_TARGET_QUEUE_DEFAULT, sets the queue's target
- * queue to the default target queue for the given queue type.
- *
- * @result
- * The newly created dispatch queue.
- */
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
-DISPATCH_NOTHROW
-dispatch_queue_t
-dispatch_queue_create_with_target(const char *_Nullable label,
- dispatch_queue_attr_t _Nullable attr, dispatch_queue_t _Nullable target)
- DISPATCH_ALIAS_V2(dispatch_queue_create_with_target);
-
-/*!
- * @function dispatch_queue_create
- *
- * @abstract
- * Creates a new dispatch queue to which blocks may be submitted.
- *
- * @discussion
- * Dispatch queues created with the DISPATCH_QUEUE_SERIAL or a NULL attribute
- * invoke blocks serially in FIFO order.
- *
- * Dispatch queues created with the DISPATCH_QUEUE_CONCURRENT attribute may
- * invoke blocks concurrently (similarly to the global concurrent queues, but
- * potentially with more overhead), and support barrier blocks submitted with
- * the dispatch barrier API, which e.g. enables the implementation of efficient
- * reader-writer schemes.
- *
- * When a dispatch queue is no longer needed, it should be released with
- * dispatch_release(). Note that any pending blocks submitted asynchronously to
- * a queue will hold a reference to that queue. Therefore a queue will not be
- * deallocated until all pending blocks have finished.
- *
- * Passing the result of the dispatch_queue_attr_make_with_qos_class() function
- * to the attr parameter of this function allows a quality of service class and
- * relative priority to be specified for the newly created queue.
- * The quality of service class so specified takes precedence over the quality
- * of service class of the newly created dispatch queue's target queue (if any)
- * as long that does not result in a lower QOS class and relative priority.
- *
- * When no quality of service class is specified, the target queue of a newly
- * created dispatch queue is the default priority global concurrent queue.
- *
- * @param label
- * A string label to attach to the queue.
- * This parameter is optional and may be NULL.
- *
- * @param attr
- * A predefined attribute such as DISPATCH_QUEUE_SERIAL,
- * DISPATCH_QUEUE_CONCURRENT, or the result of a call to
- * a dispatch_queue_attr_make_with_* function.
- *
- * @result
- * The newly created dispatch queue.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
-DISPATCH_NOTHROW
-dispatch_queue_t
-dispatch_queue_create(const char *_Nullable label,
- dispatch_queue_attr_t _Nullable attr);
-
-/*!
- * @const DISPATCH_CURRENT_QUEUE_LABEL
- * @discussion Constant to pass to the dispatch_queue_get_label() function to
- * retrieve the label of the current queue.
- */
-#define DISPATCH_CURRENT_QUEUE_LABEL NULL
-
-/*!
- * @function dispatch_queue_get_label
- *
- * @abstract
- * Returns the label of the given queue, as specified when the queue was
- * created, or the empty string if a NULL label was specified.
- *
- * Passing DISPATCH_CURRENT_QUEUE_LABEL will return the label of the current
- * queue.
- *
- * @param queue
- * The queue to query, or DISPATCH_CURRENT_QUEUE_LABEL.
- *
- * @result
- * The label of the queue.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW
-const char *
-dispatch_queue_get_label(dispatch_queue_t _Nullable queue);
-
-/*!
- * @function dispatch_queue_get_qos_class
- *
- * @abstract
- * Returns the QOS class and relative priority of the given queue.
- *
- * @discussion
- * If the given queue was created with an attribute value returned from
- * dispatch_queue_attr_make_with_qos_class(), this function returns the QOS
- * class and relative priority specified at that time; for any other attribute
- * value it returns a QOS class of QOS_CLASS_UNSPECIFIED and a relative
- * priority of 0.
- *
- * If the given queue is one of the global queues, this function returns its
- * assigned QOS class value as documented under dispatch_get_global_queue() and
- * a relative priority of 0; in the case of the main queue it returns the QOS
- * value provided by qos_class_main() and a relative priority of 0.
- *
- * @param queue
- * The queue to query.
- *
- * @param relative_priority_ptr
- * A pointer to an int variable to be filled with the relative priority offset
- * within the QOS class, or NULL.
- *
- * @return
- * A QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * - QOS_CLASS_UNSPECIFIED
- */
-API_AVAILABLE(macos(10.10), ios(8.0))
-DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-dispatch_qos_class_t
-dispatch_queue_get_qos_class(dispatch_queue_t queue,
- int *_Nullable relative_priority_ptr);
-
-/*!
- * @function dispatch_set_target_queue
- *
- * @abstract
- * Sets the target queue for the given object.
- *
- * @discussion
- * An object's target queue is responsible for processing the object.
- *
- * When no quality of service class and relative priority is specified for a
- * dispatch queue at the time of creation, a dispatch queue's quality of service
- * class is inherited from its target queue. The dispatch_get_global_queue()
- * function may be used to obtain a target queue of a specific quality of
- * service class, however the use of dispatch_queue_attr_make_with_qos_class()
- * is recommended instead.
- *
- * Blocks submitted to a serial queue whose target queue is another serial
- * queue will not be invoked concurrently with blocks submitted to the target
- * queue or to any other queue with that same target queue.
- *
- * The result of introducing a cycle into the hierarchy of target queues is
- * undefined.
- *
- * A dispatch source's target queue specifies where its event handler and
- * cancellation handler blocks will be submitted.
- *
- * A dispatch I/O channel's target queue specifies where where its I/O
- * operations are executed. If the channel's target queue's priority is set to
- * DISPATCH_QUEUE_PRIORITY_BACKGROUND, then the I/O operations performed by
- * dispatch_io_read() or dispatch_io_write() on that queue will be
- * throttled when there is I/O contention.
- *
- * For all other dispatch object types, the only function of the target queue
- * is to determine where an object's finalizer function is invoked.
- *
- * In general, changing the target queue of an object is an asynchronous
- * operation that doesn't take effect immediately, and doesn't affect blocks
- * already associated with the specified object.
- *
- * However, if an object is inactive at the time dispatch_set_target_queue() is
- * called, then the target queue change takes effect immediately, and will
- * affect blocks already associated with the specified object. After an
- * initially inactive object has been activated, calling
- * dispatch_set_target_queue() results in an assertion and the process being
- * terminated.
- *
- * If a dispatch queue is active and targeted by other dispatch objects,
- * changing its target queue results in undefined behavior.
- *
- * @param object
- * The object to modify.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param queue
- * The new target queue for the object. The queue is retained, and the
- * previous target queue, if any, is released.
- * If queue is DISPATCH_TARGET_QUEUE_DEFAULT, set the object's target queue
- * to the default target queue for the given object type.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NOTHROW
-void
-dispatch_set_target_queue(dispatch_object_t object,
- dispatch_queue_t _Nullable queue);
-
-/*!
- * @function dispatch_main
- *
- * @abstract
- * Execute blocks submitted to the main queue.
- *
- * @discussion
- * This function "parks" the main thread and waits for blocks to be submitted
- * to the main queue. This function never returns.
- *
- * Applications that call NSApplicationMain() or CFRunLoopRun() on the
- * main thread do not need to call dispatch_main().
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NOTHROW DISPATCH_NORETURN
-void
-dispatch_main(void);
-
-/*!
- * @function dispatch_after
- *
- * @abstract
- * Schedule a block for execution on a given queue at a specified time.
- *
- * @discussion
- * Passing DISPATCH_TIME_NOW as the "when" parameter is supported, but not as
- * optimal as calling dispatch_async() instead. Passing DISPATCH_TIME_FOREVER
- * is undefined.
- *
- * @param when
- * A temporal milestone returned by dispatch_time() or dispatch_walltime().
- *
- * @param queue
- * A queue to which the given block will be submitted at the specified time.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param block
- * The block of code to execute.
- * The result of passing NULL in this parameter is undefined.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NONNULL3 DISPATCH_NOTHROW
-void
-dispatch_after(dispatch_time_t when, dispatch_queue_t queue,
- dispatch_block_t block);
-#endif
-
-/*!
- * @function dispatch_after_f
- *
- * @abstract
- * Schedule a function for execution on a given queue at a specified time.
- *
- * @discussion
- * See dispatch_after() for details.
- *
- * @param when
- * A temporal milestone returned by dispatch_time() or dispatch_walltime().
- *
- * @param queue
- * A queue to which the given function will be submitted at the specified time.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the target queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_after_f().
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NONNULL4 DISPATCH_NOTHROW
-void
-dispatch_after_f(dispatch_time_t when, dispatch_queue_t queue,
- void *_Nullable context, dispatch_function_t work);
-
-/*!
- * @functiongroup Dispatch Barrier API
- * The dispatch barrier API is a mechanism for submitting barrier blocks to a
- * dispatch queue, analogous to the dispatch_async()/dispatch_sync() API.
- * It enables the implementation of efficient reader/writer schemes.
- * Barrier blocks only behave specially when submitted to queues created with
- * the DISPATCH_QUEUE_CONCURRENT attribute; on such a queue, a barrier block
- * will not run until all blocks submitted to the queue earlier have completed,
- * and any blocks submitted to the queue after a barrier block will not run
- * until the barrier block has completed.
- * When submitted to a a global queue or to a queue not created with the
- * DISPATCH_QUEUE_CONCURRENT attribute, barrier blocks behave identically to
- * blocks submitted with the dispatch_async()/dispatch_sync() API.
- */
-
-/*!
- * @function dispatch_barrier_async
- *
- * @abstract
- * Submits a barrier block for asynchronous execution on a dispatch queue.
- *
- * @discussion
- * Submits a block to a dispatch queue like dispatch_async(), but marks that
- * block as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT queues).
- *
- * See dispatch_async() for details and "Dispatch Barrier API" for a description
- * of the barrier semantics.
- *
- * @param queue
- * The target dispatch queue to which the block is submitted.
- * The system will hold a reference on the target queue until the block
- * has finished.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param block
- * The block to submit to the target dispatch queue. This function performs
- * Block_copy() and Block_release() on behalf of callers.
- * The result of passing NULL in this parameter is undefined.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.7), ios(4.3))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
-#endif
-
-/*!
- * @function dispatch_barrier_async_f
- *
- * @abstract
- * Submits a barrier function for asynchronous execution on a dispatch queue.
- *
- * @discussion
- * Submits a function to a dispatch queue like dispatch_async_f(), but marks
- * that function as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT
- * queues).
- *
- * See dispatch_async_f() for details and "Dispatch Barrier API" for a
- * description of the barrier semantics.
- *
- * @param queue
- * The target dispatch queue to which the function is submitted.
- * The system will hold a reference on the target queue until the function
- * has returned.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the target queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_barrier_async_f().
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.7), ios(4.3))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
-void
-dispatch_barrier_async_f(dispatch_queue_t queue,
- void *_Nullable context, dispatch_function_t work);
-
-/*!
- * @function dispatch_barrier_sync
- *
- * @abstract
- * Submits a barrier block for synchronous execution on a dispatch queue.
- *
- * @discussion
- * Submits a block to a dispatch queue like dispatch_sync(), but marks that
- * block as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT queues).
- *
- * See dispatch_sync() for details and "Dispatch Barrier API" for a description
- * of the barrier semantics.
- *
- * @param queue
- * The target dispatch queue to which the block is submitted.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param block
- * The block to be invoked on the target dispatch queue.
- * The result of passing NULL in this parameter is undefined.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.7), ios(4.3))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_barrier_sync(dispatch_queue_t queue,
- DISPATCH_NOESCAPE dispatch_block_t block);
-#endif
-
-/*!
- * @function dispatch_barrier_sync_f
- *
- * @abstract
- * Submits a barrier function for synchronous execution on a dispatch queue.
- *
- * @discussion
- * Submits a function to a dispatch queue like dispatch_sync_f(), but marks that
- * fuction as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT queues).
- *
- * See dispatch_sync_f() for details.
- *
- * @param queue
- * The target dispatch queue to which the function is submitted.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the target queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_barrier_sync_f().
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.7), ios(4.3))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
-void
-dispatch_barrier_sync_f(dispatch_queue_t queue,
- void *_Nullable context, dispatch_function_t work);
-
-/*!
- * @function dispatch_barrier_async_and_wait
- *
- * @abstract
- * Submits a block for synchronous execution on a dispatch queue.
- *
- * @discussion
- * Submits a block to a dispatch queue like dispatch_async_and_wait(), but marks
- * that block as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT
- * queues).
- *
- * See "Dispatch Barrier API" for a description of the barrier semantics.
- *
- * @param queue
- * The target dispatch queue to which the block is submitted.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param work
- * The application-defined block to invoke on the target queue.
- * The result of passing NULL in this parameter is undefined.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_barrier_async_and_wait(dispatch_queue_t queue,
- DISPATCH_NOESCAPE dispatch_block_t block);
-#endif
-
-/*!
- * @function dispatch_barrier_async_and_wait_f
- *
- * @abstract
- * Submits a function for synchronous execution on a dispatch queue.
- *
- * @discussion
- * Submits a function to a dispatch queue like dispatch_async_and_wait_f(), but
- * marks that function as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT
- * queues).
- *
- * See "Dispatch Barrier API" for a description of the barrier semantics.
- *
- * @param queue
- * The target dispatch queue to which the function is submitted.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param context
- * The application-defined context parameter to pass to the function.
- *
- * @param work
- * The application-defined function to invoke on the target queue. The first
- * parameter passed to this function is the context provided to
- * dispatch_barrier_async_and_wait_f().
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
-void
-dispatch_barrier_async_and_wait_f(dispatch_queue_t queue,
- void *_Nullable context, dispatch_function_t work);
-
-/*!
- * @functiongroup Dispatch queue-specific contexts
- * This API allows different subsystems to associate context to a shared queue
- * without risk of collision and to retrieve that context from blocks executing
- * on that queue or any of its child queues in the target queue hierarchy.
- */
-
-/*!
- * @function dispatch_queue_set_specific
- *
- * @abstract
- * Associates a subsystem-specific context with a dispatch queue, for a key
- * unique to the subsystem.
- *
- * @discussion
- * The specified destructor will be invoked with the context on the default
- * priority global concurrent queue when a new context is set for the same key,
- * or after all references to the queue have been released.
- *
- * @param queue
- * The dispatch queue to modify.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param key
- * The key to set the context for, typically a pointer to a static variable
- * specific to the subsystem. Keys are only compared as pointers and never
- * dereferenced. Passing a string constant directly is not recommended.
- * The NULL key is reserved and attempts to set a context for it are ignored.
- *
- * @param context
- * The new subsystem-specific context for the object. This may be NULL.
- *
- * @param destructor
- * The destructor function pointer. This may be NULL and is ignored if context
- * is NULL.
- */
-API_AVAILABLE(macos(10.7), ios(5.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-void
-dispatch_queue_set_specific(dispatch_queue_t queue, const void *key,
- void *_Nullable context, dispatch_function_t _Nullable destructor);
-
-/*!
- * @function dispatch_queue_get_specific
- *
- * @abstract
- * Returns the subsystem-specific context associated with a dispatch queue, for
- * a key unique to the subsystem.
- *
- * @discussion
- * Returns the context for the specified key if it has been set on the specified
- * queue.
- *
- * @param queue
- * The dispatch queue to query.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param key
- * The key to get the context for, typically a pointer to a static variable
- * specific to the subsystem. Keys are only compared as pointers and never
- * dereferenced. Passing a string constant directly is not recommended.
- *
- * @result
- * The context for the specified key or NULL if no context was found.
- */
-API_AVAILABLE(macos(10.7), ios(5.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_PURE DISPATCH_WARN_RESULT
-DISPATCH_NOTHROW
-void *_Nullable
-dispatch_queue_get_specific(dispatch_queue_t queue, const void *key);
-
-/*!
- * @function dispatch_get_specific
- *
- * @abstract
- * Returns the current subsystem-specific context for a key unique to the
- * subsystem.
- *
- * @discussion
- * When called from a block executing on a queue, returns the context for the
- * specified key if it has been set on the queue, otherwise returns the result
- * of dispatch_get_specific() executed on the queue's target queue or NULL
- * if the current queue is a global concurrent queue.
- *
- * @param key
- * The key to get the context for, typically a pointer to a static variable
- * specific to the subsystem. Keys are only compared as pointers and never
- * dereferenced. Passing a string constant directly is not recommended.
- *
- * @result
- * The context for the specified key or NULL if no context was found.
- */
-API_AVAILABLE(macos(10.7), ios(5.0))
-DISPATCH_EXPORT DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW
-void *_Nullable
-dispatch_get_specific(const void *key);
-
-/*!
- * @functiongroup Dispatch assertion API
- *
- * This API asserts at runtime that code is executing in (or out of) the context
- * of a given queue. It can be used to check that a block accessing a resource
- * does so from the proper queue protecting the resource. It also can be used
- * to verify that a block that could cause a deadlock if run on a given queue
- * never executes on that queue.
- */
-
-/*!
- * @function dispatch_assert_queue
- *
- * @abstract
- * Verifies that the current block is executing on a given dispatch queue.
- *
- * @discussion
- * Some code expects to be run on a specific dispatch queue. This function
- * verifies that that expectation is true.
- *
- * If the currently executing block was submitted to the specified queue or to
- * any queue targeting it (see dispatch_set_target_queue()), this function
- * returns.
- *
- * If the currently executing block was submitted with a synchronous API
- * (dispatch_sync(), dispatch_barrier_sync(), ...), the context of the
- * submitting block is also evaluated (recursively).
- * If a synchronously submitting block is found that was itself submitted to
- * the specified queue or to any queue targeting it, this function returns.
- *
- * Otherwise this function asserts: it logs an explanation to the system log and
- * terminates the application.
- *
- * Passing the result of dispatch_get_main_queue() to this function verifies
- * that the current block was submitted to the main queue, or to a queue
- * targeting it, or is running on the main thread (in any context).
- *
- * When dispatch_assert_queue() is called outside of the context of a
- * submitted block (for example from the context of a thread created manually
- * with pthread_create()) then this function will also assert and terminate
- * the application.
- *
- * The variant dispatch_assert_queue_debug() is compiled out when the
- * preprocessor macro NDEBUG is defined. (See also assert(3)).
- *
- * @param queue
- * The dispatch queue that the current block is expected to run on.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1
-void
-dispatch_assert_queue(dispatch_queue_t queue)
- DISPATCH_ALIAS_V2(dispatch_assert_queue);
-
-/*!
- * @function dispatch_assert_queue_barrier
- *
- * @abstract
- * Verifies that the current block is executing on a given dispatch queue,
- * and that the block acts as a barrier on that queue.
- *
- * @discussion
- * This behaves exactly like dispatch_assert_queue(), with the additional check
- * that the current block acts as a barrier on the specified queue, which is
- * always true if the specified queue is serial (see DISPATCH_BLOCK_BARRIER or
- * dispatch_barrier_async() for details).
- *
- * The variant dispatch_assert_queue_barrier_debug() is compiled out when the
- * preprocessor macro NDEBUG is defined. (See also assert()).
- *
- * @param queue
- * The dispatch queue that the current block is expected to run as a barrier on.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1
-void
-dispatch_assert_queue_barrier(dispatch_queue_t queue);
-
-/*!
- * @function dispatch_assert_queue_not
- *
- * @abstract
- * Verifies that the current block is not executing on a given dispatch queue.
- *
- * @discussion
- * This function is the equivalent of dispatch_assert_queue() with the test for
- * equality inverted. That means that it will terminate the application when
- * dispatch_assert_queue() would return, and vice-versa. See discussion there.
- *
- * The variant dispatch_assert_queue_not_debug() is compiled out when the
- * preprocessor macro NDEBUG is defined. (See also assert(3)).
- *
- * @param queue
- * The dispatch queue that the current block is expected not to run on.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1
-void
-dispatch_assert_queue_not(dispatch_queue_t queue)
- DISPATCH_ALIAS_V2(dispatch_assert_queue_not);
-
-#ifdef NDEBUG
-#define dispatch_assert_queue_debug(q) ((void)(0 && (q)))
-#define dispatch_assert_queue_barrier_debug(q) ((void)(0 && (q)))
-#define dispatch_assert_queue_not_debug(q) ((void)(0 && (q)))
-#else
-#define dispatch_assert_queue_debug(q) dispatch_assert_queue(q)
-#define dispatch_assert_queue_barrier_debug(q) dispatch_assert_queue_barrier(q)
-#define dispatch_assert_queue_not_debug(q) dispatch_assert_queue_not(q)
-#endif
-
-__END_DECLS
-
-DISPATCH_ASSUME_NONNULL_END
-
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/dispatch/semaphore.h b/lib/libc/include/x86_64-macos-gnu/dispatch/semaphore.h
deleted file mode 100644
index 156fb800f3..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/dispatch/semaphore.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-
-#ifndef __DISPATCH_SEMAPHORE__
-#define __DISPATCH_SEMAPHORE__
-
-#ifndef __DISPATCH_INDIRECT__
-#error "Please #include instead of this file directly."
-#include // for HeaderDoc
-#endif
-
-DISPATCH_ASSUME_NONNULL_BEGIN
-
-/*!
- * @typedef dispatch_semaphore_t
- *
- * @abstract
- * A counting semaphore.
- */
-DISPATCH_DECL(dispatch_semaphore);
-
-__BEGIN_DECLS
-
-/*!
- * @function dispatch_semaphore_create
- *
- * @abstract
- * Creates new counting semaphore with an initial value.
- *
- * @discussion
- * Passing zero for the value is useful for when two threads need to reconcile
- * the completion of a particular event. Passing a value greater than zero is
- * useful for managing a finite pool of resources, where the pool size is equal
- * to the value.
- *
- * @param value
- * The starting value for the semaphore. Passing a value less than zero will
- * cause NULL to be returned.
- *
- * @result
- * The newly created semaphore, or NULL on failure.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
-DISPATCH_NOTHROW
-dispatch_semaphore_t
-dispatch_semaphore_create(long value);
-
-/*!
- * @function dispatch_semaphore_wait
- *
- * @abstract
- * Wait (decrement) for a semaphore.
- *
- * @discussion
- * Decrement the counting semaphore. If the resulting value is less than zero,
- * this function waits for a signal to occur before returning.
- *
- * @param dsema
- * The semaphore. The result of passing NULL in this parameter is undefined.
- *
- * @param timeout
- * When to timeout (see dispatch_time). As a convenience, there are the
- * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
- *
- * @result
- * Returns zero on success, or non-zero if the timeout occurred.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-long
-dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
-
-/*!
- * @function dispatch_semaphore_signal
- *
- * @abstract
- * Signal (increment) a semaphore.
- *
- * @discussion
- * Increment the counting semaphore. If the previous value was less than zero,
- * this function wakes a waiting thread before returning.
- *
- * @param dsema The counting semaphore.
- * The result of passing NULL in this parameter is undefined.
- *
- * @result
- * This function returns non-zero if a thread is woken. Otherwise, zero is
- * returned.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-long
-dispatch_semaphore_signal(dispatch_semaphore_t dsema);
-
-__END_DECLS
-
-DISPATCH_ASSUME_NONNULL_END
-
-#endif /* __DISPATCH_SEMAPHORE__ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/dispatch/source.h b/lib/libc/include/x86_64-macos-gnu/dispatch/source.h
deleted file mode 100644
index 968b9ff89e..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/dispatch/source.h
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-
-#ifndef __DISPATCH_SOURCE__
-#define __DISPATCH_SOURCE__
-
-#ifndef __DISPATCH_INDIRECT__
-#error "Please #include instead of this file directly."
-#include // for HeaderDoc
-#endif
-
-#if TARGET_OS_MAC
-#include
-#include
-#endif
-
-#if !defined(_WIN32)
-#include
-#endif
-
-DISPATCH_ASSUME_NONNULL_BEGIN
-
-/*!
- * @header
- * The dispatch framework provides a suite of interfaces for monitoring low-
- * level system objects (file descriptors, Mach ports, signals, VFS nodes, etc.)
- * for activity and automatically submitting event handler blocks to dispatch
- * queues when such activity occurs.
- *
- * This suite of interfaces is known as the Dispatch Source API.
- */
-
-/*!
- * @typedef dispatch_source_t
- *
- * @abstract
- * Dispatch sources are used to automatically submit event handler blocks to
- * dispatch queues in response to external events.
- */
-DISPATCH_SOURCE_DECL(dispatch_source);
-
-__BEGIN_DECLS
-
-/*!
- * @typedef dispatch_source_type_t
- *
- * @abstract
- * Constants of this type represent the class of low-level system object that
- * is being monitored by the dispatch source. Constants of this type are
- * passed as a parameter to dispatch_source_create() and determine how the
- * handle argument is interpreted (i.e. as a file descriptor, mach port,
- * signal number, process identifier, etc.), and how the mask argument is
- * interpreted.
- */
-typedef const struct dispatch_source_type_s *dispatch_source_type_t;
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_DATA_ADD
- * @discussion A dispatch source that coalesces data obtained via calls to
- * dispatch_source_merge_data(). An ADD is used to coalesce the data.
- * The handle is unused (pass zero for now).
- * The mask is unused (pass zero for now).
- */
-#define DISPATCH_SOURCE_TYPE_DATA_ADD (&_dispatch_source_type_data_add)
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_SOURCE_TYPE_DECL(data_add);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_DATA_OR
- * @discussion A dispatch source that coalesces data obtained via calls to
- * dispatch_source_merge_data(). A bitwise OR is used to coalesce the data.
- * The handle is unused (pass zero for now).
- * The mask is unused (pass zero for now).
- */
-#define DISPATCH_SOURCE_TYPE_DATA_OR (&_dispatch_source_type_data_or)
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_SOURCE_TYPE_DECL(data_or);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_DATA_REPLACE
- * @discussion A dispatch source that tracks data obtained via calls to
- * dispatch_source_merge_data(). Newly obtained data values replace existing
- * data values not yet delivered to the source handler
- *
- * A data value of zero will cause the source handler to not be invoked.
- *
- * The handle is unused (pass zero for now).
- * The mask is unused (pass zero for now).
- */
-#define DISPATCH_SOURCE_TYPE_DATA_REPLACE (&_dispatch_source_type_data_replace)
-API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
-DISPATCH_SOURCE_TYPE_DECL(data_replace);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_MACH_SEND
- * @discussion A dispatch source that monitors a Mach port for dead name
- * notifications (send right no longer has any corresponding receive right).
- * The handle is a Mach port with a send or send-once right (mach_port_t).
- * The mask is a mask of desired events from dispatch_source_mach_send_flags_t.
- */
-#define DISPATCH_SOURCE_TYPE_MACH_SEND (&_dispatch_source_type_mach_send)
-API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
-DISPATCH_SOURCE_TYPE_DECL(mach_send);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_MACH_RECV
- * @discussion A dispatch source that monitors a Mach port for pending messages.
- * The handle is a Mach port with a receive right (mach_port_t).
- * The mask is a mask of desired events from dispatch_source_mach_recv_flags_t,
- * but no flags are currently defined (pass zero for now).
- */
-#define DISPATCH_SOURCE_TYPE_MACH_RECV (&_dispatch_source_type_mach_recv)
-API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
-DISPATCH_SOURCE_TYPE_DECL(mach_recv);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
- * @discussion A dispatch source that monitors the system for changes in
- * memory pressure condition.
- * The handle is unused (pass zero for now).
- * The mask is a mask of desired events from
- * dispatch_source_memorypressure_flags_t.
- */
-#define DISPATCH_SOURCE_TYPE_MEMORYPRESSURE \
- (&_dispatch_source_type_memorypressure)
-API_AVAILABLE(macos(10.9), ios(8.0)) DISPATCH_LINUX_UNAVAILABLE()
-DISPATCH_SOURCE_TYPE_DECL(memorypressure);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_PROC
- * @discussion A dispatch source that monitors an external process for events
- * defined by dispatch_source_proc_flags_t.
- * The handle is a process identifier (pid_t).
- * The mask is a mask of desired events from dispatch_source_proc_flags_t.
- */
-#define DISPATCH_SOURCE_TYPE_PROC (&_dispatch_source_type_proc)
-API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
-DISPATCH_SOURCE_TYPE_DECL(proc);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_READ
- * @discussion A dispatch source that monitors a file descriptor for pending
- * bytes available to be read.
- * The handle is a file descriptor (int).
- * The mask is unused (pass zero for now).
- */
-#define DISPATCH_SOURCE_TYPE_READ (&_dispatch_source_type_read)
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_SOURCE_TYPE_DECL(read);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_SIGNAL
- * @discussion A dispatch source that monitors the current process for signals.
- * The handle is a signal number (int).
- * The mask is unused (pass zero for now).
- */
-#define DISPATCH_SOURCE_TYPE_SIGNAL (&_dispatch_source_type_signal)
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_SOURCE_TYPE_DECL(signal);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_TIMER
- * @discussion A dispatch source that submits the event handler block based
- * on a timer.
- * The handle is unused (pass zero for now).
- * The mask specifies which flags from dispatch_source_timer_flags_t to apply.
- */
-#define DISPATCH_SOURCE_TYPE_TIMER (&_dispatch_source_type_timer)
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_SOURCE_TYPE_DECL(timer);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_VNODE
- * @discussion A dispatch source that monitors a file descriptor for events
- * defined by dispatch_source_vnode_flags_t.
- * The handle is a file descriptor (int).
- * The mask is a mask of desired events from dispatch_source_vnode_flags_t.
- */
-#define DISPATCH_SOURCE_TYPE_VNODE (&_dispatch_source_type_vnode)
-API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
-DISPATCH_SOURCE_TYPE_DECL(vnode);
-
-/*!
- * @const DISPATCH_SOURCE_TYPE_WRITE
- * @discussion A dispatch source that monitors a file descriptor for available
- * buffer space to write bytes.
- * The handle is a file descriptor (int).
- * The mask is unused (pass zero for now).
- */
-#define DISPATCH_SOURCE_TYPE_WRITE (&_dispatch_source_type_write)
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_SOURCE_TYPE_DECL(write);
-
-/*!
- * @typedef dispatch_source_mach_send_flags_t
- * Type of dispatch_source_mach_send flags
- *
- * @constant DISPATCH_MACH_SEND_DEAD
- * The receive right corresponding to the given send right was destroyed.
- */
-#define DISPATCH_MACH_SEND_DEAD 0x1
-
-typedef unsigned long dispatch_source_mach_send_flags_t;
-
-/*!
- * @typedef dispatch_source_mach_recv_flags_t
- * Type of dispatch_source_mach_recv flags
- */
-typedef unsigned long dispatch_source_mach_recv_flags_t;
-
-/*!
- * @typedef dispatch_source_memorypressure_flags_t
- * Type of dispatch_source_memorypressure flags
- *
- * @constant DISPATCH_MEMORYPRESSURE_NORMAL
- * The system memory pressure condition has returned to normal.
- *
- * @constant DISPATCH_MEMORYPRESSURE_WARN
- * The system memory pressure condition has changed to warning.
- *
- * @constant DISPATCH_MEMORYPRESSURE_CRITICAL
- * The system memory pressure condition has changed to critical.
- *
- * @discussion
- * Elevated memory pressure is a system-wide condition that applications
- * registered for this source should react to by changing their future memory
- * use behavior, e.g. by reducing cache sizes of newly initiated operations
- * until memory pressure returns back to normal.
- * NOTE: applications should NOT traverse and discard existing caches for past
- * operations when the system memory pressure enters an elevated state, as that
- * is likely to trigger VM operations that will further aggravate system memory
- * pressure.
- */
-
-#define DISPATCH_MEMORYPRESSURE_NORMAL 0x01
-#define DISPATCH_MEMORYPRESSURE_WARN 0x02
-#define DISPATCH_MEMORYPRESSURE_CRITICAL 0x04
-
-typedef unsigned long dispatch_source_memorypressure_flags_t;
-
-/*!
- * @typedef dispatch_source_proc_flags_t
- * Type of dispatch_source_proc flags
- *
- * @constant DISPATCH_PROC_EXIT
- * The process has exited (perhaps cleanly, perhaps not).
- *
- * @constant DISPATCH_PROC_FORK
- * The process has created one or more child processes.
- *
- * @constant DISPATCH_PROC_EXEC
- * The process has become another executable image via
- * exec*() or posix_spawn*().
- *
- * @constant DISPATCH_PROC_SIGNAL
- * A Unix signal was delivered to the process.
- */
-#define DISPATCH_PROC_EXIT 0x80000000
-#define DISPATCH_PROC_FORK 0x40000000
-#define DISPATCH_PROC_EXEC 0x20000000
-#define DISPATCH_PROC_SIGNAL 0x08000000
-
-typedef unsigned long dispatch_source_proc_flags_t;
-
-/*!
- * @typedef dispatch_source_vnode_flags_t
- * Type of dispatch_source_vnode flags
- *
- * @constant DISPATCH_VNODE_DELETE
- * The filesystem object was deleted from the namespace.
- *
- * @constant DISPATCH_VNODE_WRITE
- * The filesystem object data changed.
- *
- * @constant DISPATCH_VNODE_EXTEND
- * The filesystem object changed in size.
- *
- * @constant DISPATCH_VNODE_ATTRIB
- * The filesystem object metadata changed.
- *
- * @constant DISPATCH_VNODE_LINK
- * The filesystem object link count changed.
- *
- * @constant DISPATCH_VNODE_RENAME
- * The filesystem object was renamed in the namespace.
- *
- * @constant DISPATCH_VNODE_REVOKE
- * The filesystem object was revoked.
- *
- * @constant DISPATCH_VNODE_FUNLOCK
- * The filesystem object was unlocked.
- */
-
-#define DISPATCH_VNODE_DELETE 0x1
-#define DISPATCH_VNODE_WRITE 0x2
-#define DISPATCH_VNODE_EXTEND 0x4
-#define DISPATCH_VNODE_ATTRIB 0x8
-#define DISPATCH_VNODE_LINK 0x10
-#define DISPATCH_VNODE_RENAME 0x20
-#define DISPATCH_VNODE_REVOKE 0x40
-#define DISPATCH_VNODE_FUNLOCK 0x100
-
-typedef unsigned long dispatch_source_vnode_flags_t;
-
-/*!
- * @typedef dispatch_source_timer_flags_t
- * Type of dispatch_source_timer flags
- *
- * @constant DISPATCH_TIMER_STRICT
- * Specifies that the system should make a best effort to strictly observe the
- * leeway value specified for the timer via dispatch_source_set_timer(), even
- * if that value is smaller than the default leeway value that would be applied
- * to the timer otherwise. A minimal amount of leeway will be applied to the
- * timer even if this flag is specified.
- *
- * CAUTION: Use of this flag may override power-saving techniques employed by
- * the system and cause higher power consumption, so it must be used with care
- * and only when absolutely necessary.
- */
-
-#define DISPATCH_TIMER_STRICT 0x1
-
-typedef unsigned long dispatch_source_timer_flags_t;
-
-/*!
- * @function dispatch_source_create
- *
- * @abstract
- * Creates a new dispatch source to monitor low-level system objects and auto-
- * matically submit a handler block to a dispatch queue in response to events.
- *
- * @discussion
- * Dispatch sources are not reentrant. Any events received while the dispatch
- * source is suspended or while the event handler block is currently executing
- * will be coalesced and delivered after the dispatch source is resumed or the
- * event handler block has returned.
- *
- * Dispatch sources are created in an inactive state. After creating the
- * source and setting any desired attributes (i.e. the handler, context, etc.),
- * a call must be made to dispatch_activate() in order to begin event delivery.
- *
- * Calling dispatch_set_target_queue() on a source once it has been activated
- * is not allowed (see dispatch_activate() and dispatch_set_target_queue()).
- *
- * For backward compatibility reasons, dispatch_resume() on an inactive,
- * and not otherwise suspended source has the same effect as calling
- * dispatch_activate(). For new code, using dispatch_activate() is preferred.
- *
- * @param type
- * Declares the type of the dispatch source. Must be one of the defined
- * dispatch_source_type_t constants.
- *
- * @param handle
- * The underlying system handle to monitor. The interpretation of this argument
- * is determined by the constant provided in the type parameter.
- *
- * @param mask
- * A mask of flags specifying which events are desired. The interpretation of
- * this argument is determined by the constant provided in the type parameter.
- *
- * @param queue
- * The dispatch queue to which the event handler block will be submitted.
- * If queue is DISPATCH_TARGET_QUEUE_DEFAULT, the source will submit the event
- * handler block to the default priority global queue.
- *
- * @result
- * The newly created dispatch source. Or NULL if invalid arguments are passed.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
-DISPATCH_NOTHROW
-dispatch_source_t
-dispatch_source_create(dispatch_source_type_t type,
- uintptr_t handle,
- unsigned long mask,
- dispatch_queue_t _Nullable queue);
-
-/*!
- * @function dispatch_source_set_event_handler
- *
- * @abstract
- * Sets the event handler block for the given dispatch source.
- *
- * @param source
- * The dispatch source to modify.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param handler
- * The event handler block to submit to the source's target queue.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-void
-dispatch_source_set_event_handler(dispatch_source_t source,
- dispatch_block_t _Nullable handler);
-#endif /* __BLOCKS__ */
-
-/*!
- * @function dispatch_source_set_event_handler_f
- *
- * @abstract
- * Sets the event handler function for the given dispatch source.
- *
- * @param source
- * The dispatch source to modify.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param handler
- * The event handler function to submit to the source's target queue.
- * The context parameter passed to the event handler function is the context of
- * the dispatch source current at the time the event handler was set.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-void
-dispatch_source_set_event_handler_f(dispatch_source_t source,
- dispatch_function_t _Nullable handler);
-
-/*!
- * @function dispatch_source_set_cancel_handler
- *
- * @abstract
- * Sets the cancellation handler block for the given dispatch source.
- *
- * @discussion
- * The cancellation handler (if specified) will be submitted to the source's
- * target queue in response to a call to dispatch_source_cancel() once the
- * system has released all references to the source's underlying handle and
- * the source's event handler block has returned.
- *
- * IMPORTANT:
- * Source cancellation and a cancellation handler are required for file
- * descriptor and mach port based sources in order to safely close the
- * descriptor or destroy the port.
- * Closing the descriptor or port before the cancellation handler is invoked may
- * result in a race condition. If a new descriptor is allocated with the same
- * value as the recently closed descriptor while the source's event handler is
- * still running, the event handler may read/write data to the wrong descriptor.
- *
- * @param source
- * The dispatch source to modify.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param handler
- * The cancellation handler block to submit to the source's target queue.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-void
-dispatch_source_set_cancel_handler(dispatch_source_t source,
- dispatch_block_t _Nullable handler);
-#endif /* __BLOCKS__ */
-
-/*!
- * @function dispatch_source_set_cancel_handler_f
- *
- * @abstract
- * Sets the cancellation handler function for the given dispatch source.
- *
- * @discussion
- * See dispatch_source_set_cancel_handler() for more details.
- *
- * @param source
- * The dispatch source to modify.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param handler
- * The cancellation handler function to submit to the source's target queue.
- * The context parameter passed to the event handler function is the current
- * context of the dispatch source at the time the handler call is made.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-void
-dispatch_source_set_cancel_handler_f(dispatch_source_t source,
- dispatch_function_t _Nullable handler);
-
-/*!
- * @function dispatch_source_cancel
- *
- * @abstract
- * Asynchronously cancel the dispatch source, preventing any further invocation
- * of its event handler block.
- *
- * @discussion
- * Cancellation prevents any further invocation of the event handler block for
- * the specified dispatch source, but does not interrupt an event handler
- * block that is already in progress.
- *
- * The cancellation handler is submitted to the source's target queue once the
- * the source's event handler has finished, indicating it is now safe to close
- * the source's handle (i.e. file descriptor or mach port).
- *
- * See dispatch_source_set_cancel_handler() for more information.
- *
- * @param source
- * The dispatch source to be canceled.
- * The result of passing NULL in this parameter is undefined.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_source_cancel(dispatch_source_t source);
-
-/*!
- * @function dispatch_source_testcancel
- *
- * @abstract
- * Tests whether the given dispatch source has been canceled.
- *
- * @param source
- * The dispatch source to be tested.
- * The result of passing NULL in this parameter is undefined.
- *
- * @result
- * Non-zero if canceled and zero if not canceled.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
-DISPATCH_NOTHROW
-long
-dispatch_source_testcancel(dispatch_source_t source);
-
-/*!
- * @function dispatch_source_get_handle
- *
- * @abstract
- * Returns the underlying system handle associated with this dispatch source.
- *
- * @param source
- * The result of passing NULL in this parameter is undefined.
- *
- * @result
- * The return value should be interpreted according to the type of the dispatch
- * source, and may be one of the following handles:
- *
- * DISPATCH_SOURCE_TYPE_DATA_ADD: n/a
- * DISPATCH_SOURCE_TYPE_DATA_OR: n/a
- * DISPATCH_SOURCE_TYPE_DATA_REPLACE: n/a
- * DISPATCH_SOURCE_TYPE_MACH_SEND: mach port (mach_port_t)
- * DISPATCH_SOURCE_TYPE_MACH_RECV: mach port (mach_port_t)
- * DISPATCH_SOURCE_TYPE_MEMORYPRESSURE n/a
- * DISPATCH_SOURCE_TYPE_PROC: process identifier (pid_t)
- * DISPATCH_SOURCE_TYPE_READ: file descriptor (int)
- * DISPATCH_SOURCE_TYPE_SIGNAL: signal number (int)
- * DISPATCH_SOURCE_TYPE_TIMER: n/a
- * DISPATCH_SOURCE_TYPE_VNODE: file descriptor (int)
- * DISPATCH_SOURCE_TYPE_WRITE: file descriptor (int)
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
-DISPATCH_NOTHROW
-uintptr_t
-dispatch_source_get_handle(dispatch_source_t source);
-
-/*!
- * @function dispatch_source_get_mask
- *
- * @abstract
- * Returns the mask of events monitored by the dispatch source.
- *
- * @param source
- * The result of passing NULL in this parameter is undefined.
- *
- * @result
- * The return value should be interpreted according to the type of the dispatch
- * source, and may be one of the following flag sets:
- *
- * DISPATCH_SOURCE_TYPE_DATA_ADD: n/a
- * DISPATCH_SOURCE_TYPE_DATA_OR: n/a
- * DISPATCH_SOURCE_TYPE_DATA_REPLACE: n/a
- * DISPATCH_SOURCE_TYPE_MACH_SEND: dispatch_source_mach_send_flags_t
- * DISPATCH_SOURCE_TYPE_MACH_RECV: dispatch_source_mach_recv_flags_t
- * DISPATCH_SOURCE_TYPE_MEMORYPRESSURE dispatch_source_memorypressure_flags_t
- * DISPATCH_SOURCE_TYPE_PROC: dispatch_source_proc_flags_t
- * DISPATCH_SOURCE_TYPE_READ: n/a
- * DISPATCH_SOURCE_TYPE_SIGNAL: n/a
- * DISPATCH_SOURCE_TYPE_TIMER: dispatch_source_timer_flags_t
- * DISPATCH_SOURCE_TYPE_VNODE: dispatch_source_vnode_flags_t
- * DISPATCH_SOURCE_TYPE_WRITE: n/a
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
-DISPATCH_NOTHROW
-unsigned long
-dispatch_source_get_mask(dispatch_source_t source);
-
-/*!
- * @function dispatch_source_get_data
- *
- * @abstract
- * Returns pending data for the dispatch source.
- *
- * @discussion
- * This function is intended to be called from within the event handler block.
- * The result of calling this function outside of the event handler callback is
- * undefined.
- *
- * @param source
- * The result of passing NULL in this parameter is undefined.
- *
- * @result
- * The return value should be interpreted according to the type of the dispatch
- * source, and may be one of the following:
- *
- * DISPATCH_SOURCE_TYPE_DATA_ADD: application defined data
- * DISPATCH_SOURCE_TYPE_DATA_OR: application defined data
- * DISPATCH_SOURCE_TYPE_DATA_REPLACE: application defined data
- * DISPATCH_SOURCE_TYPE_MACH_SEND: dispatch_source_mach_send_flags_t
- * DISPATCH_SOURCE_TYPE_MACH_RECV: dispatch_source_mach_recv_flags_t
- * DISPATCH_SOURCE_TYPE_MEMORYPRESSURE dispatch_source_memorypressure_flags_t
- * DISPATCH_SOURCE_TYPE_PROC: dispatch_source_proc_flags_t
- * DISPATCH_SOURCE_TYPE_READ: estimated bytes available to read
- * DISPATCH_SOURCE_TYPE_SIGNAL: number of signals delivered since
- * the last handler invocation
- * DISPATCH_SOURCE_TYPE_TIMER: number of times the timer has fired
- * since the last handler invocation
- * DISPATCH_SOURCE_TYPE_VNODE: dispatch_source_vnode_flags_t
- * DISPATCH_SOURCE_TYPE_WRITE: estimated buffer space available
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
-DISPATCH_NOTHROW
-unsigned long
-dispatch_source_get_data(dispatch_source_t source);
-
-/*!
- * @function dispatch_source_merge_data
- *
- * @abstract
- * Merges data into a dispatch source of type DISPATCH_SOURCE_TYPE_DATA_ADD,
- * DISPATCH_SOURCE_TYPE_DATA_OR or DISPATCH_SOURCE_TYPE_DATA_REPLACE,
- * and submits its event handler block to its target queue.
- *
- * @param source
- * The result of passing NULL in this parameter is undefined.
- *
- * @param value
- * The value to coalesce with the pending data using a logical OR or an ADD
- * as specified by the dispatch source type. A value of zero has no effect
- * and will not result in the submission of the event handler block.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_source_merge_data(dispatch_source_t source, unsigned long value);
-
-/*!
- * @function dispatch_source_set_timer
- *
- * @abstract
- * Sets a start time, interval, and leeway value for a timer source.
- *
- * @discussion
- * Once this function returns, any pending source data accumulated for the
- * previous timer values has been cleared; the next fire of the timer will
- * occur at 'start', and every 'interval' nanoseconds thereafter until the
- * timer source is canceled.
- *
- * Any fire of the timer may be delayed by the system in order to improve power
- * consumption and system performance. The upper limit to the allowable delay
- * may be configured with the 'leeway' argument, the lower limit is under the
- * control of the system.
- *
- * For the initial timer fire at 'start', the upper limit to the allowable
- * delay is set to 'leeway' nanoseconds. For the subsequent timer fires at
- * 'start' + N * 'interval', the upper limit is MIN('leeway','interval'/2).
- *
- * The lower limit to the allowable delay may vary with process state such as
- * visibility of application UI. If the specified timer source was created with
- * a mask of DISPATCH_TIMER_STRICT, the system will make a best effort to
- * strictly observe the provided 'leeway' value even if it is smaller than the
- * current lower limit. Note that a minimal amount of delay is to be expected
- * even if this flag is specified.
- *
- * The 'start' argument also determines which clock will be used for the timer:
- * If 'start' is DISPATCH_TIME_NOW or was created with dispatch_time(3), the
- * timer is based on up time (which is obtained from mach_absolute_time() on
- * Apple platforms). If 'start' was created with dispatch_walltime(3), the
- * timer is based on gettimeofday(3).
- *
- * Calling this function has no effect if the timer source has already been
- * canceled.
- *
- * @param start
- * The start time of the timer. See dispatch_time() and dispatch_walltime()
- * for more information.
- *
- * @param interval
- * The nanosecond interval for the timer. Use DISPATCH_TIME_FOREVER for a
- * one-shot timer.
- *
- * @param leeway
- * The nanosecond leeway for the timer.
- */
-API_AVAILABLE(macos(10.6), ios(4.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_source_set_timer(dispatch_source_t source,
- dispatch_time_t start,
- uint64_t interval,
- uint64_t leeway);
-
-/*!
- * @function dispatch_source_set_registration_handler
- *
- * @abstract
- * Sets the registration handler block for the given dispatch source.
- *
- * @discussion
- * The registration handler (if specified) will be submitted to the source's
- * target queue once the corresponding kevent() has been registered with the
- * system, following the initial dispatch_resume() of the source.
- *
- * If a source is already registered when the registration handler is set, the
- * registration handler will be invoked immediately.
- *
- * @param source
- * The dispatch source to modify.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param handler
- * The registration handler block to submit to the source's target queue.
- */
-#ifdef __BLOCKS__
-API_AVAILABLE(macos(10.7), ios(4.3))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-void
-dispatch_source_set_registration_handler(dispatch_source_t source,
- dispatch_block_t _Nullable handler);
-#endif /* __BLOCKS__ */
-
-/*!
- * @function dispatch_source_set_registration_handler_f
- *
- * @abstract
- * Sets the registration handler function for the given dispatch source.
- *
- * @discussion
- * See dispatch_source_set_registration_handler() for more details.
- *
- * @param source
- * The dispatch source to modify.
- * The result of passing NULL in this parameter is undefined.
- *
- * @param handler
- * The registration handler function to submit to the source's target queue.
- * The context parameter passed to the registration handler function is the
- * current context of the dispatch source at the time the handler call is made.
- */
-API_AVAILABLE(macos(10.7), ios(4.3))
-DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
-void
-dispatch_source_set_registration_handler_f(dispatch_source_t source,
- dispatch_function_t _Nullable handler);
-
-__END_DECLS
-
-DISPATCH_ASSUME_NONNULL_END
-
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/dispatch/workloop.h b/lib/libc/include/x86_64-macos-gnu/dispatch/workloop.h
deleted file mode 100644
index dcd1db43cc..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/dispatch/workloop.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Apple Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-
-#ifndef __DISPATCH_WORKLOOP__
-#define __DISPATCH_WORKLOOP__
-
-#ifndef __DISPATCH_INDIRECT__
-#error "Please #include instead of this file directly."
-#include // for HeaderDoc
-#endif
-
-DISPATCH_ASSUME_NONNULL_BEGIN
-
-__BEGIN_DECLS
-
-/*!
- * @typedef dispatch_workloop_t
- *
- * @abstract
- * Dispatch workloops invoke workitems submitted to them in priority order.
- *
- * @discussion
- * A dispatch workloop is a flavor of dispatch_queue_t that is a priority
- * ordered queue (using the QOS class of the submitted workitems as the
- * ordering).
- *
- * Between each workitem invocation, the workloop will evaluate whether higher
- * priority workitems have since been submitted, either directly to the
- * workloop or to any queues that target the workloop, and execute these first.
- *
- * Serial queues targeting a workloop maintain FIFO execution of their
- * workitems. However, the workloop may reorder workitems submitted to
- * independent serial queues targeting it with respect to each other,
- * based on their priorities, while preserving FIFO execution with respect to
- * each serial queue.
- *
- * A dispatch workloop is a "subclass" of dispatch_queue_t which can be passed
- * to all APIs accepting a dispatch queue, except for functions from the
- * dispatch_sync() family. dispatch_async_and_wait() must be used for workloop
- * objects. Functions from the dispatch_sync() family on queues targeting
- * a workloop are still permitted but discouraged for performance reasons.
- */
-DISPATCH_DECL_SUBCLASS(dispatch_workloop, dispatch_queue);
-
-/*!
- * @function dispatch_workloop_create
- *
- * @abstract
- * Creates a new dispatch workloop to which workitems may be submitted.
- *
- * @param label
- * A string label to attach to the workloop.
- *
- * @result
- * The newly created dispatch workloop.
- */
-API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
-DISPATCH_NOTHROW
-dispatch_workloop_t
-dispatch_workloop_create(const char *_Nullable label);
-
-/*!
- * @function dispatch_workloop_create_inactive
- *
- * @abstract
- * Creates a new inactive dispatch workloop that can be setup and then
- * activated.
- *
- * @discussion
- * Creating an inactive workloop allows for it to receive further configuration
- * before it is activated, and workitems can be submitted to it.
- *
- * Submitting workitems to an inactive workloop is undefined and will cause the
- * process to be terminated.
- *
- * @param label
- * A string label to attach to the workloop.
- *
- * @result
- * The newly created dispatch workloop.
- */
-API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
-DISPATCH_NOTHROW
-dispatch_workloop_t
-dispatch_workloop_create_inactive(const char *_Nullable label);
-
-/*!
- * @function dispatch_workloop_set_autorelease_frequency
- *
- * @abstract
- * Sets the autorelease frequency of the workloop.
- *
- * @discussion
- * See dispatch_queue_attr_make_with_autorelease_frequency().
- * The default policy for a workloop is
- * DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM.
- *
- * @param workloop
- * The dispatch workloop to modify.
- *
- * This workloop must be inactive, passing an activated object is undefined
- * and will cause the process to be terminated.
- *
- * @param frequency
- * The requested autorelease frequency.
- */
-API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
-void
-dispatch_workloop_set_autorelease_frequency(dispatch_workloop_t workloop,
- dispatch_autorelease_frequency_t frequency);
-
-__END_DECLS
-
-DISPATCH_ASSUME_NONNULL_END
-
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/i386/_param.h b/lib/libc/include/x86_64-macos-gnu/i386/_param.h
index d8f7b3d4bf..b89bc39692 100644
--- a/lib/libc/include/x86_64-macos-gnu/i386/_param.h
+++ b/lib/libc/include/x86_64-macos-gnu/i386/_param.h
@@ -37,10 +37,10 @@
* cast to any desired pointer type.
*/
#define __DARWIN_ALIGNBYTES (sizeof(__darwin_size_t) - 1)
-#define __DARWIN_ALIGN(p) ((__darwin_size_t)((char *)(__darwin_size_t)(p) + __DARWIN_ALIGNBYTES) &~ __DARWIN_ALIGNBYTES)
+#define __DARWIN_ALIGN(p) ((__darwin_size_t)((__darwin_size_t)(p) + __DARWIN_ALIGNBYTES) &~ __DARWIN_ALIGNBYTES)
#define __DARWIN_ALIGNBYTES32 (sizeof(__uint32_t) - 1)
-#define __DARWIN_ALIGN32(p) ((__darwin_size_t)((char *)(__darwin_size_t)(p) + __DARWIN_ALIGNBYTES32) &~ __DARWIN_ALIGNBYTES32)
+#define __DARWIN_ALIGN32(p) ((__darwin_size_t)((__darwin_size_t)(p) + __DARWIN_ALIGNBYTES32) &~ __DARWIN_ALIGNBYTES32)
#endif /* _I386__PARAM_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/libkern/OSAtomicDeprecated.h b/lib/libc/include/x86_64-macos-gnu/libkern/OSAtomicDeprecated.h
index aef009bc04..6dc880b0d4 100644
--- a/lib/libc/include/x86_64-macos-gnu/libkern/OSAtomicDeprecated.h
+++ b/lib/libc/include/x86_64-macos-gnu/libkern/OSAtomicDeprecated.h
@@ -35,13 +35,14 @@
* is preferred.
*/
+#include
+
#if !(defined(OSATOMIC_USE_INLINED) && OSATOMIC_USE_INLINED)
#include
#include
#include
#include
-#include
#ifndef OSATOMIC_DEPRECATED
#define OSATOMIC_DEPRECATED 1
@@ -161,7 +162,7 @@ __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0)
int32_t OSAtomicAdd32Barrier( int32_t __theAmount, volatile int32_t *__theValue );
-#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_1
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_1 || TARGET_OS_DRIVERKIT
/*! @abstract Atomically increments a 32-bit value.
@result Returns the new value.
@@ -248,7 +249,7 @@ int64_t OSAtomicAdd64Barrier( int64_t __theAmount,
volatile OSAtomic_int64_aligned64_t *__theValue );
-#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_1
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_1 || TARGET_OS_DRIVERKIT
/*! @abstract Atomically increments a 64-bit value.
@result Returns the new value.
@@ -361,7 +362,7 @@ int32_t OSAtomicOr32Orig( uint32_t __theMask, volatile uint32_t *__theValue );
This function performs the bitwise OR of the value given by __theMask
with the value in the memory location referenced by __theValue,
storing the result back to that memory location atomically.
-
+
This function is equivalent to {@link OSAtomicOr32Orig}
except that it also introduces a barrier.
@result Returns the original value referenced by __theValue.
@@ -481,7 +482,7 @@ int32_t OSAtomicXor32Orig( uint32_t __theMask, volatile uint32_t *__theValue );
OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_xor)
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2)
int32_t OSAtomicXor32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue );
-
+
/*! @group Compare and swap
* Functions in this group return true if the swap occured. There are several versions,
@@ -587,7 +588,7 @@ bool OSAtomicCompareAndSwapIntBarrier( int __oldValue, int __newValue, volatile
match, this function stores the value from __newValue into
that memory location atomically.
- This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures,
+ This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures,
or {@link OSAtomicCompareAndSwap64} on 64-bit architectures.
@result Returns TRUE on a match, FALSE otherwise.
*/
@@ -606,7 +607,7 @@ bool OSAtomicCompareAndSwapLong( long __oldValue, long __newValue, volatile long
This function is equivalent to {@link OSAtomicCompareAndSwapLong}
except that it also introduces a barrier.
- This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures,
+ This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures,
or {@link OSAtomicCompareAndSwap64} on 64-bit architectures.
@result Returns TRUE on a match, FALSE otherwise.
*/
@@ -706,7 +707,7 @@ bool OSAtomicTestAndSetBarrier( uint32_t __n, volatile void *__theAddress );
For example, if __theAddress points to a 64-bit value,
to compare the value of the most significant bit, you would specify
56 for __n.
-
+
@result
Returns the original value of the bit being tested.
*/
@@ -719,15 +720,15 @@ bool OSAtomicTestAndClear( uint32_t __n, volatile void *__theAddress );
@discussion
This function tests a bit in the value referenced by __theAddress
and if it is not cleared, clears it.
-
+
The bit is chosen by the value of __n such that the
operation will be performed on bit (0x80 >> (__n & 7))
of byte ((char *)__theAddress + (n >> 3)).
-
+
For example, if __theAddress points to a 64-bit value,
to compare the value of the most significant bit, you would specify
56 for __n.
-
+
This function is equivalent to {@link OSAtomicTestAndSet}
except that it also introduces a barrier.
@result
@@ -736,7 +737,7 @@ bool OSAtomicTestAndClear( uint32_t __n, volatile void *__theAddress );
OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_and)
__OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0)
bool OSAtomicTestAndClearBarrier( uint32_t __n, volatile void *__theAddress );
-
+
/*! @group Memory barriers */
@@ -1174,4 +1175,92 @@ __END_DECLS
#endif // defined(OSATOMIC_USE_INLINED) && OSATOMIC_USE_INLINED
+#if TARGET_OS_OSX || TARGET_OS_DRIVERKIT
+
+__BEGIN_DECLS
+
+/*! @group Lockless atomic fifo enqueue and dequeue
+ * These routines manipulate singly-linked FIFO lists.
+ *
+ * This API is deprecated and no longer recommended
+ */
+
+/*! @abstract The data structure for a fifo queue head.
+ @discussion
+ You should always initialize a fifo queue head structure with the
+ initialization vector {@link OS_ATOMIC_FIFO_QUEUE_INIT} before use.
+ */
+#if defined(__LP64__)
+
+typedef volatile struct {
+ void *opaque1;
+ void *opaque2;
+ int opaque3;
+} __attribute__ ((aligned (16))) OSFifoQueueHead;
+
+#else
+
+typedef volatile struct {
+ void *opaque1;
+ void *opaque2;
+ int opaque3;
+} OSFifoQueueHead;
+
+#endif
+/*! @abstract The initialization vector for a fifo queue head. */
+#define OS_ATOMIC_FIFO_QUEUE_INIT { NULL, NULL, 0 }
+
+/*! @abstract Enqueue an element onto a list.
+ @discussion
+ Memory barriers are incorporated as needed to permit thread-safe access
+ to the queue element.
+ @param __list
+ The list on which you want to enqueue the element.
+ @param __new
+ The element to add.
+ @param __offset
+ The "offset" parameter is the offset (in bytes) of the link field
+ from the beginning of the data structure being queued (__new).
+ The link field should be a pointer type.
+ The __offset value needs to be same for all enqueuing and
+ dequeuing operations on the same list, even if different structure types
+ are enqueued on that list. The use of offsetset(), defined in
+ stddef.h is the common way to specify the __offset
+ value.
+
+ @note
+ This API is deprecated and no longer recommended
+ */
+__API_DEPRECATED("No longer supported", macos(10.7, 11.0))
+void OSAtomicFifoEnqueue( OSFifoQueueHead *__list, void *__new, size_t __offset);
+
+/*! @abstract Dequeue an element from a list.
+ @discussion
+ Memory barriers are incorporated as needed to permit thread-safe access
+ to the queue element.
+ @param __list
+ The list from which you want to dequeue an element.
+ @param __offset
+ The "offset" parameter is the offset (in bytes) of the link field
+ from the beginning of the data structure being dequeued (__new).
+ The link field should be a pointer type.
+ The __offset value needs to be same for all enqueuing and
+ dequeuing operations on the same list, even if different structure types
+ are enqueued on that list. The use of offsetset(), defined in
+ stddef.h is the common way to specify the __offset
+ value.
+ @result
+ Returns the oldest enqueued element, or NULL if the
+ list is empty.
+
+ @note
+ This API is deprecated and no longer recommended
+ */
+__API_DEPRECATED("No longer supported", macos(10.7, 11.0))
+void* OSAtomicFifoDequeue( OSFifoQueueHead *__list, size_t __offset);
+
+__END_DECLS
+
+#endif /* TARGET_OS_OSX || TARGET_OS_DRIVERKIT */
+
#endif /* _OSATOMIC_DEPRECATED_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/libkern/OSAtomicQueue.h b/lib/libc/include/x86_64-macos-gnu/libkern/OSAtomicQueue.h
index 3f673861e3..66033fc834 100644
--- a/lib/libc/include/x86_64-macos-gnu/libkern/OSAtomicQueue.h
+++ b/lib/libc/include/x86_64-macos-gnu/libkern/OSAtomicQueue.h
@@ -28,6 +28,7 @@
#include
#include
#include
+#include "OSAtomicDeprecated.h"
#include
@@ -109,83 +110,6 @@ void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset);
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_4_0)
void* OSAtomicDequeue( OSQueueHead *__list, size_t __offset);
-#if defined(__x86_64__) || defined(__i386__)
-
-/*! @group Lockless atomic fifo enqueue and dequeue
- * These routines manipulate singly-linked FIFO lists.
- */
-
-/*! @abstract The data structure for a fifo queue head.
- @discussion
- You should always initialize a fifo queue head structure with the
- initialization vector {@link OS_ATOMIC_FIFO_QUEUE_INIT} before use.
- */
-#if defined(__x86_64__)
-
-typedef volatile struct {
- void *opaque1;
- void *opaque2;
- int opaque3;
-} __attribute__ ((aligned (16))) OSFifoQueueHead;
-
-#else
-
-typedef volatile struct {
- void *opaque1;
- void *opaque2;
- int opaque3;
-} OSFifoQueueHead;
-
-#endif
-
-/*! @abstract The initialization vector for a fifo queue head. */
-#define OS_ATOMIC_FIFO_QUEUE_INIT { NULL, NULL, 0 }
-
-/*! @abstract Enqueue an element onto a list.
- @discussion
- Memory barriers are incorporated as needed to permit thread-safe access
- to the queue element.
- @param __list
- The list on which you want to enqueue the element.
- @param __new
- The element to add.
- @param __offset
- The "offset" parameter is the offset (in bytes) of the link field
- from the beginning of the data structure being queued (__new).
- The link field should be a pointer type.
- The __offset value needs to be same for all enqueuing and
- dequeuing operations on the same list, even if different structure types
- are enqueued on that list. The use of offsetset(), defined in
- stddef.h is the common way to specify the __offset
- value.
- */
-__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA)
-void OSAtomicFifoEnqueue( OSFifoQueueHead *__list, void *__new, size_t __offset);
-
-/*! @abstract Dequeue an element from a list.
- @discussion
- Memory barriers are incorporated as needed to permit thread-safe access
- to the queue element.
- @param __list
- The list from which you want to dequeue an element.
- @param __offset
- The "offset" parameter is the offset (in bytes) of the link field
- from the beginning of the data structure being dequeued (__new).
- The link field should be a pointer type.
- The __offset value needs to be same for all enqueuing and
- dequeuing operations on the same list, even if different structure types
- are enqueued on that list. The use of offsetset(), defined in
- stddef.h is the common way to specify the __offset
- value.
- @result
- Returns the oldest enqueued element, or NULL if the
- list is empty.
- */
-__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA)
-void* OSAtomicFifoDequeue( OSFifoQueueHead *__list, size_t __offset);
-
-#endif /* __i386__ || __x86_64__ */
-
__END_DECLS
#endif /* _OSATOMICQUEUE_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/libkern/OSByteOrder.h b/lib/libc/include/x86_64-macos-gnu/libkern/OSByteOrder.h
deleted file mode 100644
index 25563e26e7..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/libkern/OSByteOrder.h
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _OS_OSBYTEORDER_H
-#define _OS_OSBYTEORDER_H
-
-#include
-#include
-
-/* Macros for swapping constant values in the preprocessing stage. */
-#define OSSwapConstInt16(x) __DARWIN_OSSwapConstInt16(x)
-#define OSSwapConstInt32(x) __DARWIN_OSSwapConstInt32(x)
-#define OSSwapConstInt64(x) __DARWIN_OSSwapConstInt64(x)
-
-#if defined(__GNUC__)
-
-#if (defined(__i386__) || defined(__x86_64__))
-#include
-#else
-#include
-#endif
-
-#else /* ! __GNUC__ */
-
-#include
-
-#endif /* __GNUC__ */
-
-#define OSSwapInt16(x) __DARWIN_OSSwapInt16(x)
-#define OSSwapInt32(x) __DARWIN_OSSwapInt32(x)
-#define OSSwapInt64(x) __DARWIN_OSSwapInt64(x)
-
-enum {
- OSUnknownByteOrder,
- OSLittleEndian,
- OSBigEndian
-};
-
-OS_INLINE
-int32_t
-OSHostByteOrder(void)
-{
-#if defined(__LITTLE_ENDIAN__)
- return OSLittleEndian;
-#elif defined(__BIG_ENDIAN__)
- return OSBigEndian;
-#else
- return OSUnknownByteOrder;
-#endif
-}
-
-#define OSReadBigInt(x, y) OSReadBigInt32(x, y)
-#define OSWriteBigInt(x, y, z) OSWriteBigInt32(x, y, z)
-#define OSSwapBigToHostInt(x) OSSwapBigToHostInt32(x)
-#define OSSwapHostToBigInt(x) OSSwapHostToBigInt32(x)
-#define OSReadLittleInt(x, y) OSReadLittleInt32(x, y)
-#define OSWriteLittleInt(x, y, z) OSWriteLittleInt32(x, y, z)
-#define OSSwapHostToLittleInt(x) OSSwapHostToLittleInt32(x)
-#define OSSwapLittleToHostInt(x) OSSwapLittleToHostInt32(x)
-
-/* Functions for loading native endian values. */
-
-OS_INLINE
-uint16_t
-_OSReadInt16(
- const volatile void * base,
- uintptr_t byteOffset
- )
-{
- return *(volatile uint16_t *)((uintptr_t)base + byteOffset);
-}
-
-OS_INLINE
-uint32_t
-_OSReadInt32(
- const volatile void * base,
- uintptr_t byteOffset
- )
-{
- return *(volatile uint32_t *)((uintptr_t)base + byteOffset);
-}
-
-OS_INLINE
-uint64_t
-_OSReadInt64(
- const volatile void * base,
- uintptr_t byteOffset
- )
-{
- return *(volatile uint64_t *)((uintptr_t)base + byteOffset);
-}
-
-/* Functions for storing native endian values. */
-
-OS_INLINE
-void
-_OSWriteInt16(
- volatile void * base,
- uintptr_t byteOffset,
- uint16_t data
- )
-{
- *(volatile uint16_t *)((uintptr_t)base + byteOffset) = data;
-}
-
-OS_INLINE
-void
-_OSWriteInt32(
- volatile void * base,
- uintptr_t byteOffset,
- uint32_t data
- )
-{
- *(volatile uint32_t *)((uintptr_t)base + byteOffset) = data;
-}
-
-OS_INLINE
-void
-_OSWriteInt64(
- volatile void * base,
- uintptr_t byteOffset,
- uint64_t data
- )
-{
- *(volatile uint64_t *)((uintptr_t)base + byteOffset) = data;
-}
-
-#if defined(__BIG_ENDIAN__)
-
-/* Functions for loading big endian to host endianess. */
-
-#define OSReadBigInt16(base, byteOffset) _OSReadInt16(base, byteOffset)
-#define OSReadBigInt32(base, byteOffset) _OSReadInt32(base, byteOffset)
-#define OSReadBigInt64(base, byteOffset) _OSReadInt64(base, byteOffset)
-
-/* Functions for storing host endianess to big endian. */
-
-#define OSWriteBigInt16(base, byteOffset, data) _OSWriteInt16(base, byteOffset, data)
-#define OSWriteBigInt32(base, byteOffset, data) _OSWriteInt32(base, byteOffset, data)
-#define OSWriteBigInt64(base, byteOffset, data) _OSWriteInt64(base, byteOffset, data)
-
-/* Functions for loading little endian to host endianess. */
-
-#define OSReadLittleInt16(base, byteOffset) OSReadSwapInt16(base, byteOffset)
-#define OSReadLittleInt32(base, byteOffset) OSReadSwapInt32(base, byteOffset)
-#define OSReadLittleInt64(base, byteOffset) OSReadSwapInt64(base, byteOffset)
-
-/* Functions for storing host endianess to little endian. */
-
-#define OSWriteLittleInt16(base, byteOffset, data) OSWriteSwapInt16(base, byteOffset, data)
-#define OSWriteLittleInt32(base, byteOffset, data) OSWriteSwapInt32(base, byteOffset, data)
-#define OSWriteLittleInt64(base, byteOffset, data) OSWriteSwapInt64(base, byteOffset, data)
-
-/* Host endianess to big endian byte swapping macros for constants. */
-
-#define OSSwapHostToBigConstInt16(x) ((uint16_t)(x))
-#define OSSwapHostToBigConstInt32(x) ((uint32_t)(x))
-#define OSSwapHostToBigConstInt64(x) ((uint64_t)(x))
-
-/* Generic host endianess to big endian byte swapping functions. */
-
-#define OSSwapHostToBigInt16(x) ((uint16_t)(x))
-#define OSSwapHostToBigInt32(x) ((uint32_t)(x))
-#define OSSwapHostToBigInt64(x) ((uint64_t)(x))
-
-/* Host endianess to little endian byte swapping macros for constants. */
-
-#define OSSwapHostToLittleConstInt16(x) OSSwapConstInt16(x)
-#define OSSwapHostToLittleConstInt32(x) OSSwapConstInt32(x)
-#define OSSwapHostToLittleConstInt64(x) OSSwapConstInt64(x)
-
-/* Generic host endianess to little endian byte swapping functions. */
-
-#define OSSwapHostToLittleInt16(x) OSSwapInt16(x)
-#define OSSwapHostToLittleInt32(x) OSSwapInt32(x)
-#define OSSwapHostToLittleInt64(x) OSSwapInt64(x)
-
-/* Big endian to host endianess byte swapping macros for constants. */
-
-#define OSSwapBigToHostConstInt16(x) ((uint16_t)(x))
-#define OSSwapBigToHostConstInt32(x) ((uint32_t)(x))
-#define OSSwapBigToHostConstInt64(x) ((uint64_t)(x))
-
-/* Generic big endian to host endianess byte swapping functions. */
-
-#define OSSwapBigToHostInt16(x) ((uint16_t)(x))
-#define OSSwapBigToHostInt32(x) ((uint32_t)(x))
-#define OSSwapBigToHostInt64(x) ((uint64_t)(x))
-
-/* Little endian to host endianess byte swapping macros for constants. */
-
-#define OSSwapLittleToHostConstInt16(x) OSSwapConstInt16(x)
-#define OSSwapLittleToHostConstInt32(x) OSSwapConstInt32(x)
-#define OSSwapLittleToHostConstInt64(x) OSSwapConstInt64(x)
-
-/* Generic little endian to host endianess byte swapping functions. */
-
-#define OSSwapLittleToHostInt16(x) OSSwapInt16(x)
-#define OSSwapLittleToHostInt32(x) OSSwapInt32(x)
-#define OSSwapLittleToHostInt64(x) OSSwapInt64(x)
-
-#elif defined(__LITTLE_ENDIAN__)
-
-/* Functions for loading big endian to host endianess. */
-
-#define OSReadBigInt16(base, byteOffset) OSReadSwapInt16(base, byteOffset)
-#define OSReadBigInt32(base, byteOffset) OSReadSwapInt32(base, byteOffset)
-#define OSReadBigInt64(base, byteOffset) OSReadSwapInt64(base, byteOffset)
-
-/* Functions for storing host endianess to big endian. */
-
-#define OSWriteBigInt16(base, byteOffset, data) OSWriteSwapInt16(base, byteOffset, data)
-#define OSWriteBigInt32(base, byteOffset, data) OSWriteSwapInt32(base, byteOffset, data)
-#define OSWriteBigInt64(base, byteOffset, data) OSWriteSwapInt64(base, byteOffset, data)
-
-/* Functions for loading little endian to host endianess. */
-
-#define OSReadLittleInt16(base, byteOffset) _OSReadInt16(base, byteOffset)
-#define OSReadLittleInt32(base, byteOffset) _OSReadInt32(base, byteOffset)
-#define OSReadLittleInt64(base, byteOffset) _OSReadInt64(base, byteOffset)
-
-/* Functions for storing host endianess to little endian. */
-
-#define OSWriteLittleInt16(base, byteOffset, data) _OSWriteInt16(base, byteOffset, data)
-#define OSWriteLittleInt32(base, byteOffset, data) _OSWriteInt32(base, byteOffset, data)
-#define OSWriteLittleInt64(base, byteOffset, data) _OSWriteInt64(base, byteOffset, data)
-
-/* Host endianess to big endian byte swapping macros for constants. */
-
-#define OSSwapHostToBigConstInt16(x) OSSwapConstInt16(x)
-#define OSSwapHostToBigConstInt32(x) OSSwapConstInt32(x)
-#define OSSwapHostToBigConstInt64(x) OSSwapConstInt64(x)
-
-/* Generic host endianess to big endian byte swapping functions. */
-
-#define OSSwapHostToBigInt16(x) OSSwapInt16(x)
-#define OSSwapHostToBigInt32(x) OSSwapInt32(x)
-#define OSSwapHostToBigInt64(x) OSSwapInt64(x)
-
-/* Host endianess to little endian byte swapping macros for constants. */
-
-#define OSSwapHostToLittleConstInt16(x) ((uint16_t)(x))
-#define OSSwapHostToLittleConstInt32(x) ((uint32_t)(x))
-#define OSSwapHostToLittleConstInt64(x) ((uint64_t)(x))
-
-/* Generic host endianess to little endian byte swapping functions. */
-
-#define OSSwapHostToLittleInt16(x) ((uint16_t)(x))
-#define OSSwapHostToLittleInt32(x) ((uint32_t)(x))
-#define OSSwapHostToLittleInt64(x) ((uint64_t)(x))
-
-/* Big endian to host endianess byte swapping macros for constants. */
-
-#define OSSwapBigToHostConstInt16(x) OSSwapConstInt16(x)
-#define OSSwapBigToHostConstInt32(x) OSSwapConstInt32(x)
-#define OSSwapBigToHostConstInt64(x) OSSwapConstInt64(x)
-
-/* Generic big endian to host endianess byte swapping functions. */
-
-#define OSSwapBigToHostInt16(x) OSSwapInt16(x)
-#define OSSwapBigToHostInt32(x) OSSwapInt32(x)
-#define OSSwapBigToHostInt64(x) OSSwapInt64(x)
-
-/* Little endian to host endianess byte swapping macros for constants. */
-
-#define OSSwapLittleToHostConstInt16(x) ((uint16_t)(x))
-#define OSSwapLittleToHostConstInt32(x) ((uint32_t)(x))
-#define OSSwapLittleToHostConstInt64(x) ((uint64_t)(x))
-
-/* Generic little endian to host endianess byte swapping functions. */
-
-#define OSSwapLittleToHostInt16(x) ((uint16_t)(x))
-#define OSSwapLittleToHostInt32(x) ((uint32_t)(x))
-#define OSSwapLittleToHostInt64(x) ((uint64_t)(x))
-
-#else
-#error Unknown endianess.
-#endif
-
-#endif /* ! _OS_OSBYTEORDER_H */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/libkern/_OSByteOrder.h b/lib/libc/include/x86_64-macos-gnu/libkern/_OSByteOrder.h
deleted file mode 100644
index 06614c63ea..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/libkern/_OSByteOrder.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _OS__OSBYTEORDER_H
-#define _OS__OSBYTEORDER_H
-
-/*
- * This header is normally included from . However,
- * also includes this in the case of little-endian
- * architectures, so that we can map OSByteOrder routines to the hton* and ntoh*
- * macros. This results in the asymmetry below; we only include
- * for little-endian architectures.
- */
-
-#include
-
-/* Macros for swapping constant values in the preprocessing stage. */
-#define __DARWIN_OSSwapConstInt16(x) \
- ((__uint16_t)((((__uint16_t)(x) & 0xff00) >> 8) | \
- (((__uint16_t)(x) & 0x00ff) << 8)))
-
-#define __DARWIN_OSSwapConstInt32(x) \
- ((__uint32_t)((((__uint32_t)(x) & 0xff000000) >> 24) | \
- (((__uint32_t)(x) & 0x00ff0000) >> 8) | \
- (((__uint32_t)(x) & 0x0000ff00) << 8) | \
- (((__uint32_t)(x) & 0x000000ff) << 24)))
-
-#define __DARWIN_OSSwapConstInt64(x) \
- ((__uint64_t)((((__uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
- (((__uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
- (((__uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
- (((__uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
- (((__uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
- (((__uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
- (((__uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
- (((__uint64_t)(x) & 0x00000000000000ffULL) << 56)))
-
-#if defined(__GNUC__)
-
-#if defined(__i386__) || defined(__x86_64__)
-#include
-#endif
-
-
-
-#define __DARWIN_OSSwapInt16(x) \
- ((__uint16_t)(__builtin_constant_p(x) ? __DARWIN_OSSwapConstInt16(x) : _OSSwapInt16(x)))
-
-#define __DARWIN_OSSwapInt32(x) \
- (__builtin_constant_p(x) ? __DARWIN_OSSwapConstInt32(x) : _OSSwapInt32(x))
-
-#define __DARWIN_OSSwapInt64(x) \
- (__builtin_constant_p(x) ? __DARWIN_OSSwapConstInt64(x) : _OSSwapInt64(x))
-
-#else /* ! __GNUC__ */
-
-#if defined(__i386__) || defined(__x86_64__)
-
-#if !defined(__DARWIN_OS_INLINE)
-# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-# define __DARWIN_OS_INLINE static inline
-# elif defined(__MWERKS__) || defined(__cplusplus)
-# define __DARWIN_OS_INLINE static inline
-# else
-# define __DARWIN_OS_INLINE static __inline__
-# endif
-#endif
-
-__DARWIN_OS_INLINE
-uint16_t
-_OSSwapInt16(
- uint16_t data
- )
-{
- return __DARWIN_OSSwapConstInt16(data);
-}
-
-__DARWIN_OS_INLINE
-uint32_t
-_OSSwapInt32(
- uint32_t data
- )
-{
- return __DARWIN_OSSwapConstInt32(data);
-}
-
-__DARWIN_OS_INLINE
-uint64_t
-_OSSwapInt64(
- uint64_t data
- )
-{
- return __DARWIN_OSSwapConstInt64(data);
-}
-#endif
-
-#define __DARWIN_OSSwapInt16(x) _OSSwapInt16(x)
-
-#define __DARWIN_OSSwapInt32(x) _OSSwapInt32(x)
-
-#define __DARWIN_OSSwapInt64(x) _OSSwapInt64(x)
-
-#endif /* __GNUC__ */
-
-#endif /* ! _OS__OSBYTEORDER_H */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/libproc.h b/lib/libc/include/x86_64-macos-gnu/libproc.h
deleted file mode 100644
index 4094fe40ef..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/libproc.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2006, 2007, 2010 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#ifndef _LIBPROC_H_
-#define _LIBPROC_H_
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include /* for audit_token_t */
-
-#include
-
-#include
-#include
-
-/*
- * This header file contains private interfaces to obtain process information.
- * These interfaces are subject to change in future releases.
- */
-
-/*!
- * @define PROC_LISTPIDSPATH_PATH_IS_VOLUME
- * @discussion This flag indicates that all processes that hold open
- * file references on the volume associated with the specified
- * path should be returned.
- */
-#define PROC_LISTPIDSPATH_PATH_IS_VOLUME 1
-
-
-/*!
- * @define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY
- * @discussion This flag indicates that file references that were opened
- * with the O_EVTONLY flag should be excluded from the matching
- * criteria.
- */
-#define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY 2
-
-__BEGIN_DECLS
-
-
-/*!
- * @function proc_listpidspath
- * @discussion A function which will search through the current
- * processes looking for open file references which match
- * a specified path or volume.
- * @param type types of processes to be searched (see proc_listpids)
- * @param typeinfo adjunct information for type
- * @param path file or volume path
- * @param pathflags flags to control which files should be considered
- * during the process search.
- * @param buffer a C array of int-sized values to be filled with
- * process identifiers that hold an open file reference
- * matching the specified path or volume. Pass NULL to
- * obtain the minimum buffer size needed to hold the
- * currently active processes.
- * @param buffersize the size (in bytes) of the provided buffer.
- * @result the number of bytes of data returned in the provided buffer;
- * -1 if an error was encountered;
- */
-int proc_listpidspath(uint32_t type,
- uint32_t typeinfo,
- const char *path,
- uint32_t pathflags,
- void *buffer,
- int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-
-int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-int proc_listallpids(void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
-int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
-int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
-int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-int proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
-int proc_name(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-int proc_kmsgbuf(void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-int proc_pidpath(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-int proc_pidpath_audittoken(audit_token_t *audittoken, void * buffer, uint32_t buffersize) API_AVAILABLE(macos(11.0), ios(14.0), watchos(7.0), tvos(14.0));
-int proc_libversion(int *major, int * minor) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-
-/*
- * Return resource usage information for the given pid, which can be a live process or a zombie.
- *
- * Returns 0 on success; or -1 on failure, with errno set to indicate the specific error.
- */
-int proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
-
-/*
- * A process can use the following api to set its own process control
- * state on resoure starvation. The argument can have one of the PROC_SETPC_XX values
- */
-#define PROC_SETPC_NONE 0
-#define PROC_SETPC_THROTTLEMEM 1
-#define PROC_SETPC_SUSPEND 2
-#define PROC_SETPC_TERMINATE 3
-
-int proc_setpcontrol(const int control) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
-int proc_setpcontrol(const int control);
-
-int proc_track_dirty(pid_t pid, uint32_t flags);
-int proc_set_dirty(pid_t pid, bool dirty);
-int proc_get_dirty(pid_t pid, uint32_t *flags);
-int proc_clear_dirty(pid_t pid, uint32_t flags);
-
-int proc_terminate(pid_t pid, int *sig);
-
-/*
- * NO_SMT means that on an SMT CPU, this thread must be scheduled alone,
- * with the paired CPU idle.
- *
- * Set NO_SMT on the current proc (all existing and future threads)
- * This attribute is inherited on fork and exec
- */
-int proc_set_no_smt(void) __API_AVAILABLE(macos(11.0));
-
-/* Set NO_SMT on the current thread */
-int proc_setthread_no_smt(void) __API_AVAILABLE(macos(11.0));
-
-/*
- * CPU Security Mitigation APIs
- *
- * Set CPU security mitigation on the current proc (all existing and future threads)
- * This attribute is inherited on fork and exec
- */
-int proc_set_csm(uint32_t flags) __API_AVAILABLE(macos(11.0));
-
-/* Set CPU security mitigation on the current thread */
-int proc_setthread_csm(uint32_t flags) __API_AVAILABLE(macos(11.0));
-
-/*
- * flags for CPU Security Mitigation APIs
- * PROC_CSM_ALL should be used in most cases,
- * the individual flags are provided only for performance evaluation etc
- */
-#define PROC_CSM_ALL 0x0001 /* Set all available mitigations */
-#define PROC_CSM_NOSMT 0x0002 /* Set NO_SMT - see above */
-#define PROC_CSM_TECS 0x0004 /* Execute VERW on every return to user mode */
-
-#ifdef PRIVATE
-#include
-/*
- * Enumerate potential userspace pointers embedded in kernel data structures.
- * Currently inspects kqueues only.
- *
- * NOTE: returned "pointers" are opaque user-supplied values and thus not
- * guaranteed to address valid objects or be pointers at all.
- *
- * Returns the number of pointers found (which may exceed buffersize), or -1 on
- * failure and errno set appropriately.
- */
-int proc_list_uptrs(pid_t pid, uint64_t *buffer, uint32_t buffersize);
-
-int proc_list_dynkqueueids(int pid, kqueue_id_t *buf, uint32_t bufsz);
-int proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer,
- int buffersize);
-#endif /* PRIVATE */
-
-int proc_udata_info(int pid, int flavor, void *buffer, int buffersize);
-
-__END_DECLS
-
-#endif /*_LIBPROC_H_ */
diff --git a/lib/libc/include/x86_64-macos-gnu/mach-o/dyld.h b/lib/libc/include/x86_64-macos-gnu/mach-o/dyld.h
deleted file mode 100644
index 0b293cbd09..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach-o/dyld.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (c) 1999-2008 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#ifndef _MACH_O_DYLD_H_
-#define _MACH_O_DYLD_H_
-
-
-#include
-#include
-#include
-
-#include
-#include
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifdef __DRIVERKIT_19_0
- #define DYLD_DRIVERKIT_UNAVAILABLE __API_UNAVAILABLE(driverkit)
-#else
- #define DYLD_DRIVERKIT_UNAVAILABLE
-#endif
-
-/*
- * The following functions allow you to iterate through all loaded images.
- * This is not a thread safe operation. Another thread can add or remove
- * an image during the iteration.
- *
- * Many uses of these routines can be replace by a call to dladdr() which
- * will return the mach_header and name of an image, given an address in
- * the image. dladdr() is thread safe.
- */
-extern uint32_t _dyld_image_count(void) __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0);
-extern const struct mach_header* _dyld_get_image_header(uint32_t image_index) __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0);
-extern intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index) __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0);
-extern const char* _dyld_get_image_name(uint32_t image_index) __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0);
-
-
-/*
- * The following functions allow you to install callbacks which will be called
- * by dyld whenever an image is loaded or unloaded. During a call to _dyld_register_func_for_add_image()
- * the callback func is called for every existing image. Later, it is called as each new image
- * is loaded and bound (but initializers not yet run). The callback registered with
- * _dyld_register_func_for_remove_image() is called after any terminators in an image are run
- * and before the image is un-memory-mapped.
- */
-extern void _dyld_register_func_for_add_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)) __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0);
-extern void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)) __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0);
-
-
-/*
- * NSVersionOfRunTimeLibrary() returns the current_version number of the currently dylib
- * specifed by the libraryName. The libraryName parameter would be "bar" for /path/libbar.3.dylib and
- * "Foo" for /path/Foo.framework/Versions/A/Foo. It returns -1 if no such library is loaded.
- */
-extern int32_t NSVersionOfRunTimeLibrary(const char* libraryName) __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0);
-
-
-/*
- * NSVersionOfLinkTimeLibrary() returns the current_version number that the main executable was linked
- * against at build time. The libraryName parameter would be "bar" for /path/libbar.3.dylib and
- * "Foo" for /path/Foo.framework/Versions/A/Foo. It returns -1 if the main executable did not link
- * against the specified library.
- */
-extern int32_t NSVersionOfLinkTimeLibrary(const char* libraryName) __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0);
-
-
-/*
- * _NSGetExecutablePath() copies the path of the main executable into the buffer. The bufsize parameter
- * should initially be the size of the buffer. The function returns 0 if the path was successfully copied,
- * and *bufsize is left unchanged. It returns -1 if the buffer is not large enough, and *bufsize is set
- * to the size required.
- *
- * Note that _NSGetExecutablePath will return "a path" to the executable not a "real path" to the executable.
- * That is the path may be a symbolic link and not the real file. With deep directories the total bufsize
- * needed could be more than MAXPATHLEN.
- */
-extern int _NSGetExecutablePath(char* buf, uint32_t* bufsize) __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_2_0);
-
-
-
-/*
- * Registers a function to be called when the current thread terminates.
- * Called by c++ compiler to implement destructors on thread_local object variables.
- */
-extern void _tlv_atexit(void (*termFunc)(void* objAddr), void* objAddr) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0);
-
-
-/*
- * Never called. On-disk thread local variables contain a pointer to this. Once
- * the thread local is prepared, the pointer changes to a real handler such as tlv_get_addr.
- */
-extern void _tlv_bootstrap(void) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) DYLD_DRIVERKIT_UNAVAILABLE ;
-
-/*
- * The following dyld API's are deprecated as of Mac OS X 10.5. They are either
- * no longer necessary or are superceeded by dlopen and friends in .
- * dlopen/dlsym/dlclose have been available since Mac OS X 10.3 and work with
- * dylibs and bundles.
- *
- * NSAddImage -> dlopen
- * NSLookupSymbolInImage -> dlsym
- * NSCreateObjectFileImageFromFile -> dlopen
- * NSDestroyObjectFileImage -> dlclose
- * NSLinkModule -> not needed when dlopen used
- * NSUnLinkModule -> not needed when dlclose used
- * NSLookupSymbolInModule -> dlsym
- * _dyld_image_containing_address -> dladdr
- * NSLinkEditError -> dlerror
- *
- */
-
-#ifndef ENUM_DYLD_BOOL
-#define ENUM_DYLD_BOOL
- #undef FALSE
- #undef TRUE
- enum DYLD_BOOL { FALSE, TRUE };
-#endif /* ENUM_DYLD_BOOL */
-
-
-/* Object file image API */
-typedef enum {
- NSObjectFileImageFailure, /* for this a message is printed on stderr */
- NSObjectFileImageSuccess,
- NSObjectFileImageInappropriateFile,
- NSObjectFileImageArch,
- NSObjectFileImageFormat, /* for this a message is printed on stderr */
- NSObjectFileImageAccess
-} NSObjectFileImageReturnCode;
-
-typedef struct __NSObjectFileImage* NSObjectFileImage;
-
-
-
-/* NSObjectFileImage can only be used with MH_BUNDLE files */
-extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(const char* pathName, NSObjectFileImage *objectFileImage) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlopen()");
-extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(const void *address, size_t size, NSObjectFileImage *objectFileImage) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-extern bool NSDestroyObjectFileImage(NSObjectFileImage objectFileImage) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlclose()");
-
-extern uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-extern const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-extern uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-extern const char* NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal, bool *tentative_definition) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-extern bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage, const char* symbolName) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlsym()");
-extern void* NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage, const char* segmentName, const char* sectionName, size_t *size) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "getsectiondata()");
-
-typedef struct __NSModule* NSModule;
-extern const char* NSNameOfModule(NSModule m) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-extern const char* NSLibraryNameForModule(NSModule m) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-
-extern NSModule NSLinkModule(NSObjectFileImage objectFileImage, const char* moduleName, uint32_t options) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlopen()");
-#define NSLINKMODULE_OPTION_NONE 0x0
-#define NSLINKMODULE_OPTION_BINDNOW 0x1
-#define NSLINKMODULE_OPTION_PRIVATE 0x2
-#define NSLINKMODULE_OPTION_RETURN_ON_ERROR 0x4
-#define NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES 0x8
-#define NSLINKMODULE_OPTION_TRAILING_PHYS_NAME 0x10
-
-extern bool NSUnLinkModule(NSModule module, uint32_t options) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-#define NSUNLINKMODULE_OPTION_NONE 0x0
-#define NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED 0x1
-#define NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES 0x2
-
-/* symbol API */
-typedef struct __NSSymbol* NSSymbol;
-extern bool NSIsSymbolNameDefined(const char* symbolName) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlsym()");
-extern bool NSIsSymbolNameDefinedWithHint(const char* symbolName, const char* libraryNameHint) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlsym()");
-extern bool NSIsSymbolNameDefinedInImage(const struct mach_header* image, const char* symbolName) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlsym()");
-extern NSSymbol NSLookupAndBindSymbol(const char* symbolName) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlsym()");
-extern NSSymbol NSLookupAndBindSymbolWithHint(const char* symbolName, const char* libraryNameHint) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlsym()");
-extern NSSymbol NSLookupSymbolInModule(NSModule module, const char* symbolName) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlsym()");
-extern NSSymbol NSLookupSymbolInImage(const struct mach_header* image, const char* symbolName, uint32_t options) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlsym()");
-#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
-#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
-#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
-#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
-extern const char* NSNameOfSymbol(NSSymbol symbol) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-extern void * NSAddressOfSymbol(NSSymbol symbol) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlsym()");
-extern NSModule NSModuleForSymbol(NSSymbol symbol) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dladdr()");
-
-/* error handling API */
-typedef enum {
- NSLinkEditFileAccessError,
- NSLinkEditFileFormatError,
- NSLinkEditMachResourceError,
- NSLinkEditUnixResourceError,
- NSLinkEditOtherError,
- NSLinkEditWarningError,
- NSLinkEditMultiplyDefinedError,
- NSLinkEditUndefinedError
-} NSLinkEditErrors;
-
-/*
- * For the NSLinkEditErrors value NSLinkEditOtherError these are the values
- * passed to the link edit error handler as the errorNumber (what would be an
- * errno value for NSLinkEditUnixResourceError or a kern_return_t value for
- * NSLinkEditMachResourceError).
- */
-typedef enum {
- NSOtherErrorRelocation,
- NSOtherErrorLazyBind,
- NSOtherErrorIndrLoop,
- NSOtherErrorLazyInit,
- NSOtherErrorInvalidArgs
-} NSOtherErrorNumbers;
-
-extern void NSLinkEditError(NSLinkEditErrors *c, int *errorNumber, const char** fileName, const char** errorString) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlerror()");
-
-typedef struct {
- void (*undefined)(const char* symbolName);
- NSModule (*multiple)(NSSymbol s, NSModule oldModule, NSModule newModule);
- void (*linkEdit)(NSLinkEditErrors errorClass, int errorNumber,
- const char* fileName, const char* errorString);
-} NSLinkEditErrorHandlers;
-
-extern void NSInstallLinkEditErrorHandlers(const NSLinkEditErrorHandlers *handlers) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "");
-
-extern bool NSAddLibrary(const char* pathName) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlopen()");
-extern bool NSAddLibraryWithSearching(const char* pathName) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlopen()");
-extern const struct mach_header* NSAddImage(const char* image_name, uint32_t options) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlopen()");
-#define NSADDIMAGE_OPTION_NONE 0x0
-#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
-#define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
-#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
-#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
-
-extern bool _dyld_present(void) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "always true");
-extern bool _dyld_launched_prebound(void) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "moot");
-extern bool _dyld_all_twolevel_modules_prebound(void) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.3, 10.5, "moot");
-extern bool _dyld_bind_fully_image_containing_address(const void* address) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlopen(RTLD_NOW)");
-extern bool _dyld_image_containing_address(const void* address) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.3, 10.5, "dladdr()");
-extern void _dyld_lookup_and_bind(const char* symbol_name, void **address, NSModule* module) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlsym()");
-extern void _dyld_lookup_and_bind_with_hint(const char* symbol_name, const char* library_name_hint, void** address, NSModule* module) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.4, "dlsym()");
-extern void _dyld_lookup_and_bind_fully(const char* symbol_name, void** address, NSModule* module) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.1, 10.5, "dlsym()");
-
-extern const struct mach_header* _dyld_get_image_header_containing_address(const void* address) __API_UNAVAILABLE(ios, tvos, watchos) DYLD_DRIVERKIT_UNAVAILABLE __OSX_DEPRECATED(10.3, 10.5, "dladdr()");
-
-
-#if __cplusplus
-}
-#endif
-
-#endif /* _MACH_O_DYLD_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach-o/loader.h b/lib/libc/include/x86_64-macos-gnu/mach-o/loader.h
deleted file mode 100644
index a088105205..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach-o/loader.h
+++ /dev/null
@@ -1,1577 +0,0 @@
-/*
- * Copyright (c) 1999-2010 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#ifndef _MACHO_LOADER_H_
-#define _MACHO_LOADER_H_
-
-/*
- * This file describes the format of mach object files.
- */
-#include
-
-/*
- * is needed here for the cpu_type_t and cpu_subtype_t types
- * and contains the constants for the possible values of these types.
- */
-#include
-
-/*
- * is needed here for the vm_prot_t type and contains the
- * constants that are or'ed together for the possible values of this type.
- */
-#include
-
-/*
- * is expected to define the flavors of the thread
- * states and the structures of those flavors for each machine.
- */
-#include
-#include
-
-/*
- * The 32-bit mach header appears at the very beginning of the object file for
- * 32-bit architectures.
- */
-struct mach_header {
- uint32_t magic; /* mach magic number identifier */
- cpu_type_t cputype; /* cpu specifier */
- cpu_subtype_t cpusubtype; /* machine specifier */
- uint32_t filetype; /* type of file */
- uint32_t ncmds; /* number of load commands */
- uint32_t sizeofcmds; /* the size of all the load commands */
- uint32_t flags; /* flags */
-};
-
-/* Constant for the magic field of the mach_header (32-bit architectures) */
-#define MH_MAGIC 0xfeedface /* the mach magic number */
-#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */
-
-/*
- * The 64-bit mach header appears at the very beginning of object files for
- * 64-bit architectures.
- */
-struct mach_header_64 {
- uint32_t magic; /* mach magic number identifier */
- cpu_type_t cputype; /* cpu specifier */
- cpu_subtype_t cpusubtype; /* machine specifier */
- uint32_t filetype; /* type of file */
- uint32_t ncmds; /* number of load commands */
- uint32_t sizeofcmds; /* the size of all the load commands */
- uint32_t flags; /* flags */
- uint32_t reserved; /* reserved */
-};
-
-/* Constant for the magic field of the mach_header_64 (64-bit architectures) */
-#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
-#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */
-
-/*
- * The layout of the file depends on the filetype. For all but the MH_OBJECT
- * file type the segments are padded out and aligned on a segment alignment
- * boundary for efficient demand pageing. The MH_EXECUTE, MH_FVMLIB, MH_DYLIB,
- * MH_DYLINKER and MH_BUNDLE file types also have the headers included as part
- * of their first segment.
- *
- * The file type MH_OBJECT is a compact format intended as output of the
- * assembler and input (and possibly output) of the link editor (the .o
- * format). All sections are in one unnamed segment with no segment padding.
- * This format is used as an executable format when the file is so small the
- * segment padding greatly increases its size.
- *
- * The file type MH_PRELOAD is an executable format intended for things that
- * are not executed under the kernel (proms, stand alones, kernels, etc). The
- * format can be executed under the kernel but may demand paged it and not
- * preload it before execution.
- *
- * A core file is in MH_CORE format and can be any in an arbritray legal
- * Mach-O file.
- *
- * Constants for the filetype field of the mach_header
- */
-#define MH_OBJECT 0x1 /* relocatable object file */
-#define MH_EXECUTE 0x2 /* demand paged executable file */
-#define MH_FVMLIB 0x3 /* fixed VM shared library file */
-#define MH_CORE 0x4 /* core file */
-#define MH_PRELOAD 0x5 /* preloaded executable file */
-#define MH_DYLIB 0x6 /* dynamically bound shared library */
-#define MH_DYLINKER 0x7 /* dynamic link editor */
-#define MH_BUNDLE 0x8 /* dynamically bound bundle file */
-#define MH_DYLIB_STUB 0x9 /* shared library stub for static */
- /* linking only, no section contents */
-#define MH_DSYM 0xa /* companion file with only debug */
- /* sections */
-#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */
-
-/* Constants for the flags field of the mach_header */
-#define MH_NOUNDEFS 0x1 /* the object file has no undefined
- references */
-#define MH_INCRLINK 0x2 /* the object file is the output of an
- incremental link against a base file
- and can't be link edited again */
-#define MH_DYLDLINK 0x4 /* the object file is input for the
- dynamic linker and can't be staticly
- link edited again */
-#define MH_BINDATLOAD 0x8 /* the object file's undefined
- references are bound by the dynamic
- linker when loaded. */
-#define MH_PREBOUND 0x10 /* the file has its dynamic undefined
- references prebound. */
-#define MH_SPLIT_SEGS 0x20 /* the file has its read-only and
- read-write segments split */
-#define MH_LAZY_INIT 0x40 /* the shared library init routine is
- to be run lazily via catching memory
- faults to its writeable segments
- (obsolete) */
-#define MH_TWOLEVEL 0x80 /* the image is using two-level name
- space bindings */
-#define MH_FORCE_FLAT 0x100 /* the executable is forcing all images
- to use flat name space bindings */
-#define MH_NOMULTIDEFS 0x200 /* this umbrella guarantees no multiple
- defintions of symbols in its
- sub-images so the two-level namespace
- hints can always be used. */
-#define MH_NOFIXPREBINDING 0x400 /* do not have dyld notify the
- prebinding agent about this
- executable */
-#define MH_PREBINDABLE 0x800 /* the binary is not prebound but can
- have its prebinding redone. only used
- when MH_PREBOUND is not set. */
-#define MH_ALLMODSBOUND 0x1000 /* indicates that this binary binds to
- all two-level namespace modules of
- its dependent libraries. only used
- when MH_PREBINDABLE and MH_TWOLEVEL
- are both set. */
-#define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000/* safe to divide up the sections into
- sub-sections via symbols for dead
- code stripping */
-#define MH_CANONICAL 0x4000 /* the binary has been canonicalized
- via the unprebind operation */
-#define MH_WEAK_DEFINES 0x8000 /* the final linked image contains
- external weak symbols */
-#define MH_BINDS_TO_WEAK 0x10000 /* the final linked image uses
- weak symbols */
-
-#define MH_ALLOW_STACK_EXECUTION 0x20000/* When this bit is set, all stacks
- in the task will be given stack
- execution privilege. Only used in
- MH_EXECUTE filetypes. */
-#define MH_ROOT_SAFE 0x40000 /* When this bit is set, the binary
- declares it is safe for use in
- processes with uid zero */
-
-#define MH_SETUID_SAFE 0x80000 /* When this bit is set, the binary
- declares it is safe for use in
- processes when issetugid() is true */
-
-#define MH_NO_REEXPORTED_DYLIBS 0x100000 /* When this bit is set on a dylib,
- the static linker does not need to
- examine dependent dylibs to see
- if any are re-exported */
-#define MH_PIE 0x200000 /* When this bit is set, the OS will
- load the main executable at a
- random address. Only used in
- MH_EXECUTE filetypes. */
-#define MH_DEAD_STRIPPABLE_DYLIB 0x400000 /* Only for use on dylibs. When
- linking against a dylib that
- has this bit set, the static linker
- will automatically not create a
- LC_LOAD_DYLIB load command to the
- dylib if no symbols are being
- referenced from the dylib. */
-#define MH_HAS_TLV_DESCRIPTORS 0x800000 /* Contains a section of type
- S_THREAD_LOCAL_VARIABLES */
-
-#define MH_NO_HEAP_EXECUTION 0x1000000 /* When this bit is set, the OS will
- run the main executable with
- a non-executable heap even on
- platforms (e.g. i386) that don't
- require it. Only used in MH_EXECUTE
- filetypes. */
-
-#define MH_APP_EXTENSION_SAFE 0x02000000 /* The code was linked for use in an
- application extension. */
-
-#define MH_NLIST_OUTOFSYNC_WITH_DYLDINFO 0x04000000 /* The external symbols
- listed in the nlist symbol table do
- not include all the symbols listed in
- the dyld info. */
-
-#define MH_SIM_SUPPORT 0x08000000 /* Allow LC_MIN_VERSION_MACOS and
- LC_BUILD_VERSION load commands with
- the platforms macOS, macCatalyst,
- iOSSimulator, tvOSSimulator and
- watchOSSimulator. */
-
-#define MH_DYLIB_IN_CACHE 0x80000000 /* Only for use on dylibs. When this bit
- is set, the dylib is part of the dyld
- shared cache, rather than loose in
- the filesystem. */
-
-/*
- * The load commands directly follow the mach_header. The total size of all
- * of the commands is given by the sizeofcmds field in the mach_header. All
- * load commands must have as their first two fields cmd and cmdsize. The cmd
- * field is filled in with a constant for that command type. Each command type
- * has a structure specifically for it. The cmdsize field is the size in bytes
- * of the particular load command structure plus anything that follows it that
- * is a part of the load command (i.e. section structures, strings, etc.). To
- * advance to the next load command the cmdsize can be added to the offset or
- * pointer of the current load command. The cmdsize for 32-bit architectures
- * MUST be a multiple of 4 bytes and for 64-bit architectures MUST be a multiple
- * of 8 bytes (these are forever the maximum alignment of any load commands).
- * The padded bytes must be zero. All tables in the object file must also
- * follow these rules so the file can be memory mapped. Otherwise the pointers
- * to these tables will not work well or at all on some machines. With all
- * padding zeroed like objects will compare byte for byte.
- */
-struct load_command {
- uint32_t cmd; /* type of load command */
- uint32_t cmdsize; /* total size of command in bytes */
-};
-
-/*
- * After MacOS X 10.1 when a new load command is added that is required to be
- * understood by the dynamic linker for the image to execute properly the
- * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic
- * linker sees such a load command it it does not understand will issue a
- * "unknown load command required for execution" error and refuse to use the
- * image. Other load commands without this bit that are not understood will
- * simply be ignored.
- */
-#define LC_REQ_DYLD 0x80000000
-
-/* Constants for the cmd field of all load commands, the type */
-#define LC_SEGMENT 0x1 /* segment of this file to be mapped */
-#define LC_SYMTAB 0x2 /* link-edit stab symbol table info */
-#define LC_SYMSEG 0x3 /* link-edit gdb symbol table info (obsolete) */
-#define LC_THREAD 0x4 /* thread */
-#define LC_UNIXTHREAD 0x5 /* unix thread (includes a stack) */
-#define LC_LOADFVMLIB 0x6 /* load a specified fixed VM shared library */
-#define LC_IDFVMLIB 0x7 /* fixed VM shared library identification */
-#define LC_IDENT 0x8 /* object identification info (obsolete) */
-#define LC_FVMFILE 0x9 /* fixed VM file inclusion (internal use) */
-#define LC_PREPAGE 0xa /* prepage command (internal use) */
-#define LC_DYSYMTAB 0xb /* dynamic link-edit symbol table info */
-#define LC_LOAD_DYLIB 0xc /* load a dynamically linked shared library */
-#define LC_ID_DYLIB 0xd /* dynamically linked shared lib ident */
-#define LC_LOAD_DYLINKER 0xe /* load a dynamic linker */
-#define LC_ID_DYLINKER 0xf /* dynamic linker identification */
-#define LC_PREBOUND_DYLIB 0x10 /* modules prebound for a dynamically */
- /* linked shared library */
-#define LC_ROUTINES 0x11 /* image routines */
-#define LC_SUB_FRAMEWORK 0x12 /* sub framework */
-#define LC_SUB_UMBRELLA 0x13 /* sub umbrella */
-#define LC_SUB_CLIENT 0x14 /* sub client */
-#define LC_SUB_LIBRARY 0x15 /* sub library */
-#define LC_TWOLEVEL_HINTS 0x16 /* two-level namespace lookup hints */
-#define LC_PREBIND_CKSUM 0x17 /* prebind checksum */
-
-/*
- * load a dynamically linked shared library that is allowed to be missing
- * (all symbols are weak imported).
- */
-#define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
-
-#define LC_SEGMENT_64 0x19 /* 64-bit segment of this file to be
- mapped */
-#define LC_ROUTINES_64 0x1a /* 64-bit image routines */
-#define LC_UUID 0x1b /* the uuid */
-#define LC_RPATH (0x1c | LC_REQ_DYLD) /* runpath additions */
-#define LC_CODE_SIGNATURE 0x1d /* local of code signature */
-#define LC_SEGMENT_SPLIT_INFO 0x1e /* local of info to split segments */
-#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) /* load and re-export dylib */
-#define LC_LAZY_LOAD_DYLIB 0x20 /* delay load of dylib until first use */
-#define LC_ENCRYPTION_INFO 0x21 /* encrypted segment information */
-#define LC_DYLD_INFO 0x22 /* compressed dyld information */
-#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) /* compressed dyld information only */
-#define LC_LOAD_UPWARD_DYLIB (0x23 | LC_REQ_DYLD) /* load upward dylib */
-#define LC_VERSION_MIN_MACOSX 0x24 /* build for MacOSX min OS version */
-#define LC_VERSION_MIN_IPHONEOS 0x25 /* build for iPhoneOS min OS version */
-#define LC_FUNCTION_STARTS 0x26 /* compressed table of function start addresses */
-#define LC_DYLD_ENVIRONMENT 0x27 /* string for dyld to treat
- like environment variable */
-#define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */
-#define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */
-#define LC_SOURCE_VERSION 0x2A /* source version used to build binary */
-#define LC_DYLIB_CODE_SIGN_DRS 0x2B /* Code signing DRs copied from linked dylibs */
-#define LC_ENCRYPTION_INFO_64 0x2C /* 64-bit encrypted segment information */
-#define LC_LINKER_OPTION 0x2D /* linker options in MH_OBJECT files */
-#define LC_LINKER_OPTIMIZATION_HINT 0x2E /* optimization hints in MH_OBJECT files */
-#define LC_VERSION_MIN_TVOS 0x2F /* build for AppleTV min OS version */
-#define LC_VERSION_MIN_WATCHOS 0x30 /* build for Watch min OS version */
-#define LC_NOTE 0x31 /* arbitrary data included within a Mach-O file */
-#define LC_BUILD_VERSION 0x32 /* build for platform min OS version */
-#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) /* used with linkedit_data_command, payload is trie */
-#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) /* used with linkedit_data_command */
-
-/*
- * A variable length string in a load command is represented by an lc_str
- * union. The strings are stored just after the load command structure and
- * the offset is from the start of the load command structure. The size
- * of the string is reflected in the cmdsize field of the load command.
- * Once again any padded bytes to bring the cmdsize field to a multiple
- * of 4 bytes must be zero.
- */
-union lc_str {
- uint32_t offset; /* offset to the string */
-#ifndef __LP64__
- char *ptr; /* pointer to the string */
-#endif
-};
-
-/*
- * The segment load command indicates that a part of this file is to be
- * mapped into the task's address space. The size of this segment in memory,
- * vmsize, maybe equal to or larger than the amount to map from this file,
- * filesize. The file is mapped starting at fileoff to the beginning of
- * the segment in memory, vmaddr. The rest of the memory of the segment,
- * if any, is allocated zero fill on demand. The segment's maximum virtual
- * memory protection and initial virtual memory protection are specified
- * by the maxprot and initprot fields. If the segment has sections then the
- * section structures directly follow the segment command and their size is
- * reflected in cmdsize.
- */
-struct segment_command { /* for 32-bit architectures */
- uint32_t cmd; /* LC_SEGMENT */
- uint32_t cmdsize; /* includes sizeof section structs */
- char segname[16]; /* segment name */
- uint32_t vmaddr; /* memory address of this segment */
- uint32_t vmsize; /* memory size of this segment */
- uint32_t fileoff; /* file offset of this segment */
- uint32_t filesize; /* amount to map from the file */
- vm_prot_t maxprot; /* maximum VM protection */
- vm_prot_t initprot; /* initial VM protection */
- uint32_t nsects; /* number of sections in segment */
- uint32_t flags; /* flags */
-};
-
-/*
- * The 64-bit segment load command indicates that a part of this file is to be
- * mapped into a 64-bit task's address space. If the 64-bit segment has
- * sections then section_64 structures directly follow the 64-bit segment
- * command and their size is reflected in cmdsize.
- */
-struct segment_command_64 { /* for 64-bit architectures */
- uint32_t cmd; /* LC_SEGMENT_64 */
- uint32_t cmdsize; /* includes sizeof section_64 structs */
- char segname[16]; /* segment name */
- uint64_t vmaddr; /* memory address of this segment */
- uint64_t vmsize; /* memory size of this segment */
- uint64_t fileoff; /* file offset of this segment */
- uint64_t filesize; /* amount to map from the file */
- vm_prot_t maxprot; /* maximum VM protection */
- vm_prot_t initprot; /* initial VM protection */
- uint32_t nsects; /* number of sections in segment */
- uint32_t flags; /* flags */
-};
-
-/* Constants for the flags field of the segment_command */
-#define SG_HIGHVM 0x1 /* the file contents for this segment is for
- the high part of the VM space, the low part
- is zero filled (for stacks in core files) */
-#define SG_FVMLIB 0x2 /* this segment is the VM that is allocated by
- a fixed VM library, for overlap checking in
- the link editor */
-#define SG_NORELOC 0x4 /* this segment has nothing that was relocated
- in it and nothing relocated to it, that is
- it maybe safely replaced without relocation*/
-#define SG_PROTECTED_VERSION_1 0x8 /* This segment is protected. If the
- segment starts at file offset 0, the
- first page of the segment is not
- protected. All other pages of the
- segment are protected. */
-#define SG_READ_ONLY 0x10 /* This segment is made read-only after fixups */
-
-
-
-/*
- * A segment is made up of zero or more sections. Non-MH_OBJECT files have
- * all of their segments with the proper sections in each, and padded to the
- * specified segment alignment when produced by the link editor. The first
- * segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header
- * and load commands of the object file before its first section. The zero
- * fill sections are always last in their segment (in all formats). This
- * allows the zeroed segment padding to be mapped into memory where zero fill
- * sections might be. The gigabyte zero fill sections, those with the section
- * type S_GB_ZEROFILL, can only be in a segment with sections of this type.
- * These segments are then placed after all other segments.
- *
- * The MH_OBJECT format has all of its sections in one segment for
- * compactness. There is no padding to a specified segment boundary and the
- * mach_header and load commands are not part of the segment.
- *
- * Sections with the same section name, sectname, going into the same segment,
- * segname, are combined by the link editor. The resulting section is aligned
- * to the maximum alignment of the combined sections and is the new section's
- * alignment. The combined sections are aligned to their original alignment in
- * the combined section. Any padded bytes to get the specified alignment are
- * zeroed.
- *
- * The format of the relocation entries referenced by the reloff and nreloc
- * fields of the section structure for mach object files is described in the
- * header file .
- */
-struct section { /* for 32-bit architectures */
- char sectname[16]; /* name of this section */
- char segname[16]; /* segment this section goes in */
- uint32_t addr; /* memory address of this section */
- uint32_t size; /* size in bytes of this section */
- uint32_t offset; /* file offset of this section */
- uint32_t align; /* section alignment (power of 2) */
- uint32_t reloff; /* file offset of relocation entries */
- uint32_t nreloc; /* number of relocation entries */
- uint32_t flags; /* flags (section type and attributes)*/
- uint32_t reserved1; /* reserved (for offset or index) */
- uint32_t reserved2; /* reserved (for count or sizeof) */
-};
-
-struct section_64 { /* for 64-bit architectures */
- char sectname[16]; /* name of this section */
- char segname[16]; /* segment this section goes in */
- uint64_t addr; /* memory address of this section */
- uint64_t size; /* size in bytes of this section */
- uint32_t offset; /* file offset of this section */
- uint32_t align; /* section alignment (power of 2) */
- uint32_t reloff; /* file offset of relocation entries */
- uint32_t nreloc; /* number of relocation entries */
- uint32_t flags; /* flags (section type and attributes)*/
- uint32_t reserved1; /* reserved (for offset or index) */
- uint32_t reserved2; /* reserved (for count or sizeof) */
- uint32_t reserved3; /* reserved */
-};
-
-/*
- * The flags field of a section structure is separated into two parts a section
- * type and section attributes. The section types are mutually exclusive (it
- * can only have one type) but the section attributes are not (it may have more
- * than one attribute).
- */
-#define SECTION_TYPE 0x000000ff /* 256 section types */
-#define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes */
-
-/* Constants for the type of a section */
-#define S_REGULAR 0x0 /* regular section */
-#define S_ZEROFILL 0x1 /* zero fill on demand section */
-#define S_CSTRING_LITERALS 0x2 /* section with only literal C strings*/
-#define S_4BYTE_LITERALS 0x3 /* section with only 4 byte literals */
-#define S_8BYTE_LITERALS 0x4 /* section with only 8 byte literals */
-#define S_LITERAL_POINTERS 0x5 /* section with only pointers to */
- /* literals */
-/*
- * For the two types of symbol pointers sections and the symbol stubs section
- * they have indirect symbol table entries. For each of the entries in the
- * section the indirect symbol table entries, in corresponding order in the
- * indirect symbol table, start at the index stored in the reserved1 field
- * of the section structure. Since the indirect symbol table entries
- * correspond to the entries in the section the number of indirect symbol table
- * entries is inferred from the size of the section divided by the size of the
- * entries in the section. For symbol pointers sections the size of the entries
- * in the section is 4 bytes and for symbol stubs sections the byte size of the
- * stubs is stored in the reserved2 field of the section structure.
- */
-#define S_NON_LAZY_SYMBOL_POINTERS 0x6 /* section with only non-lazy
- symbol pointers */
-#define S_LAZY_SYMBOL_POINTERS 0x7 /* section with only lazy symbol
- pointers */
-#define S_SYMBOL_STUBS 0x8 /* section with only symbol
- stubs, byte size of stub in
- the reserved2 field */
-#define S_MOD_INIT_FUNC_POINTERS 0x9 /* section with only function
- pointers for initialization*/
-#define S_MOD_TERM_FUNC_POINTERS 0xa /* section with only function
- pointers for termination */
-#define S_COALESCED 0xb /* section contains symbols that
- are to be coalesced */
-#define S_GB_ZEROFILL 0xc /* zero fill on demand section
- (that can be larger than 4
- gigabytes) */
-#define S_INTERPOSING 0xd /* section with only pairs of
- function pointers for
- interposing */
-#define S_16BYTE_LITERALS 0xe /* section with only 16 byte
- literals */
-#define S_DTRACE_DOF 0xf /* section contains
- DTrace Object Format */
-#define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10 /* section with only lazy
- symbol pointers to lazy
- loaded dylibs */
-/*
- * Section types to support thread local variables
- */
-#define S_THREAD_LOCAL_REGULAR 0x11 /* template of initial
- values for TLVs */
-#define S_THREAD_LOCAL_ZEROFILL 0x12 /* template of initial
- values for TLVs */
-#define S_THREAD_LOCAL_VARIABLES 0x13 /* TLV descriptors */
-#define S_THREAD_LOCAL_VARIABLE_POINTERS 0x14 /* pointers to TLV
- descriptors */
-#define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS 0x15 /* functions to call
- to initialize TLV
- values */
-#define S_INIT_FUNC_OFFSETS 0x16 /* 32-bit offsets to
- initializers */
-
-/*
- * Constants for the section attributes part of the flags field of a section
- * structure.
- */
-#define SECTION_ATTRIBUTES_USR 0xff000000 /* User setable attributes */
-#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section contains only true
- machine instructions */
-#define S_ATTR_NO_TOC 0x40000000 /* section contains coalesced
- symbols that are not to be
- in a ranlib table of
- contents */
-#define S_ATTR_STRIP_STATIC_SYMS 0x20000000 /* ok to strip static symbols
- in this section in files
- with the MH_DYLDLINK flag */
-#define S_ATTR_NO_DEAD_STRIP 0x10000000 /* no dead stripping */
-#define S_ATTR_LIVE_SUPPORT 0x08000000 /* blocks are live if they
- reference live blocks */
-#define S_ATTR_SELF_MODIFYING_CODE 0x04000000 /* Used with i386 code stubs
- written on by dyld */
-/*
- * If a segment contains any sections marked with S_ATTR_DEBUG then all
- * sections in that segment must have this attribute. No section other than
- * a section marked with this attribute may reference the contents of this
- * section. A section with this attribute may contain no symbols and must have
- * a section type S_REGULAR. The static linker will not copy section contents
- * from sections with this attribute into its output file. These sections
- * generally contain DWARF debugging info.
- */
-#define S_ATTR_DEBUG 0x02000000 /* a debug section */
-#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
-#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
- machine instructions */
-#define S_ATTR_EXT_RELOC 0x00000200 /* section has external
- relocation entries */
-#define S_ATTR_LOC_RELOC 0x00000100 /* section has local
- relocation entries */
-
-
-/*
- * The names of segments and sections in them are mostly meaningless to the
- * link-editor. But there are few things to support traditional UNIX
- * executables that require the link-editor and assembler to use some names
- * agreed upon by convention.
- *
- * The initial protection of the "__TEXT" segment has write protection turned
- * off (not writeable).
- *
- * The link-editor will allocate common symbols at the end of the "__common"
- * section in the "__DATA" segment. It will create the section and segment
- * if needed.
- */
-
-/* The currently known segment names and the section names in those segments */
-
-#define SEG_PAGEZERO "__PAGEZERO" /* the pagezero segment which has no */
- /* protections and catches NULL */
- /* references for MH_EXECUTE files */
-
-
-#define SEG_TEXT "__TEXT" /* the tradition UNIX text segment */
-#define SECT_TEXT "__text" /* the real text part of the text */
- /* section no headers, and no padding */
-#define SECT_FVMLIB_INIT0 "__fvmlib_init0" /* the fvmlib initialization */
- /* section */
-#define SECT_FVMLIB_INIT1 "__fvmlib_init1" /* the section following the */
- /* fvmlib initialization */
- /* section */
-
-#define SEG_DATA "__DATA" /* the tradition UNIX data segment */
-#define SECT_DATA "__data" /* the real initialized data section */
- /* no padding, no bss overlap */
-#define SECT_BSS "__bss" /* the real uninitialized data section*/
- /* no padding */
-#define SECT_COMMON "__common" /* the section common symbols are */
- /* allocated in by the link editor */
-
-#define SEG_OBJC "__OBJC" /* objective-C runtime segment */
-#define SECT_OBJC_SYMBOLS "__symbol_table" /* symbol table */
-#define SECT_OBJC_MODULES "__module_info" /* module information */
-#define SECT_OBJC_STRINGS "__selector_strs" /* string table */
-#define SECT_OBJC_REFS "__selector_refs" /* string table */
-
-#define SEG_ICON "__ICON" /* the icon segment */
-#define SECT_ICON_HEADER "__header" /* the icon headers */
-#define SECT_ICON_TIFF "__tiff" /* the icons in tiff format */
-
-#define SEG_LINKEDIT "__LINKEDIT" /* the segment containing all structs */
- /* created and maintained by the link */
- /* editor. Created with -seglinkedit */
- /* option to ld(1) for MH_EXECUTE and */
- /* FVMLIB file types only */
-
-#define SEG_UNIXSTACK "__UNIXSTACK" /* the unix stack segment */
-
-#define SEG_IMPORT "__IMPORT" /* the segment for the self (dyld) */
- /* modifing code stubs that has read, */
- /* write and execute permissions */
-
-/*
- * Fixed virtual memory shared libraries are identified by two things. The
- * target pathname (the name of the library as found for execution), and the
- * minor version number. The address of where the headers are loaded is in
- * header_addr. (THIS IS OBSOLETE and no longer supported).
- */
-struct fvmlib {
- union lc_str name; /* library's target pathname */
- uint32_t minor_version; /* library's minor version number */
- uint32_t header_addr; /* library's header address */
-};
-
-/*
- * A fixed virtual shared library (filetype == MH_FVMLIB in the mach header)
- * contains a fvmlib_command (cmd == LC_IDFVMLIB) to identify the library.
- * An object that uses a fixed virtual shared library also contains a
- * fvmlib_command (cmd == LC_LOADFVMLIB) for each library it uses.
- * (THIS IS OBSOLETE and no longer supported).
- */
-struct fvmlib_command {
- uint32_t cmd; /* LC_IDFVMLIB or LC_LOADFVMLIB */
- uint32_t cmdsize; /* includes pathname string */
- struct fvmlib fvmlib; /* the library identification */
-};
-
-/*
- * Dynamicly linked shared libraries are identified by two things. The
- * pathname (the name of the library as found for execution), and the
- * compatibility version number. The pathname must match and the compatibility
- * number in the user of the library must be greater than or equal to the
- * library being used. The time stamp is used to record the time a library was
- * built and copied into user so it can be use to determined if the library used
- * at runtime is exactly the same as used to built the program.
- */
-struct dylib {
- union lc_str name; /* library's path name */
- uint32_t timestamp; /* library's build time stamp */
- uint32_t current_version; /* library's current version number */
- uint32_t compatibility_version; /* library's compatibility vers number*/
-};
-
-/*
- * A dynamically linked shared library (filetype == MH_DYLIB in the mach header)
- * contains a dylib_command (cmd == LC_ID_DYLIB) to identify the library.
- * An object that uses a dynamically linked shared library also contains a
- * dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or
- * LC_REEXPORT_DYLIB) for each library it uses.
- */
-struct dylib_command {
- uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,
- LC_REEXPORT_DYLIB */
- uint32_t cmdsize; /* includes pathname string */
- struct dylib dylib; /* the library identification */
-};
-
-/*
- * A dynamically linked shared library may be a subframework of an umbrella
- * framework. If so it will be linked with "-umbrella umbrella_name" where
- * Where "umbrella_name" is the name of the umbrella framework. A subframework
- * can only be linked against by its umbrella framework or other subframeworks
- * that are part of the same umbrella framework. Otherwise the static link
- * editor produces an error and states to link against the umbrella framework.
- * The name of the umbrella framework for subframeworks is recorded in the
- * following structure.
- */
-struct sub_framework_command {
- uint32_t cmd; /* LC_SUB_FRAMEWORK */
- uint32_t cmdsize; /* includes umbrella string */
- union lc_str umbrella; /* the umbrella framework name */
-};
-
-/*
- * For dynamically linked shared libraries that are subframework of an umbrella
- * framework they can allow clients other than the umbrella framework or other
- * subframeworks in the same umbrella framework. To do this the subframework
- * is built with "-allowable_client client_name" and an LC_SUB_CLIENT load
- * command is created for each -allowable_client flag. The client_name is
- * usually a framework name. It can also be a name used for bundles clients
- * where the bundle is built with "-client_name client_name".
- */
-struct sub_client_command {
- uint32_t cmd; /* LC_SUB_CLIENT */
- uint32_t cmdsize; /* includes client string */
- union lc_str client; /* the client name */
-};
-
-/*
- * A dynamically linked shared library may be a sub_umbrella of an umbrella
- * framework. If so it will be linked with "-sub_umbrella umbrella_name" where
- * Where "umbrella_name" is the name of the sub_umbrella framework. When
- * staticly linking when -twolevel_namespace is in effect a twolevel namespace
- * umbrella framework will only cause its subframeworks and those frameworks
- * listed as sub_umbrella frameworks to be implicited linked in. Any other
- * dependent dynamic libraries will not be linked it when -twolevel_namespace
- * is in effect. The primary library recorded by the static linker when
- * resolving a symbol in these libraries will be the umbrella framework.
- * Zero or more sub_umbrella frameworks may be use by an umbrella framework.
- * The name of a sub_umbrella framework is recorded in the following structure.
- */
-struct sub_umbrella_command {
- uint32_t cmd; /* LC_SUB_UMBRELLA */
- uint32_t cmdsize; /* includes sub_umbrella string */
- union lc_str sub_umbrella; /* the sub_umbrella framework name */
-};
-
-/*
- * A dynamically linked shared library may be a sub_library of another shared
- * library. If so it will be linked with "-sub_library library_name" where
- * Where "library_name" is the name of the sub_library shared library. When
- * staticly linking when -twolevel_namespace is in effect a twolevel namespace
- * shared library will only cause its subframeworks and those frameworks
- * listed as sub_umbrella frameworks and libraries listed as sub_libraries to
- * be implicited linked in. Any other dependent dynamic libraries will not be
- * linked it when -twolevel_namespace is in effect. The primary library
- * recorded by the static linker when resolving a symbol in these libraries
- * will be the umbrella framework (or dynamic library). Zero or more sub_library
- * shared libraries may be use by an umbrella framework or (or dynamic library).
- * The name of a sub_library framework is recorded in the following structure.
- * For example /usr/lib/libobjc_profile.A.dylib would be recorded as "libobjc".
- */
-struct sub_library_command {
- uint32_t cmd; /* LC_SUB_LIBRARY */
- uint32_t cmdsize; /* includes sub_library string */
- union lc_str sub_library; /* the sub_library name */
-};
-
-/*
- * A program (filetype == MH_EXECUTE) that is
- * prebound to its dynamic libraries has one of these for each library that
- * the static linker used in prebinding. It contains a bit vector for the
- * modules in the library. The bits indicate which modules are bound (1) and
- * which are not (0) from the library. The bit for module 0 is the low bit
- * of the first byte. So the bit for the Nth module is:
- * (linked_modules[N/8] >> N%8) & 1
- */
-struct prebound_dylib_command {
- uint32_t cmd; /* LC_PREBOUND_DYLIB */
- uint32_t cmdsize; /* includes strings */
- union lc_str name; /* library's path name */
- uint32_t nmodules; /* number of modules in library */
- union lc_str linked_modules; /* bit vector of linked modules */
-};
-
-/*
- * A program that uses a dynamic linker contains a dylinker_command to identify
- * the name of the dynamic linker (LC_LOAD_DYLINKER). And a dynamic linker
- * contains a dylinker_command to identify the dynamic linker (LC_ID_DYLINKER).
- * A file can have at most one of these.
- * This struct is also used for the LC_DYLD_ENVIRONMENT load command and
- * contains string for dyld to treat like environment variable.
- */
-struct dylinker_command {
- uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or
- LC_DYLD_ENVIRONMENT */
- uint32_t cmdsize; /* includes pathname string */
- union lc_str name; /* dynamic linker's path name */
-};
-
-/*
- * Thread commands contain machine-specific data structures suitable for
- * use in the thread state primitives. The machine specific data structures
- * follow the struct thread_command as follows.
- * Each flavor of machine specific data structure is preceded by an uint32_t
- * constant for the flavor of that data structure, an uint32_t that is the
- * count of uint32_t's of the size of the state data structure and then
- * the state data structure follows. This triple may be repeated for many
- * flavors. The constants for the flavors, counts and state data structure
- * definitions are expected to be in the header file .
- * These machine specific data structures sizes must be multiples of
- * 4 bytes. The cmdsize reflects the total size of the thread_command
- * and all of the sizes of the constants for the flavors, counts and state
- * data structures.
- *
- * For executable objects that are unix processes there will be one
- * thread_command (cmd == LC_UNIXTHREAD) created for it by the link-editor.
- * This is the same as a LC_THREAD, except that a stack is automatically
- * created (based on the shell's limit for the stack size). Command arguments
- * and environment variables are copied onto that stack.
- */
-struct thread_command {
- uint32_t cmd; /* LC_THREAD or LC_UNIXTHREAD */
- uint32_t cmdsize; /* total size of this command */
- /* uint32_t flavor flavor of thread state */
- /* uint32_t count count of uint32_t's in thread state */
- /* struct XXX_thread_state state thread state for this flavor */
- /* ... */
-};
-
-/*
- * The routines command contains the address of the dynamic shared library
- * initialization routine and an index into the module table for the module
- * that defines the routine. Before any modules are used from the library the
- * dynamic linker fully binds the module that defines the initialization routine
- * and then calls it. This gets called before any module initialization
- * routines (used for C++ static constructors) in the library.
- */
-struct routines_command { /* for 32-bit architectures */
- uint32_t cmd; /* LC_ROUTINES */
- uint32_t cmdsize; /* total size of this command */
- uint32_t init_address; /* address of initialization routine */
- uint32_t init_module; /* index into the module table that */
- /* the init routine is defined in */
- uint32_t reserved1;
- uint32_t reserved2;
- uint32_t reserved3;
- uint32_t reserved4;
- uint32_t reserved5;
- uint32_t reserved6;
-};
-
-/*
- * The 64-bit routines command. Same use as above.
- */
-struct routines_command_64 { /* for 64-bit architectures */
- uint32_t cmd; /* LC_ROUTINES_64 */
- uint32_t cmdsize; /* total size of this command */
- uint64_t init_address; /* address of initialization routine */
- uint64_t init_module; /* index into the module table that */
- /* the init routine is defined in */
- uint64_t reserved1;
- uint64_t reserved2;
- uint64_t reserved3;
- uint64_t reserved4;
- uint64_t reserved5;
- uint64_t reserved6;
-};
-
-/*
- * The symtab_command contains the offsets and sizes of the link-edit 4.3BSD
- * "stab" style symbol table information as described in the header files
- * and .
- */
-struct symtab_command {
- uint32_t cmd; /* LC_SYMTAB */
- uint32_t cmdsize; /* sizeof(struct symtab_command) */
- uint32_t symoff; /* symbol table offset */
- uint32_t nsyms; /* number of symbol table entries */
- uint32_t stroff; /* string table offset */
- uint32_t strsize; /* string table size in bytes */
-};
-
-/*
- * This is the second set of the symbolic information which is used to support
- * the data structures for the dynamically link editor.
- *
- * The original set of symbolic information in the symtab_command which contains
- * the symbol and string tables must also be present when this load command is
- * present. When this load command is present the symbol table is organized
- * into three groups of symbols:
- * local symbols (static and debugging symbols) - grouped by module
- * defined external symbols - grouped by module (sorted by name if not lib)
- * undefined external symbols (sorted by name if MH_BINDATLOAD is not set,
- * and in order the were seen by the static
- * linker if MH_BINDATLOAD is set)
- * In this load command there are offsets and counts to each of the three groups
- * of symbols.
- *
- * This load command contains a the offsets and sizes of the following new
- * symbolic information tables:
- * table of contents
- * module table
- * reference symbol table
- * indirect symbol table
- * The first three tables above (the table of contents, module table and
- * reference symbol table) are only present if the file is a dynamically linked
- * shared library. For executable and object modules, which are files
- * containing only one module, the information that would be in these three
- * tables is determined as follows:
- * table of contents - the defined external symbols are sorted by name
- * module table - the file contains only one module so everything in the
- * file is part of the module.
- * reference symbol table - is the defined and undefined external symbols
- *
- * For dynamically linked shared library files this load command also contains
- * offsets and sizes to the pool of relocation entries for all sections
- * separated into two groups:
- * external relocation entries
- * local relocation entries
- * For executable and object modules the relocation entries continue to hang
- * off the section structures.
- */
-struct dysymtab_command {
- uint32_t cmd; /* LC_DYSYMTAB */
- uint32_t cmdsize; /* sizeof(struct dysymtab_command) */
-
- /*
- * The symbols indicated by symoff and nsyms of the LC_SYMTAB load command
- * are grouped into the following three groups:
- * local symbols (further grouped by the module they are from)
- * defined external symbols (further grouped by the module they are from)
- * undefined symbols
- *
- * The local symbols are used only for debugging. The dynamic binding
- * process may have to use them to indicate to the debugger the local
- * symbols for a module that is being bound.
- *
- * The last two groups are used by the dynamic binding process to do the
- * binding (indirectly through the module table and the reference symbol
- * table when this is a dynamically linked shared library file).
- */
- uint32_t ilocalsym; /* index to local symbols */
- uint32_t nlocalsym; /* number of local symbols */
-
- uint32_t iextdefsym;/* index to externally defined symbols */
- uint32_t nextdefsym;/* number of externally defined symbols */
-
- uint32_t iundefsym; /* index to undefined symbols */
- uint32_t nundefsym; /* number of undefined symbols */
-
- /*
- * For the for the dynamic binding process to find which module a symbol
- * is defined in the table of contents is used (analogous to the ranlib
- * structure in an archive) which maps defined external symbols to modules
- * they are defined in. This exists only in a dynamically linked shared
- * library file. For executable and object modules the defined external
- * symbols are sorted by name and is use as the table of contents.
- */
- uint32_t tocoff; /* file offset to table of contents */
- uint32_t ntoc; /* number of entries in table of contents */
-
- /*
- * To support dynamic binding of "modules" (whole object files) the symbol
- * table must reflect the modules that the file was created from. This is
- * done by having a module table that has indexes and counts into the merged
- * tables for each module. The module structure that these two entries
- * refer to is described below. This exists only in a dynamically linked
- * shared library file. For executable and object modules the file only
- * contains one module so everything in the file belongs to the module.
- */
- uint32_t modtaboff; /* file offset to module table */
- uint32_t nmodtab; /* number of module table entries */
-
- /*
- * To support dynamic module binding the module structure for each module
- * indicates the external references (defined and undefined) each module
- * makes. For each module there is an offset and a count into the
- * reference symbol table for the symbols that the module references.
- * This exists only in a dynamically linked shared library file. For
- * executable and object modules the defined external symbols and the
- * undefined external symbols indicates the external references.
- */
- uint32_t extrefsymoff; /* offset to referenced symbol table */
- uint32_t nextrefsyms; /* number of referenced symbol table entries */
-
- /*
- * The sections that contain "symbol pointers" and "routine stubs" have
- * indexes and (implied counts based on the size of the section and fixed
- * size of the entry) into the "indirect symbol" table for each pointer
- * and stub. For every section of these two types the index into the
- * indirect symbol table is stored in the section header in the field
- * reserved1. An indirect symbol table entry is simply a 32bit index into
- * the symbol table to the symbol that the pointer or stub is referring to.
- * The indirect symbol table is ordered to match the entries in the section.
- */
- uint32_t indirectsymoff; /* file offset to the indirect symbol table */
- uint32_t nindirectsyms; /* number of indirect symbol table entries */
-
- /*
- * To support relocating an individual module in a library file quickly the
- * external relocation entries for each module in the library need to be
- * accessed efficiently. Since the relocation entries can't be accessed
- * through the section headers for a library file they are separated into
- * groups of local and external entries further grouped by module. In this
- * case the presents of this load command who's extreloff, nextrel,
- * locreloff and nlocrel fields are non-zero indicates that the relocation
- * entries of non-merged sections are not referenced through the section
- * structures (and the reloff and nreloc fields in the section headers are
- * set to zero).
- *
- * Since the relocation entries are not accessed through the section headers
- * this requires the r_address field to be something other than a section
- * offset to identify the item to be relocated. In this case r_address is
- * set to the offset from the vmaddr of the first LC_SEGMENT command.
- * For MH_SPLIT_SEGS images r_address is set to the the offset from the
- * vmaddr of the first read-write LC_SEGMENT command.
- *
- * The relocation entries are grouped by module and the module table
- * entries have indexes and counts into them for the group of external
- * relocation entries for that the module.
- *
- * For sections that are merged across modules there must not be any
- * remaining external relocation entries for them (for merged sections
- * remaining relocation entries must be local).
- */
- uint32_t extreloff; /* offset to external relocation entries */
- uint32_t nextrel; /* number of external relocation entries */
-
- /*
- * All the local relocation entries are grouped together (they are not
- * grouped by their module since they are only used if the object is moved
- * from it staticly link edited address).
- */
- uint32_t locreloff; /* offset to local relocation entries */
- uint32_t nlocrel; /* number of local relocation entries */
-
-};
-
-/*
- * An indirect symbol table entry is simply a 32bit index into the symbol table
- * to the symbol that the pointer or stub is refering to. Unless it is for a
- * non-lazy symbol pointer section for a defined symbol which strip(1) as
- * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the
- * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that.
- */
-#define INDIRECT_SYMBOL_LOCAL 0x80000000
-#define INDIRECT_SYMBOL_ABS 0x40000000
-
-
-/* a table of contents entry */
-struct dylib_table_of_contents {
- uint32_t symbol_index; /* the defined external symbol
- (index into the symbol table) */
- uint32_t module_index; /* index into the module table this symbol
- is defined in */
-};
-
-/* a module table entry */
-struct dylib_module {
- uint32_t module_name; /* the module name (index into string table) */
-
- uint32_t iextdefsym; /* index into externally defined symbols */
- uint32_t nextdefsym; /* number of externally defined symbols */
- uint32_t irefsym; /* index into reference symbol table */
- uint32_t nrefsym; /* number of reference symbol table entries */
- uint32_t ilocalsym; /* index into symbols for local symbols */
- uint32_t nlocalsym; /* number of local symbols */
-
- uint32_t iextrel; /* index into external relocation entries */
- uint32_t nextrel; /* number of external relocation entries */
-
- uint32_t iinit_iterm; /* low 16 bits are the index into the init
- section, high 16 bits are the index into
- the term section */
- uint32_t ninit_nterm; /* low 16 bits are the number of init section
- entries, high 16 bits are the number of
- term section entries */
-
- uint32_t /* for this module address of the start of */
- objc_module_info_addr; /* the (__OBJC,__module_info) section */
- uint32_t /* for this module size of */
- objc_module_info_size; /* the (__OBJC,__module_info) section */
-};
-
-/* a 64-bit module table entry */
-struct dylib_module_64 {
- uint32_t module_name; /* the module name (index into string table) */
-
- uint32_t iextdefsym; /* index into externally defined symbols */
- uint32_t nextdefsym; /* number of externally defined symbols */
- uint32_t irefsym; /* index into reference symbol table */
- uint32_t nrefsym; /* number of reference symbol table entries */
- uint32_t ilocalsym; /* index into symbols for local symbols */
- uint32_t nlocalsym; /* number of local symbols */
-
- uint32_t iextrel; /* index into external relocation entries */
- uint32_t nextrel; /* number of external relocation entries */
-
- uint32_t iinit_iterm; /* low 16 bits are the index into the init
- section, high 16 bits are the index into
- the term section */
- uint32_t ninit_nterm; /* low 16 bits are the number of init section
- entries, high 16 bits are the number of
- term section entries */
-
- uint32_t /* for this module size of */
- objc_module_info_size; /* the (__OBJC,__module_info) section */
- uint64_t /* for this module address of the start of */
- objc_module_info_addr; /* the (__OBJC,__module_info) section */
-};
-
-/*
- * The entries in the reference symbol table are used when loading the module
- * (both by the static and dynamic link editors) and if the module is unloaded
- * or replaced. Therefore all external symbols (defined and undefined) are
- * listed in the module's reference table. The flags describe the type of
- * reference that is being made. The constants for the flags are defined in
- * as they are also used for symbol table entries.
- */
-struct dylib_reference {
- uint32_t isym:24, /* index into the symbol table */
- flags:8; /* flags to indicate the type of reference */
-};
-
-/*
- * The twolevel_hints_command contains the offset and number of hints in the
- * two-level namespace lookup hints table.
- */
-struct twolevel_hints_command {
- uint32_t cmd; /* LC_TWOLEVEL_HINTS */
- uint32_t cmdsize; /* sizeof(struct twolevel_hints_command) */
- uint32_t offset; /* offset to the hint table */
- uint32_t nhints; /* number of hints in the hint table */
-};
-
-/*
- * The entries in the two-level namespace lookup hints table are twolevel_hint
- * structs. These provide hints to the dynamic link editor where to start
- * looking for an undefined symbol in a two-level namespace image. The
- * isub_image field is an index into the sub-images (sub-frameworks and
- * sub-umbrellas list) that made up the two-level image that the undefined
- * symbol was found in when it was built by the static link editor. If
- * isub-image is 0 the the symbol is expected to be defined in library and not
- * in the sub-images. If isub-image is non-zero it is an index into the array
- * of sub-images for the umbrella with the first index in the sub-images being
- * 1. The array of sub-images is the ordered list of sub-images of the umbrella
- * that would be searched for a symbol that has the umbrella recorded as its
- * primary library. The table of contents index is an index into the
- * library's table of contents. This is used as the starting point of the
- * binary search or a directed linear search.
- */
-struct twolevel_hint {
- uint32_t
- isub_image:8, /* index into the sub images */
- itoc:24; /* index into the table of contents */
-};
-
-/*
- * The prebind_cksum_command contains the value of the original check sum for
- * prebound files or zero. When a prebound file is first created or modified
- * for other than updating its prebinding information the value of the check sum
- * is set to zero. When the file has it prebinding re-done and if the value of
- * the check sum is zero the original check sum is calculated and stored in
- * cksum field of this load command in the output file. If when the prebinding
- * is re-done and the cksum field is non-zero it is left unchanged from the
- * input file.
- */
-struct prebind_cksum_command {
- uint32_t cmd; /* LC_PREBIND_CKSUM */
- uint32_t cmdsize; /* sizeof(struct prebind_cksum_command) */
- uint32_t cksum; /* the check sum or zero */
-};
-
-/*
- * The uuid load command contains a single 128-bit unique random number that
- * identifies an object produced by the static link editor.
- */
-struct uuid_command {
- uint32_t cmd; /* LC_UUID */
- uint32_t cmdsize; /* sizeof(struct uuid_command) */
- uint8_t uuid[16]; /* the 128-bit uuid */
-};
-
-/*
- * The rpath_command contains a path which at runtime should be added to
- * the current run path used to find @rpath prefixed dylibs.
- */
-struct rpath_command {
- uint32_t cmd; /* LC_RPATH */
- uint32_t cmdsize; /* includes string */
- union lc_str path; /* path to add to run path */
-};
-
-/*
- * The linkedit_data_command contains the offsets and sizes of a blob
- * of data in the __LINKEDIT segment.
- */
-struct linkedit_data_command {
- uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
- LC_FUNCTION_STARTS, LC_DATA_IN_CODE,
- LC_DYLIB_CODE_SIGN_DRS,
- LC_LINKER_OPTIMIZATION_HINT,
- LC_DYLD_EXPORTS_TRIE, or
- LC_DYLD_CHAINED_FIXUPS. */
- uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */
- uint32_t dataoff; /* file offset of data in __LINKEDIT segment */
- uint32_t datasize; /* file size of data in __LINKEDIT segment */
-};
-
-/*
- * The encryption_info_command contains the file offset and size of an
- * of an encrypted segment.
- */
-struct encryption_info_command {
- uint32_t cmd; /* LC_ENCRYPTION_INFO */
- uint32_t cmdsize; /* sizeof(struct encryption_info_command) */
- uint32_t cryptoff; /* file offset of encrypted range */
- uint32_t cryptsize; /* file size of encrypted range */
- uint32_t cryptid; /* which enryption system,
- 0 means not-encrypted yet */
-};
-
-/*
- * The encryption_info_command_64 contains the file offset and size of an
- * of an encrypted segment (for use in x86_64 targets).
- */
-struct encryption_info_command_64 {
- uint32_t cmd; /* LC_ENCRYPTION_INFO_64 */
- uint32_t cmdsize; /* sizeof(struct encryption_info_command_64) */
- uint32_t cryptoff; /* file offset of encrypted range */
- uint32_t cryptsize; /* file size of encrypted range */
- uint32_t cryptid; /* which enryption system,
- 0 means not-encrypted yet */
- uint32_t pad; /* padding to make this struct's size a multiple
- of 8 bytes */
-};
-
-/*
- * The version_min_command contains the min OS version on which this
- * binary was built to run.
- */
-struct version_min_command {
- uint32_t cmd; /* LC_VERSION_MIN_MACOSX or
- LC_VERSION_MIN_IPHONEOS or
- LC_VERSION_MIN_WATCHOS or
- LC_VERSION_MIN_TVOS */
- uint32_t cmdsize; /* sizeof(struct min_version_command) */
- uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
- uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
-};
-
-/*
- * The build_version_command contains the min OS version on which this
- * binary was built to run for its platform. The list of known platforms and
- * tool values following it.
- */
-struct build_version_command {
- uint32_t cmd; /* LC_BUILD_VERSION */
- uint32_t cmdsize; /* sizeof(struct build_version_command) plus */
- /* ntools * sizeof(struct build_tool_version) */
- uint32_t platform; /* platform */
- uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
- uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
- uint32_t ntools; /* number of tool entries following this */
-};
-
-struct build_tool_version {
- uint32_t tool; /* enum for the tool */
- uint32_t version; /* version number of the tool */
-};
-
-/* Known values for the platform field above. */
-#define PLATFORM_MACOS 1
-#define PLATFORM_IOS 2
-#define PLATFORM_TVOS 3
-#define PLATFORM_WATCHOS 4
-#define PLATFORM_BRIDGEOS 5
-#define PLATFORM_MACCATALYST 6
-#if (!defined(PLATFORM_MACCATALYST))
-#define PLATFORM_MACCATALYST 6
-#endif
-#define PLATFORM_IOSSIMULATOR 7
-#define PLATFORM_TVOSSIMULATOR 8
-#define PLATFORM_WATCHOSSIMULATOR 9
-#define PLATFORM_DRIVERKIT 10
-
-/* Known values for the tool field above. */
-#define TOOL_CLANG 1
-#define TOOL_SWIFT 2
-#define TOOL_LD 3
-
-/*
- * The dyld_info_command contains the file offsets and sizes of
- * the new compressed form of the information dyld needs to
- * load the image. This information is used by dyld on Mac OS X
- * 10.6 and later. All information pointed to by this command
- * is encoded using byte streams, so no endian swapping is needed
- * to interpret it.
- */
-struct dyld_info_command {
- uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */
- uint32_t cmdsize; /* sizeof(struct dyld_info_command) */
-
- /*
- * Dyld rebases an image whenever dyld loads it at an address different
- * from its preferred address. The rebase information is a stream
- * of byte sized opcodes whose symbolic names start with REBASE_OPCODE_.
- * Conceptually the rebase information is a table of tuples:
- *
- * The opcodes are a compressed way to encode the table by only
- * encoding when a column changes. In addition simple patterns
- * like "every n'th offset for m times" can be encoded in a few
- * bytes.
- */
- uint32_t rebase_off; /* file offset to rebase info */
- uint32_t rebase_size; /* size of rebase info */
-
- /*
- * Dyld binds an image during the loading process, if the image
- * requires any pointers to be initialized to symbols in other images.
- * The bind information is a stream of byte sized
- * opcodes whose symbolic names start with BIND_OPCODE_.
- * Conceptually the bind information is a table of tuples:
- *
- * The opcodes are a compressed way to encode the table by only
- * encoding when a column changes. In addition simple patterns
- * like for runs of pointers initialzed to the same value can be
- * encoded in a few bytes.
- */
- uint32_t bind_off; /* file offset to binding info */
- uint32_t bind_size; /* size of binding info */
-
- /*
- * Some C++ programs require dyld to unique symbols so that all
- * images in the process use the same copy of some code/data.
- * This step is done after binding. The content of the weak_bind
- * info is an opcode stream like the bind_info. But it is sorted
- * alphabetically by symbol name. This enable dyld to walk
- * all images with weak binding information in order and look
- * for collisions. If there are no collisions, dyld does
- * no updating. That means that some fixups are also encoded
- * in the bind_info. For instance, all calls to "operator new"
- * are first bound to libstdc++.dylib using the information
- * in bind_info. Then if some image overrides operator new
- * that is detected when the weak_bind information is processed
- * and the call to operator new is then rebound.
- */
- uint32_t weak_bind_off; /* file offset to weak binding info */
- uint32_t weak_bind_size; /* size of weak binding info */
-
- /*
- * Some uses of external symbols do not need to be bound immediately.
- * Instead they can be lazily bound on first use. The lazy_bind
- * are contains a stream of BIND opcodes to bind all lazy symbols.
- * Normal use is that dyld ignores the lazy_bind section when
- * loading an image. Instead the static linker arranged for the
- * lazy pointer to initially point to a helper function which
- * pushes the offset into the lazy_bind area for the symbol
- * needing to be bound, then jumps to dyld which simply adds
- * the offset to lazy_bind_off to get the information on what
- * to bind.
- */
- uint32_t lazy_bind_off; /* file offset to lazy binding info */
- uint32_t lazy_bind_size; /* size of lazy binding infs */
-
- /*
- * The symbols exported by a dylib are encoded in a trie. This
- * is a compact representation that factors out common prefixes.
- * It also reduces LINKEDIT pages in RAM because it encodes all
- * information (name, address, flags) in one small, contiguous range.
- * The export area is a stream of nodes. The first node sequentially
- * is the start node for the trie.
- *
- * Nodes for a symbol start with a uleb128 that is the length of
- * the exported symbol information for the string so far.
- * If there is no exported symbol, the node starts with a zero byte.
- * If there is exported info, it follows the length.
- *
- * First is a uleb128 containing flags. Normally, it is followed by
- * a uleb128 encoded offset which is location of the content named
- * by the symbol from the mach_header for the image. If the flags
- * is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is
- * a uleb128 encoded library ordinal, then a zero terminated
- * UTF8 string. If the string is zero length, then the symbol
- * is re-export from the specified dylib with the same name.
- * If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following
- * the flags is two uleb128s: the stub offset and the resolver offset.
- * The stub is used by non-lazy pointers. The resolver is used
- * by lazy pointers and must be called to get the actual address to use.
- *
- * After the optional exported symbol information is a byte of
- * how many edges (0-255) that this node has leaving it,
- * followed by each edge.
- * Each edge is a zero terminated UTF8 of the addition chars
- * in the symbol, followed by a uleb128 offset for the node that
- * edge points to.
- *
- */
- uint32_t export_off; /* file offset to lazy binding info */
- uint32_t export_size; /* size of lazy binding infs */
-};
-
-/*
- * The following are used to encode rebasing information
- */
-#define REBASE_TYPE_POINTER 1
-#define REBASE_TYPE_TEXT_ABSOLUTE32 2
-#define REBASE_TYPE_TEXT_PCREL32 3
-
-#define REBASE_OPCODE_MASK 0xF0
-#define REBASE_IMMEDIATE_MASK 0x0F
-#define REBASE_OPCODE_DONE 0x00
-#define REBASE_OPCODE_SET_TYPE_IMM 0x10
-#define REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x20
-#define REBASE_OPCODE_ADD_ADDR_ULEB 0x30
-#define REBASE_OPCODE_ADD_ADDR_IMM_SCALED 0x40
-#define REBASE_OPCODE_DO_REBASE_IMM_TIMES 0x50
-#define REBASE_OPCODE_DO_REBASE_ULEB_TIMES 0x60
-#define REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB 0x70
-#define REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB 0x80
-
-
-/*
- * The following are used to encode binding information
- */
-#define BIND_TYPE_POINTER 1
-#define BIND_TYPE_TEXT_ABSOLUTE32 2
-#define BIND_TYPE_TEXT_PCREL32 3
-
-#define BIND_SPECIAL_DYLIB_SELF 0
-#define BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE -1
-#define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2
-#define BIND_SPECIAL_DYLIB_WEAK_LOOKUP -3
-
-#define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1
-#define BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION 0x8
-
-#define BIND_OPCODE_MASK 0xF0
-#define BIND_IMMEDIATE_MASK 0x0F
-#define BIND_OPCODE_DONE 0x00
-#define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10
-#define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20
-#define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30
-#define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40
-#define BIND_OPCODE_SET_TYPE_IMM 0x50
-#define BIND_OPCODE_SET_ADDEND_SLEB 0x60
-#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70
-#define BIND_OPCODE_ADD_ADDR_ULEB 0x80
-#define BIND_OPCODE_DO_BIND 0x90
-#define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xA0
-#define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xB0
-#define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xC0
-#define BIND_OPCODE_THREADED 0xD0
-#define BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB 0x00
-#define BIND_SUBOPCODE_THREADED_APPLY 0x01
-
-
-/*
- * The following are used on the flags byte of a terminal node
- * in the export information.
- */
-#define EXPORT_SYMBOL_FLAGS_KIND_MASK 0x03
-#define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00
-#define EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL 0x01
-#define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 0x02
-#define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04
-#define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
-#define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10
-
-/*
- * The linker_option_command contains linker options embedded in object files.
- */
-struct linker_option_command {
- uint32_t cmd; /* LC_LINKER_OPTION only used in MH_OBJECT filetypes */
- uint32_t cmdsize;
- uint32_t count; /* number of strings */
- /* concatenation of zero terminated UTF8 strings.
- Zero filled at end to align */
-};
-
-/*
- * The symseg_command contains the offset and size of the GNU style
- * symbol table information as described in the header file .
- * The symbol roots of the symbol segments must also be aligned properly
- * in the file. So the requirement of keeping the offsets aligned to a
- * multiple of a 4 bytes translates to the length field of the symbol
- * roots also being a multiple of a long. Also the padding must again be
- * zeroed. (THIS IS OBSOLETE and no longer supported).
- */
-struct symseg_command {
- uint32_t cmd; /* LC_SYMSEG */
- uint32_t cmdsize; /* sizeof(struct symseg_command) */
- uint32_t offset; /* symbol segment offset */
- uint32_t size; /* symbol segment size in bytes */
-};
-
-/*
- * The ident_command contains a free format string table following the
- * ident_command structure. The strings are null terminated and the size of
- * the command is padded out with zero bytes to a multiple of 4 bytes/
- * (THIS IS OBSOLETE and no longer supported).
- */
-struct ident_command {
- uint32_t cmd; /* LC_IDENT */
- uint32_t cmdsize; /* strings that follow this command */
-};
-
-/*
- * The fvmfile_command contains a reference to a file to be loaded at the
- * specified virtual address. (Presently, this command is reserved for
- * internal use. The kernel ignores this command when loading a program into
- * memory).
- */
-struct fvmfile_command {
- uint32_t cmd; /* LC_FVMFILE */
- uint32_t cmdsize; /* includes pathname string */
- union lc_str name; /* files pathname */
- uint32_t header_addr; /* files virtual address */
-};
-
-
-/*
- * The entry_point_command is a replacement for thread_command.
- * It is used for main executables to specify the location (file offset)
- * of main(). If -stack_size was used at link time, the stacksize
- * field will contain the stack size need for the main thread.
- */
-struct entry_point_command {
- uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */
- uint32_t cmdsize; /* 24 */
- uint64_t entryoff; /* file (__TEXT) offset of main() */
- uint64_t stacksize;/* if not zero, initial stack size */
-};
-
-
-/*
- * The source_version_command is an optional load command containing
- * the version of the sources used to build the binary.
- */
-struct source_version_command {
- uint32_t cmd; /* LC_SOURCE_VERSION */
- uint32_t cmdsize; /* 16 */
- uint64_t version; /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */
-};
-
-
-/*
- * The LC_DATA_IN_CODE load commands uses a linkedit_data_command
- * to point to an array of data_in_code_entry entries. Each entry
- * describes a range of data in a code section.
- */
-struct data_in_code_entry {
- uint32_t offset; /* from mach_header to start of data range*/
- uint16_t length; /* number of bytes in data range */
- uint16_t kind; /* a DICE_KIND_* value */
-};
-#define DICE_KIND_DATA 0x0001
-#define DICE_KIND_JUMP_TABLE8 0x0002
-#define DICE_KIND_JUMP_TABLE16 0x0003
-#define DICE_KIND_JUMP_TABLE32 0x0004
-#define DICE_KIND_ABS_JUMP_TABLE32 0x0005
-
-
-
-/*
- * Sections of type S_THREAD_LOCAL_VARIABLES contain an array
- * of tlv_descriptor structures.
- */
-struct tlv_descriptor
-{
- void* (*thunk)(struct tlv_descriptor*);
- unsigned long key;
- unsigned long offset;
-};
-
-/*
- * LC_NOTE commands describe a region of arbitrary data included in a Mach-O
- * file. Its initial use is to record extra data in MH_CORE files.
- */
-struct note_command {
- uint32_t cmd; /* LC_NOTE */
- uint32_t cmdsize; /* sizeof(struct note_command) */
- char data_owner[16]; /* owner name for this LC_NOTE */
- uint64_t offset; /* file offset of this data */
- uint64_t size; /* length of data region */
-};
-
-#endif /* _MACHO_LOADER_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/exception_types.h b/lib/libc/include/x86_64-macos-gnu/mach/exception_types.h
deleted file mode 100644
index a0026b9ce2..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/exception_types.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- */
-
-#ifndef _MACH_EXCEPTION_TYPES_H_
-#define _MACH_EXCEPTION_TYPES_H_
-
-#include
-
-/*
- * Machine-independent exception definitions.
- */
-
-#define EXC_BAD_ACCESS 1 /* Could not access memory */
-/* Code contains kern_return_t describing error. */
-/* Subcode contains bad memory address. */
-
-#define EXC_BAD_INSTRUCTION 2 /* Instruction failed */
-/* Illegal or undefined instruction or operand */
-
-#define EXC_ARITHMETIC 3 /* Arithmetic exception */
-/* Exact nature of exception is in code field */
-
-#define EXC_EMULATION 4 /* Emulation instruction */
-/* Emulation support instruction encountered */
-/* Details in code and subcode fields */
-
-#define EXC_SOFTWARE 5 /* Software generated exception */
-/* Exact exception is in code field. */
-/* Codes 0 - 0xFFFF reserved to hardware */
-/* Codes 0x10000 - 0x1FFFF reserved for OS emulation (Unix) */
-
-#define EXC_BREAKPOINT 6 /* Trace, breakpoint, etc. */
-/* Details in code field. */
-
-#define EXC_SYSCALL 7 /* System calls. */
-
-#define EXC_MACH_SYSCALL 8 /* Mach system calls. */
-
-#define EXC_RPC_ALERT 9 /* RPC alert */
-
-#define EXC_CRASH 10 /* Abnormal process exit */
-
-#define EXC_RESOURCE 11 /* Hit resource consumption limit */
-/* Exact resource is in code field. */
-
-#define EXC_GUARD 12 /* Violated guarded resource protections */
-
-#define EXC_CORPSE_NOTIFY 13 /* Abnormal process exited to corpse state */
-
-#define EXC_CORPSE_VARIANT_BIT 0x100 /* bit set for EXC_*_CORPSE variants of EXC_* */
-
-
-/*
- * Machine-independent exception behaviors
- */
-
-# define EXCEPTION_DEFAULT 1
-/* Send a catch_exception_raise message including the identity.
- */
-
-# define EXCEPTION_STATE 2
-/* Send a catch_exception_raise_state message including the
- * thread state.
- */
-
-# define EXCEPTION_STATE_IDENTITY 3
-/* Send a catch_exception_raise_state_identity message including
- * the thread identity and state.
- */
-
-#define MACH_EXCEPTION_ERRORS 0x40000000
-/* include additional exception specific errors, not used yet. */
-
-#define MACH_EXCEPTION_CODES 0x80000000
-/* Send 64-bit code and subcode in the exception header */
-
-#define MACH_EXCEPTION_MASK (MACH_EXCEPTION_CODES | MACH_EXCEPTION_ERRORS)
-/*
- * Masks for exception definitions, above
- * bit zero is unused, therefore 1 word = 31 exception types
- */
-
-#define EXC_MASK_BAD_ACCESS (1 << EXC_BAD_ACCESS)
-#define EXC_MASK_BAD_INSTRUCTION (1 << EXC_BAD_INSTRUCTION)
-#define EXC_MASK_ARITHMETIC (1 << EXC_ARITHMETIC)
-#define EXC_MASK_EMULATION (1 << EXC_EMULATION)
-#define EXC_MASK_SOFTWARE (1 << EXC_SOFTWARE)
-#define EXC_MASK_BREAKPOINT (1 << EXC_BREAKPOINT)
-#define EXC_MASK_SYSCALL (1 << EXC_SYSCALL)
-#define EXC_MASK_MACH_SYSCALL (1 << EXC_MACH_SYSCALL)
-#define EXC_MASK_RPC_ALERT (1 << EXC_RPC_ALERT)
-#define EXC_MASK_CRASH (1 << EXC_CRASH)
-#define EXC_MASK_RESOURCE (1 << EXC_RESOURCE)
-#define EXC_MASK_GUARD (1 << EXC_GUARD)
-#define EXC_MASK_CORPSE_NOTIFY (1 << EXC_CORPSE_NOTIFY)
-
-#define EXC_MASK_ALL (EXC_MASK_BAD_ACCESS | \
- EXC_MASK_BAD_INSTRUCTION | \
- EXC_MASK_ARITHMETIC | \
- EXC_MASK_EMULATION | \
- EXC_MASK_SOFTWARE | \
- EXC_MASK_BREAKPOINT | \
- EXC_MASK_SYSCALL | \
- EXC_MASK_MACH_SYSCALL | \
- EXC_MASK_RPC_ALERT | \
- EXC_MASK_RESOURCE | \
- EXC_MASK_GUARD | \
- EXC_MASK_MACHINE)
-
-
-#define FIRST_EXCEPTION 1 /* ZERO is illegal */
-
-/*
- * Machine independent codes for EXC_SOFTWARE
- * Codes 0x10000 - 0x1FFFF reserved for OS emulation (Unix)
- * 0x10000 - 0x10002 in use for unix signals
- * 0x20000 - 0x2FFFF reserved for MACF
- */
-#define EXC_SOFT_SIGNAL 0x10003 /* Unix signal exceptions */
-
-#define EXC_MACF_MIN 0x20000 /* MACF exceptions */
-#define EXC_MACF_MAX 0x2FFFF
-
-#ifndef ASSEMBLER
-
-#include
-#include
-#include
-/*
- * Exported types
- */
-
-typedef int exception_type_t;
-typedef integer_t exception_data_type_t;
-typedef int64_t mach_exception_data_type_t;
-typedef int exception_behavior_t;
-typedef exception_data_type_t *exception_data_t;
-typedef mach_exception_data_type_t *mach_exception_data_t;
-typedef unsigned int exception_mask_t;
-typedef exception_mask_t *exception_mask_array_t;
-typedef exception_behavior_t *exception_behavior_array_t;
-typedef thread_state_flavor_t *exception_flavor_array_t;
-typedef mach_port_t *exception_port_array_t;
-typedef mach_exception_data_type_t mach_exception_code_t;
-typedef mach_exception_data_type_t mach_exception_subcode_t;
-
-#endif /* ASSEMBLER */
-
-#endif /* _MACH_EXCEPTION_TYPES_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/host_special_ports.h b/lib/libc/include/x86_64-macos-gnu/mach/host_special_ports.h
deleted file mode 100644
index 8d4cdbefce..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/host_special_ports.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- */
-/*
- * File: mach/host_special_ports.h
- *
- * Defines codes for access to host-wide special ports.
- */
-
-#ifndef _MACH_HOST_SPECIAL_PORTS_H_
-#define _MACH_HOST_SPECIAL_PORTS_H_
-
-/*
- * Cannot be set or gotten from user space
- */
-#define HOST_SECURITY_PORT 0
-
-#define HOST_MIN_SPECIAL_PORT HOST_SECURITY_PORT
-
-/*
- * Always provided by kernel (cannot be set from user-space).
- */
-#define HOST_PORT 1
-#define HOST_PRIV_PORT 2
-#define HOST_IO_MASTER_PORT 3
-#define HOST_MAX_SPECIAL_KERNEL_PORT 7 /* room to grow */
-
-#define HOST_LAST_SPECIAL_KERNEL_PORT HOST_IO_MASTER_PORT
-
-/*
- * Not provided by kernel
- */
-#define HOST_DYNAMIC_PAGER_PORT (1 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_AUDIT_CONTROL_PORT (2 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_USER_NOTIFICATION_PORT (3 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_AUTOMOUNTD_PORT (4 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_LOCKD_PORT (5 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_KTRACE_BACKGROUND_PORT (6 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_SEATBELT_PORT (7 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_KEXTD_PORT (8 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_LAUNCHCTL_PORT (9 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_UNFREED_PORT (10 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_AMFID_PORT (11 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_GSSD_PORT (12 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_TELEMETRY_PORT (13 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_ATM_NOTIFICATION_PORT (14 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_COALITION_PORT (15 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_SYSDIAGNOSE_PORT (16 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_XPC_EXCEPTION_PORT (17 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_CONTAINERD_PORT (18 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_NODE_PORT (19 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_RESOURCE_NOTIFY_PORT (20 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_CLOSURED_PORT (21 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_SYSPOLICYD_PORT (22 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_FILECOORDINATIOND_PORT (23 + HOST_MAX_SPECIAL_KERNEL_PORT)
-#define HOST_FAIRPLAYD_PORT (24 + HOST_MAX_SPECIAL_KERNEL_PORT)
-
-#define HOST_MAX_SPECIAL_PORT HOST_FAIRPLAYD_PORT
-/* MAX = last since rdar://35861175 */
-
-/* obsolete name */
-#define HOST_CHUD_PORT HOST_LAUNCHCTL_PORT
-
-/*
- * Special node identifier to always represent the local node.
- */
-#define HOST_LOCAL_NODE -1
-
-/*
- * Definitions for ease of use.
- *
- * In the get call, the host parameter can be any host, but will generally
- * be the local node host port. In the set call, the host must the per-node
- * host port for the node being affected.
- */
-#define host_get_host_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_PORT, (port)))
-#define host_set_host_port(host, port) (KERN_INVALID_ARGUMENT)
-
-#define host_get_host_priv_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_PRIV_PORT, (port)))
-#define host_set_host_priv_port(host, port) (KERN_INVALID_ARGUMENT)
-
-#define host_get_io_master_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_IO_MASTER_PORT, (port)))
-#define host_set_io_master_port(host, port) (KERN_INVALID_ARGUMENT)
-
-/*
- * User-settable special ports.
- */
-#define host_get_dynamic_pager_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_DYNAMIC_PAGER_PORT, (port)))
-#define host_set_dynamic_pager_port(host, port) \
- (host_set_special_port((host), HOST_DYNAMIC_PAGER_PORT, (port)))
-
-#define host_get_audit_control_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_AUDIT_CONTROL_PORT, (port)))
-#define host_set_audit_control_port(host, port) \
- (host_set_special_port((host), HOST_AUDIT_CONTROL_PORT, (port)))
-
-#define host_get_user_notification_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_USER_NOTIFICATION_PORT, (port)))
-#define host_set_user_notification_port(host, port) \
- (host_set_special_port((host), HOST_USER_NOTIFICATION_PORT, (port)))
-
-#define host_get_automountd_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_AUTOMOUNTD_PORT, (port)))
-#define host_set_automountd_port(host, port) \
- (host_set_special_port((host), HOST_AUTOMOUNTD_PORT, (port)))
-
-#define host_get_lockd_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_LOCKD_PORT, (port)))
-#define host_set_lockd_port(host, port) \
- (host_set_special_port((host), HOST_LOCKD_PORT, (port)))
-
-#define host_get_ktrace_background_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_KTRACE_BACKGROUND_PORT, (port)))
-#define host_set_ktrace_background_port(host, port) \
- (host_set_special_port((host), HOST_KTRACE_BACKGROUND_PORT, (port)))
-
-#define host_get_kextd_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_KEXTD_PORT, (port)))
-#define host_set_kextd_port(host, port) \
- (host_set_special_port((host), HOST_KEXTD_PORT, (port)))
-
-#define host_get_launchctl_port(host, port) \
- (host_get_special_port((host), HOST_LOCAL_NODE, HOST_LAUNCHCTL_PORT, \
- (port)))
-#define host_set_launchctl_port(host, port) \
- (host_set_special_port((host), HOST_LAUNCHCTL_PORT, (port)))
-
-#define host_get_chud_port(host, port) host_get_launchctl_port(host, port)
-#define host_set_chud_port(host, port) host_set_launchctl_port(host, port)
-
-#define host_get_unfreed_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_UNFREED_PORT, (port)))
-#define host_set_unfreed_port(host, port) \
- (host_set_special_port((host), HOST_UNFREED_PORT, (port)))
-
-#define host_get_amfid_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_AMFID_PORT, (port)))
-#define host_set_amfid_port(host, port) \
- (host_set_special_port((host), HOST_AMFID_PORT, (port)))
-
-#define host_get_gssd_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_GSSD_PORT, (port)))
-#define host_set_gssd_port(host, port) \
- (host_set_special_port((host), HOST_GSSD_PORT, (port)))
-
-#define host_get_telemetry_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_TELEMETRY_PORT, (port)))
-#define host_set_telemetry_port(host, port) \
- (host_set_special_port((host), HOST_TELEMETRY_PORT, (port)))
-
-#define host_get_atm_notification_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_ATM_NOTIFICATION_PORT, (port)))
-#define host_set_atm_notification_port(host, port) \
- (host_set_special_port((host), HOST_ATM_NOTIFICATION_PORT, (port)))
-
-#define host_get_coalition_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_COALITION_PORT, (port)))
-#define host_set_coalition_port(host, port) \
- (host_set_special_port((host), HOST_COALITION_PORT, (port)))
-
-#define host_get_sysdiagnose_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_SYSDIAGNOSE_PORT, (port)))
-#define host_set_sysdiagnose_port(host, port) \
- (host_set_special_port((host), HOST_SYSDIAGNOSE_PORT, (port)))
-
-#define host_get_container_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_CONTAINERD_PORT, (port)))
-#define host_set_container_port(host, port) \
- (host_set_special_port((host), HOST_CONTAINERD_PORT, (port)))
-
-#define host_get_node_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_NODE_PORT, (port)))
-#define host_set_node_port(host, port) \
- (host_set_special_port((host), HOST_NODE_PORT, (port)))
-
-#define host_get_closured_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_CLOSURED_PORT, (port)))
-#define host_set_closured_port(host, port) \
- (host_set_special_port((host), HOST_CLOSURED_PORT, (port)))
-
-#define host_get_syspolicyd_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_SYSPOLICYD_PORT, (port)))
-#define host_set_syspolicyd_port(host, port) \
- (host_set_special_port((host), HOST_SYSPOLICYD_PORT, (port)))
-
-#define host_get_filecoordinationd_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_FILECOORDINATIOND_PORT, (port)))
-#define host_set_filecoordinationd_port(host, port) \
- (host_set_special_port((host), HOST_FILECOORDINATIOND_PORT, (port)))
-
-#define host_get_fairplayd_port(host, port) \
- (host_get_special_port((host), \
- HOST_LOCAL_NODE, HOST_FAIRPLAYD_PORT, (port)))
-#define host_set_fairplayd_port(host, port) \
- (host_set_special_port((host), HOST_FAIRPLAYD_PORT, (port)))
-
-/* HOST_RESOURCE_NOTIFY_PORT doesn't #defines these conveniences.
- * All lookups go through send_resource_violation()
- */
-
-#endif /* _MACH_HOST_SPECIAL_PORTS_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/i386/_structs.h b/lib/libc/include/x86_64-macos-gnu/mach/i386/_structs.h
index f041af9f3f..248653b4f8 100644
--- a/lib/libc/include/x86_64-macos-gnu/mach/i386/_structs.h
+++ b/lib/libc/include/x86_64-macos-gnu/mach/i386/_structs.h
@@ -603,7 +603,48 @@ _STRUCT_X86_DEBUG_STATE32
unsigned int __dr6;
unsigned int __dr7;
};
+
+#define _STRUCT_X86_INSTRUCTION_STATE struct __x86_instruction_state
+_STRUCT_X86_INSTRUCTION_STATE
+{
+ int __insn_stream_valid_bytes;
+ int __insn_offset;
+ int __out_of_synch; /*
+ * non-zero when the cacheline that includes the insn_offset
+ * is replaced in the insn_bytes array due to a mismatch
+ * detected when comparing it with the same cacheline in memory
+ */
+#define _X86_INSTRUCTION_STATE_MAX_INSN_BYTES (2448 - 64 - 4)
+ __uint8_t __insn_bytes[_X86_INSTRUCTION_STATE_MAX_INSN_BYTES];
+#define _X86_INSTRUCTION_STATE_CACHELINE_SIZE 64
+ __uint8_t __insn_cacheline[_X86_INSTRUCTION_STATE_CACHELINE_SIZE];
+};
+
+#define _STRUCT_LAST_BRANCH_RECORD struct __last_branch_record
+_STRUCT_LAST_BRANCH_RECORD
+{
+ __uint64_t __from_ip;
+ __uint64_t __to_ip;
+ __uint32_t __mispredict : 1,
+ __tsx_abort : 1,
+ __in_tsx : 1,
+ __cycle_count: 16,
+ __reserved : 13;
+};
+
+#define _STRUCT_LAST_BRANCH_STATE struct __last_branch_state
+_STRUCT_LAST_BRANCH_STATE
+{
+ int __lbr_count;
+ __uint32_t __lbr_supported_tsx : 1,
+ __lbr_supported_cycle_count : 1,
+ __reserved : 30;
+#define __LASTBRANCH_MAX 32
+ _STRUCT_LAST_BRANCH_RECORD __lbrs[__LASTBRANCH_MAX];
+};
+
#else /* !__DARWIN_UNIX03 */
+
#define _STRUCT_X86_DEBUG_STATE32 struct x86_debug_state32
_STRUCT_X86_DEBUG_STATE32
{
@@ -616,6 +657,45 @@ _STRUCT_X86_DEBUG_STATE32
unsigned int dr6;
unsigned int dr7;
};
+
+#define _STRUCT_X86_INSTRUCTION_STATE struct __x86_instruction_state
+_STRUCT_X86_INSTRUCTION_STATE
+{
+ int insn_stream_valid_bytes;
+ int insn_offset;
+ int out_of_synch; /*
+ * non-zero when the cacheline that includes the insn_offset
+ * is replaced in the insn_bytes array due to a mismatch
+ * detected when comparing it with the same cacheline in memory
+ */
+#define x86_INSTRUCTION_STATE_MAX_INSN_BYTES (2448 - 64 - 4)
+ __uint8_t insn_bytes[x86_INSTRUCTION_STATE_MAX_INSN_BYTES];
+#define x86_INSTRUCTION_STATE_CACHELINE_SIZE 64
+ __uint8_t insn_cacheline[x86_INSTRUCTION_STATE_CACHELINE_SIZE];
+};
+
+#define _STRUCT_LAST_BRANCH_RECORD struct __last_branch_record
+_STRUCT_LAST_BRANCH_RECORD
+{
+ __uint64_t from_ip;
+ __uint64_t to_ip;
+ __uint32_t mispredict : 1,
+ tsx_abort : 1,
+ in_tsx : 1,
+ cycle_count: 16,
+ reserved : 13;
+};
+
+#define _STRUCT_LAST_BRANCH_STATE struct __last_branch_state
+_STRUCT_LAST_BRANCH_STATE
+{
+ int lbr_count;
+ __uint32_t lbr_supported_tsx : 1,
+ lbr_supported_cycle_count : 1,
+ reserved : 30;
+#define __LASTBRANCH_MAX 32
+ _STRUCT_LAST_BRANCH_RECORD lbrs[__LASTBRANCH_MAX];
+};
#endif /* !__DARWIN_UNIX03 */
#define _STRUCT_X86_PAGEIN_STATE struct __x86_pagein_state
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/i386/thread_state.h b/lib/libc/include/x86_64-macos-gnu/mach/i386/thread_state.h
index 78595255a3..4d9825be70 100644
--- a/lib/libc/include/x86_64-macos-gnu/mach/i386/thread_state.h
+++ b/lib/libc/include/x86_64-macos-gnu/mach/i386/thread_state.h
@@ -32,7 +32,7 @@
#ifndef _MACH_I386_THREAD_STATE_H_
#define _MACH_I386_THREAD_STATE_H_
-/* Size of maximum exported thread state in words */
+/* Size of maximum exported thread state in 32-bit words */
#define I386_THREAD_STATE_MAX (614) /* Size of biggest state possible */
#if defined (__i386__) || defined(__x86_64__)
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/i386/thread_status.h b/lib/libc/include/x86_64-macos-gnu/mach/i386/thread_status.h
index 233e0f22a6..24de7ae76c 100644
--- a/lib/libc/include/x86_64-macos-gnu/mach/i386/thread_status.h
+++ b/lib/libc/include/x86_64-macos-gnu/mach/i386/thread_status.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -121,6 +121,8 @@
#define x86_AVX512_STATE (x86_AVX512_STATE32 + 2)
#define x86_PAGEIN_STATE 22
#define x86_THREAD_FULL_STATE64 23
+#define x86_INSTRUCTION_STATE 24
+#define x86_LAST_BRANCH_STATE 25
/*
* Largest state on this machine:
@@ -155,6 +157,8 @@
(x == x86_AVX512_STATE64) || \
(x == x86_AVX512_STATE) || \
(x == x86_PAGEIN_STATE) || \
+ (x == x86_INSTRUCTION_STATE) || \
+ (x == x86_LAST_BRANCH_STATE) || \
(x == THREAD_STATE_NONE))
struct x86_state_hdr {
@@ -259,6 +263,19 @@ typedef _STRUCT_X86_PAGEIN_STATE x86_pagein_state_t;
#define X86_PAGEIN_STATE_COUNT x86_PAGEIN_STATE_COUNT
+typedef _STRUCT_X86_INSTRUCTION_STATE x86_instruction_state_t;
+#define x86_INSTRUCTION_STATE_COUNT \
+ ((mach_msg_type_number_t)(sizeof(x86_instruction_state_t) / sizeof(int)))
+
+#define X86_INSTRUCTION_STATE_COUNT x86_INSTRUCTION_STATE_COUNT
+
+typedef _STRUCT_LAST_BRANCH_STATE last_branch_state_t;
+#define x86_LAST_BRANCH_STATE_COUNT \
+ ((mach_msg_type_number_t)(sizeof(last_branch_state_t) / sizeof(int)))
+
+#define X86_LAST_BRANCH_STATE_COUNT x86_LAST_BRANCH_STATE_COUNT
+
+
/*
* Combined thread, float and exception states
*/
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/i386/vm_param.h b/lib/libc/include/x86_64-macos-gnu/mach/i386/vm_param.h
index a85ee924b7..fa27fffa2f 100644
--- a/lib/libc/include/x86_64-macos-gnu/mach/i386/vm_param.h
+++ b/lib/libc/include/x86_64-macos-gnu/mach/i386/vm_param.h
@@ -90,47 +90,34 @@
#ifndef _MACH_I386_VM_PARAM_H_
#define _MACH_I386_VM_PARAM_H_
+#if !defined(KERNEL) && !defined(__ASSEMBLER__)
+
+#include
+#endif
+
#define BYTE_SIZE 8 /* byte size in bits */
#define I386_PGBYTES 4096 /* bytes per 80386 page */
#define I386_PGSHIFT 12 /* bitshift for pages */
-#define PAGE_SIZE I386_PGBYTES
+
+#if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || (__MAC_OS_X_VERSION_MIN_REQUIRED < 101600)
#define PAGE_SHIFT I386_PGSHIFT
-#define PAGE_MASK (PAGE_SIZE - 1)
+#define PAGE_SIZE I386_PGBYTES
+#define PAGE_MASK (PAGE_SIZE-1)
+#else /* !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || (__MAC_OS_X_VERSION_MIN_REQUIRED < 101600) */
+#define PAGE_SHIFT vm_page_shift
+#define PAGE_SIZE vm_page_size
+#define PAGE_MASK vm_page_mask
+#endif /* !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || (__MAC_OS_X_VERSION_MIN_REQUIRED < 101600) */
-#define PAGE_MAX_SHIFT PAGE_SHIFT
-#define PAGE_MAX_SIZE PAGE_SIZE
-#define PAGE_MAX_MASK PAGE_MASK
-
-#define PAGE_MIN_SHIFT PAGE_SHIFT
-#define PAGE_MIN_SIZE PAGE_SIZE
-#define PAGE_MIN_MASK PAGE_MASK
-
-#define I386_LPGBYTES 2*1024*1024 /* bytes per large page */
-#define I386_LPGSHIFT 21 /* bitshift for large pages */
-#define I386_LPGMASK (I386_LPGBYTES-1)
-
-/*
- * Convert bytes to pages and convert pages to bytes.
- * No rounding is used.
- */
-
-#define i386_btop(x) ((ppnum_t)((x) >> I386_PGSHIFT))
-#define machine_btop(x) i386_btop(x)
-#define i386_ptob(x) (((pmap_paddr_t)(x)) << I386_PGSHIFT)
-#define machine_ptob(x) i386_ptob(x)
-
-/*
- * Round off or truncate to the nearest page. These will work
- * for either addresses or counts. (i.e. 1 byte rounds to 1 page
- * bytes.
- */
-
-#define i386_round_page(x) ((((pmap_paddr_t)(x)) + I386_PGBYTES - 1) & \
- ~(I386_PGBYTES-1))
-#define i386_trunc_page(x) (((pmap_paddr_t)(x)) & ~(I386_PGBYTES-1))
+#define PAGE_MAX_SHIFT 14
+#define PAGE_MAX_SIZE (1 << PAGE_MAX_SHIFT)
+#define PAGE_MAX_MASK (PAGE_MAX_SIZE-1)
+#define PAGE_MIN_SHIFT 12
+#define PAGE_MIN_SIZE (1 << PAGE_MIN_SHIFT)
+#define PAGE_MIN_MASK (PAGE_MIN_SIZE-1)
#define VM_MIN_ADDRESS64 ((user_addr_t) 0x0000000000000000ULL)
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/i386/vm_types.h b/lib/libc/include/x86_64-macos-gnu/mach/i386/vm_types.h
index 8a95db53ee..57bc28af88 100644
--- a/lib/libc/include/x86_64-macos-gnu/mach/i386/vm_types.h
+++ b/lib/libc/include/x86_64-macos-gnu/mach/i386/vm_types.h
@@ -70,7 +70,6 @@
#ifndef ASSEMBLER
#include
-#include
#include
/*
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/kern_return.h b/lib/libc/include/x86_64-macos-gnu/mach/kern_return.h
deleted file mode 100644
index 62d6415f52..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/kern_return.h
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- */
-/*
- * File: h/kern_return.h
- * Author: Avadis Tevanian, Jr.
- * Date: 1985
- *
- * Kernel return codes.
- *
- */
-
-#ifndef _MACH_KERN_RETURN_H_
-#define _MACH_KERN_RETURN_H_
-
-#include
-
-#define KERN_SUCCESS 0
-
-#define KERN_INVALID_ADDRESS 1
-/* Specified address is not currently valid.
- */
-
-#define KERN_PROTECTION_FAILURE 2
-/* Specified memory is valid, but does not permit the
- * required forms of access.
- */
-
-#define KERN_NO_SPACE 3
-/* The address range specified is already in use, or
- * no address range of the size specified could be
- * found.
- */
-
-#define KERN_INVALID_ARGUMENT 4
-/* The function requested was not applicable to this
- * type of argument, or an argument is invalid
- */
-
-#define KERN_FAILURE 5
-/* The function could not be performed. A catch-all.
- */
-
-#define KERN_RESOURCE_SHORTAGE 6
-/* A system resource could not be allocated to fulfill
- * this request. This failure may not be permanent.
- */
-
-#define KERN_NOT_RECEIVER 7
-/* The task in question does not hold receive rights
- * for the port argument.
- */
-
-#define KERN_NO_ACCESS 8
-/* Bogus access restriction.
- */
-
-#define KERN_MEMORY_FAILURE 9
-/* During a page fault, the target address refers to a
- * memory object that has been destroyed. This
- * failure is permanent.
- */
-
-#define KERN_MEMORY_ERROR 10
-/* During a page fault, the memory object indicated
- * that the data could not be returned. This failure
- * may be temporary; future attempts to access this
- * same data may succeed, as defined by the memory
- * object.
- */
-
-#define KERN_ALREADY_IN_SET 11
-/* The receive right is already a member of the portset.
- */
-
-#define KERN_NOT_IN_SET 12
-/* The receive right is not a member of a port set.
- */
-
-#define KERN_NAME_EXISTS 13
-/* The name already denotes a right in the task.
- */
-
-#define KERN_ABORTED 14
-/* The operation was aborted. Ipc code will
- * catch this and reflect it as a message error.
- */
-
-#define KERN_INVALID_NAME 15
-/* The name doesn't denote a right in the task.
- */
-
-#define KERN_INVALID_TASK 16
-/* Target task isn't an active task.
- */
-
-#define KERN_INVALID_RIGHT 17
-/* The name denotes a right, but not an appropriate right.
- */
-
-#define KERN_INVALID_VALUE 18
-/* A blatant range error.
- */
-
-#define KERN_UREFS_OVERFLOW 19
-/* Operation would overflow limit on user-references.
- */
-
-#define KERN_INVALID_CAPABILITY 20
-/* The supplied (port) capability is improper.
- */
-
-#define KERN_RIGHT_EXISTS 21
-/* The task already has send or receive rights
- * for the port under another name.
- */
-
-#define KERN_INVALID_HOST 22
-/* Target host isn't actually a host.
- */
-
-#define KERN_MEMORY_PRESENT 23
-/* An attempt was made to supply "precious" data
- * for memory that is already present in a
- * memory object.
- */
-
-#define KERN_MEMORY_DATA_MOVED 24
-/* A page was requested of a memory manager via
- * memory_object_data_request for an object using
- * a MEMORY_OBJECT_COPY_CALL strategy, with the
- * VM_PROT_WANTS_COPY flag being used to specify
- * that the page desired is for a copy of the
- * object, and the memory manager has detected
- * the page was pushed into a copy of the object
- * while the kernel was walking the shadow chain
- * from the copy to the object. This error code
- * is delivered via memory_object_data_error
- * and is handled by the kernel (it forces the
- * kernel to restart the fault). It will not be
- * seen by users.
- */
-
-#define KERN_MEMORY_RESTART_COPY 25
-/* A strategic copy was attempted of an object
- * upon which a quicker copy is now possible.
- * The caller should retry the copy using
- * vm_object_copy_quickly. This error code
- * is seen only by the kernel.
- */
-
-#define KERN_INVALID_PROCESSOR_SET 26
-/* An argument applied to assert processor set privilege
- * was not a processor set control port.
- */
-
-#define KERN_POLICY_LIMIT 27
-/* The specified scheduling attributes exceed the thread's
- * limits.
- */
-
-#define KERN_INVALID_POLICY 28
-/* The specified scheduling policy is not currently
- * enabled for the processor set.
- */
-
-#define KERN_INVALID_OBJECT 29
-/* The external memory manager failed to initialize the
- * memory object.
- */
-
-#define KERN_ALREADY_WAITING 30
-/* A thread is attempting to wait for an event for which
- * there is already a waiting thread.
- */
-
-#define KERN_DEFAULT_SET 31
-/* An attempt was made to destroy the default processor
- * set.
- */
-
-#define KERN_EXCEPTION_PROTECTED 32
-/* An attempt was made to fetch an exception port that is
- * protected, or to abort a thread while processing a
- * protected exception.
- */
-
-#define KERN_INVALID_LEDGER 33
-/* A ledger was required but not supplied.
- */
-
-#define KERN_INVALID_MEMORY_CONTROL 34
-/* The port was not a memory cache control port.
- */
-
-#define KERN_INVALID_SECURITY 35
-/* An argument supplied to assert security privilege
- * was not a host security port.
- */
-
-#define KERN_NOT_DEPRESSED 36
-/* thread_depress_abort was called on a thread which
- * was not currently depressed.
- */
-
-#define KERN_TERMINATED 37
-/* Object has been terminated and is no longer available
- */
-
-#define KERN_LOCK_SET_DESTROYED 38
-/* Lock set has been destroyed and is no longer available.
- */
-
-#define KERN_LOCK_UNSTABLE 39
-/* The thread holding the lock terminated before releasing
- * the lock
- */
-
-#define KERN_LOCK_OWNED 40
-/* The lock is already owned by another thread
- */
-
-#define KERN_LOCK_OWNED_SELF 41
-/* The lock is already owned by the calling thread
- */
-
-#define KERN_SEMAPHORE_DESTROYED 42
-/* Semaphore has been destroyed and is no longer available.
- */
-
-#define KERN_RPC_SERVER_TERMINATED 43
-/* Return from RPC indicating the target server was
- * terminated before it successfully replied
- */
-
-#define KERN_RPC_TERMINATE_ORPHAN 44
-/* Terminate an orphaned activation.
- */
-
-#define KERN_RPC_CONTINUE_ORPHAN 45
-/* Allow an orphaned activation to continue executing.
- */
-
-#define KERN_NOT_SUPPORTED 46
-/* Empty thread activation (No thread linked to it)
- */
-
-#define KERN_NODE_DOWN 47
-/* Remote node down or inaccessible.
- */
-
-#define KERN_NOT_WAITING 48
-/* A signalled thread was not actually waiting. */
-
-#define KERN_OPERATION_TIMED_OUT 49
-/* Some thread-oriented operation (semaphore_wait) timed out
- */
-
-#define KERN_CODESIGN_ERROR 50
-/* During a page fault, indicates that the page was rejected
- * as a result of a signature check.
- */
-
-#define KERN_POLICY_STATIC 51
-/* The requested property cannot be changed at this time.
- */
-
-#define KERN_INSUFFICIENT_BUFFER_SIZE 52
-/* The provided buffer is of insufficient size for the requested data.
- */
-
-#define KERN_RETURN_MAX 0x100
-/* Maximum return value allowable
- */
-
-#endif /* _MACH_KERN_RETURN_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/mach_init.h b/lib/libc/include/x86_64-macos-gnu/mach/mach_init.h
deleted file mode 100644
index d61d6e90b5..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/mach_init.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987,1986 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/*
- * Items provided by the Mach environment initialization.
- */
-
-#ifndef _MACH_INIT_
-#define _MACH_INIT_ 1
-
-#include
-#include
-#include
-
-#include
-
-/*
- * Kernel-related ports; how a task/thread controls itself
- */
-
-__BEGIN_DECLS
-extern mach_port_t mach_host_self(void);
-extern mach_port_t mach_thread_self(void);
-extern kern_return_t host_page_size(host_t, vm_size_t *);
-
-extern mach_port_t mach_task_self_;
-#define mach_task_self() mach_task_self_
-#define current_task() mach_task_self()
-
-__END_DECLS
-#include
-__BEGIN_DECLS
-
-/*
- * Other important ports in the Mach user environment
- */
-
-extern mach_port_t bootstrap_port;
-
-/*
- * Where these ports occur in the "mach_ports_register"
- * collection... only servers or the runtime library need know.
- */
-
-#define NAME_SERVER_SLOT 0
-#define ENVIRONMENT_SLOT 1
-#define SERVICE_SLOT 2
-
-#define MACH_PORTS_SLOTS_USED 3
-
-/*
- * fprintf_stderr uses vprintf_stderr_func to produce
- * error messages, this can be overridden by a user
- * application to point to a user-specified output function
- */
-extern int (*vprintf_stderr_func)(const char *format, va_list ap);
-
-__END_DECLS
-
-#endif /* _MACH_INIT_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/mach_port.h b/lib/libc/include/x86_64-macos-gnu/mach/mach_port.h
deleted file mode 100644
index fcec114ccf..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/mach_port.h
+++ /dev/null
@@ -1,1808 +0,0 @@
-#ifndef _mach_port_user_
-#define _mach_port_user_
-
-/* Module mach_port */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* BEGIN MIG_STRNCPY_ZEROFILL CODE */
-
-#if defined(__has_include)
-#if __has_include()
-#ifndef USING_MIG_STRNCPY_ZEROFILL
-#define USING_MIG_STRNCPY_ZEROFILL
-#endif
-#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__
-#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__
-#ifdef __cplusplus
-extern "C" {
-#endif
- extern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import));
-#ifdef __cplusplus
-}
-#endif
-#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */
-#endif /* __has_include() */
-#endif /* __has_include */
-
-/* END MIG_STRNCPY_ZEROFILL CODE */
-
-
-#ifdef AUTOTEST
-#ifndef FUNCTION_PTR_T
-#define FUNCTION_PTR_T
-typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t);
-typedef struct {
- char *name;
- function_ptr_t function;
-} function_table_entry;
-typedef function_table_entry *function_table_t;
-#endif /* FUNCTION_PTR_T */
-#endif /* AUTOTEST */
-
-#ifndef mach_port_MSG_COUNT
-#define mach_port_MSG_COUNT 40
-#endif /* mach_port_MSG_COUNT */
-
-#include
-#include
-#include
-#include
-#include
-
-#ifdef __BeforeMigUserHeader
-__BeforeMigUserHeader
-#endif /* __BeforeMigUserHeader */
-
-#include
-__BEGIN_DECLS
-
-
-/* Routine mach_port_names */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_names
-(
- ipc_space_t task,
- mach_port_name_array_t *names,
- mach_msg_type_number_t *namesCnt,
- mach_port_type_array_t *types,
- mach_msg_type_number_t *typesCnt
-);
-
-/* Routine mach_port_type */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_type
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_type_t *ptype
-);
-
-/* Routine mach_port_rename */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_rename
-(
- ipc_space_t task,
- mach_port_name_t old_name,
- mach_port_name_t new_name
-);
-
-/* Routine mach_port_allocate_name */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-__WATCHOS_PROHIBITED
-__TVOS_PROHIBITED
-kern_return_t mach_port_allocate_name
-(
- ipc_space_t task,
- mach_port_right_t right,
- mach_port_name_t name
-);
-
-/* Routine mach_port_allocate */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_allocate
-(
- ipc_space_t task,
- mach_port_right_t right,
- mach_port_name_t *name
-);
-
-/* Routine mach_port_destroy */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_destroy
-(
- ipc_space_t task,
- mach_port_name_t name
-);
-
-/* Routine mach_port_deallocate */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_deallocate
-(
- ipc_space_t task,
- mach_port_name_t name
-);
-
-/* Routine mach_port_get_refs */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_get_refs
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_right_t right,
- mach_port_urefs_t *refs
-);
-
-/* Routine mach_port_mod_refs */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_mod_refs
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_right_t right,
- mach_port_delta_t delta
-);
-
-/* Routine mach_port_peek */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_peek
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_msg_trailer_type_t trailer_type,
- mach_port_seqno_t *request_seqnop,
- mach_msg_size_t *msg_sizep,
- mach_msg_id_t *msg_idp,
- mach_msg_trailer_info_t trailer_infop,
- mach_msg_type_number_t *trailer_infopCnt
-);
-
-/* Routine mach_port_set_mscount */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_set_mscount
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_mscount_t mscount
-);
-
-/* Routine mach_port_get_set_status */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_get_set_status
-(
- ipc_space_inspect_t task,
- mach_port_name_t name,
- mach_port_name_array_t *members,
- mach_msg_type_number_t *membersCnt
-);
-
-/* Routine mach_port_move_member */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_move_member
-(
- ipc_space_t task,
- mach_port_name_t member,
- mach_port_name_t after
-);
-
-/* Routine mach_port_request_notification */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_request_notification
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_msg_id_t msgid,
- mach_port_mscount_t sync,
- mach_port_t notify,
- mach_msg_type_name_t notifyPoly,
- mach_port_t *previous
-);
-
-/* Routine mach_port_insert_right */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_insert_right
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_t poly,
- mach_msg_type_name_t polyPoly
-);
-
-/* Routine mach_port_extract_right */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_extract_right
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_msg_type_name_t msgt_name,
- mach_port_t *poly,
- mach_msg_type_name_t *polyPoly
-);
-
-/* Routine mach_port_set_seqno */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_set_seqno
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_seqno_t seqno
-);
-
-/* Routine mach_port_get_attributes */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_get_attributes
-(
- ipc_space_inspect_t task,
- mach_port_name_t name,
- mach_port_flavor_t flavor,
- mach_port_info_t port_info_out,
- mach_msg_type_number_t *port_info_outCnt
-);
-
-/* Routine mach_port_set_attributes */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_set_attributes
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_flavor_t flavor,
- mach_port_info_t port_info,
- mach_msg_type_number_t port_infoCnt
-);
-
-/* Routine mach_port_allocate_qos */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_allocate_qos
-(
- ipc_space_t task,
- mach_port_right_t right,
- mach_port_qos_t *qos,
- mach_port_name_t *name
-);
-
-/* Routine mach_port_allocate_full */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_allocate_full
-(
- ipc_space_t task,
- mach_port_right_t right,
- mach_port_t proto,
- mach_port_qos_t *qos,
- mach_port_name_t *name
-);
-
-/* Routine task_set_port_space */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-__WATCHOS_PROHIBITED
-__TVOS_PROHIBITED
-kern_return_t task_set_port_space
-(
- ipc_space_t task,
- int table_entries
-);
-
-/* Routine mach_port_get_srights */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_get_srights
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_rights_t *srights
-);
-
-/* Routine mach_port_space_info */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_space_info
-(
- ipc_space_inspect_t task,
- ipc_info_space_t *space_info,
- ipc_info_name_array_t *table_info,
- mach_msg_type_number_t *table_infoCnt,
- ipc_info_tree_name_array_t *tree_info,
- mach_msg_type_number_t *tree_infoCnt
-);
-
-/* Routine mach_port_dnrequest_info */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_dnrequest_info
-(
- ipc_space_t task,
- mach_port_name_t name,
- unsigned *dnr_total,
- unsigned *dnr_used
-);
-
-/* Routine mach_port_kernel_object */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_kernel_object
-(
- ipc_space_inspect_t task,
- mach_port_name_t name,
- unsigned *object_type,
- unsigned *object_addr
-);
-
-/* Routine mach_port_insert_member */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_insert_member
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_name_t pset
-);
-
-/* Routine mach_port_extract_member */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_extract_member
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_name_t pset
-);
-
-/* Routine mach_port_get_context */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_get_context
-(
- ipc_space_inspect_t task,
- mach_port_name_t name,
- mach_port_context_t *context
-);
-
-/* Routine mach_port_set_context */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_set_context
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_context_t context
-);
-
-/* Routine mach_port_kobject */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_kobject
-(
- ipc_space_inspect_t task,
- mach_port_name_t name,
- natural_t *object_type,
- mach_vm_address_t *object_addr
-);
-
-/* Routine mach_port_construct */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_construct
-(
- ipc_space_t task,
- mach_port_options_ptr_t options,
- mach_port_context_t context,
- mach_port_name_t *name
-);
-
-/* Routine mach_port_destruct */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_destruct
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_delta_t srdelta,
- mach_port_context_t guard
-);
-
-/* Routine mach_port_guard */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_guard
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_context_t guard,
- boolean_t strict
-);
-
-/* Routine mach_port_unguard */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_unguard
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_context_t guard
-);
-
-/* Routine mach_port_space_basic_info */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_space_basic_info
-(
- ipc_space_inspect_t task,
- ipc_info_space_basic_t *basic_info
-);
-
-/* Routine mach_port_guard_with_flags */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_guard_with_flags
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_context_t guard,
- uint64_t flags
-);
-
-/* Routine mach_port_swap_guard */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_swap_guard
-(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_context_t old_guard,
- mach_port_context_t new_guard
-);
-
-/* Routine mach_port_kobject_description */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t mach_port_kobject_description
-(
- ipc_space_inspect_t task,
- mach_port_name_t name,
- natural_t *object_type,
- mach_vm_address_t *object_addr,
- kobject_description_t description
-);
-
-__END_DECLS
-
-/********************** Caution **************************/
-/* The following data types should be used to calculate */
-/* maximum message sizes only. The actual message may be */
-/* smaller, and the position of the arguments within the */
-/* message layout may vary from what is presented here. */
-/* For example, if any of the arguments are variable- */
-/* sized, and less than the maximum is sent, the data */
-/* will be packed tight in the actual message to reduce */
-/* the presence of holes. */
-/********************** Caution **************************/
-
-/* typedefs for all requests */
-
-#ifndef __Request__mach_port_subsystem__defined
-#define __Request__mach_port_subsystem__defined
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- } __Request__mach_port_names_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_type_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t old_name;
- mach_port_name_t new_name;
- } __Request__mach_port_rename_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_right_t right;
- mach_port_name_t name;
- } __Request__mach_port_allocate_name_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_right_t right;
- } __Request__mach_port_allocate_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_destroy_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_deallocate_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_right_t right;
- } __Request__mach_port_get_refs_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_right_t right;
- mach_port_delta_t delta;
- } __Request__mach_port_mod_refs_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_msg_trailer_type_t trailer_type;
- mach_port_seqno_t request_seqnop;
- mach_msg_type_number_t trailer_infopCnt;
- } __Request__mach_port_peek_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_mscount_t mscount;
- } __Request__mach_port_set_mscount_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_get_set_status_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t member;
- mach_port_name_t after;
- } __Request__mach_port_move_member_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t notify;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_msg_id_t msgid;
- mach_port_mscount_t sync;
- } __Request__mach_port_request_notification_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t poly;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_insert_right_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_msg_type_name_t msgt_name;
- } __Request__mach_port_extract_right_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_seqno_t seqno;
- } __Request__mach_port_set_seqno_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_flavor_t flavor;
- mach_msg_type_number_t port_info_outCnt;
- } __Request__mach_port_get_attributes_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_flavor_t flavor;
- mach_msg_type_number_t port_infoCnt;
- integer_t port_info[17];
- } __Request__mach_port_set_attributes_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_right_t right;
- mach_port_qos_t qos;
- } __Request__mach_port_allocate_qos_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t proto;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- mach_port_right_t right;
- mach_port_qos_t qos;
- mach_port_name_t name;
- } __Request__mach_port_allocate_full_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- int table_entries;
- } __Request__task_set_port_space_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_get_srights_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- } __Request__mach_port_space_info_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_dnrequest_info_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_kernel_object_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_name_t pset;
- } __Request__mach_port_insert_member_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_name_t pset;
- } __Request__mach_port_extract_member_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_get_context_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_context_t context;
- } __Request__mach_port_set_context_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_kobject_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_ool_descriptor_t options;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- mach_port_context_t context;
- } __Request__mach_port_construct_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_delta_t srdelta;
- mach_port_context_t guard;
- } __Request__mach_port_destruct_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_context_t guard;
- boolean_t strict;
- } __Request__mach_port_guard_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_context_t guard;
- } __Request__mach_port_unguard_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- } __Request__mach_port_space_basic_info_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_context_t guard;
- uint64_t flags;
- } __Request__mach_port_guard_with_flags_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- mach_port_context_t old_guard;
- mach_port_context_t new_guard;
- } __Request__mach_port_swap_guard_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- mach_port_name_t name;
- } __Request__mach_port_kobject_description_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-#endif /* !__Request__mach_port_subsystem__defined */
-
-/* union of all requests */
-
-#ifndef __RequestUnion__mach_port_subsystem__defined
-#define __RequestUnion__mach_port_subsystem__defined
-union __RequestUnion__mach_port_subsystem {
- __Request__mach_port_names_t Request_mach_port_names;
- __Request__mach_port_type_t Request_mach_port_type;
- __Request__mach_port_rename_t Request_mach_port_rename;
- __Request__mach_port_allocate_name_t Request_mach_port_allocate_name;
- __Request__mach_port_allocate_t Request_mach_port_allocate;
- __Request__mach_port_destroy_t Request_mach_port_destroy;
- __Request__mach_port_deallocate_t Request_mach_port_deallocate;
- __Request__mach_port_get_refs_t Request_mach_port_get_refs;
- __Request__mach_port_mod_refs_t Request_mach_port_mod_refs;
- __Request__mach_port_peek_t Request_mach_port_peek;
- __Request__mach_port_set_mscount_t Request_mach_port_set_mscount;
- __Request__mach_port_get_set_status_t Request_mach_port_get_set_status;
- __Request__mach_port_move_member_t Request_mach_port_move_member;
- __Request__mach_port_request_notification_t Request_mach_port_request_notification;
- __Request__mach_port_insert_right_t Request_mach_port_insert_right;
- __Request__mach_port_extract_right_t Request_mach_port_extract_right;
- __Request__mach_port_set_seqno_t Request_mach_port_set_seqno;
- __Request__mach_port_get_attributes_t Request_mach_port_get_attributes;
- __Request__mach_port_set_attributes_t Request_mach_port_set_attributes;
- __Request__mach_port_allocate_qos_t Request_mach_port_allocate_qos;
- __Request__mach_port_allocate_full_t Request_mach_port_allocate_full;
- __Request__task_set_port_space_t Request_task_set_port_space;
- __Request__mach_port_get_srights_t Request_mach_port_get_srights;
- __Request__mach_port_space_info_t Request_mach_port_space_info;
- __Request__mach_port_dnrequest_info_t Request_mach_port_dnrequest_info;
- __Request__mach_port_kernel_object_t Request_mach_port_kernel_object;
- __Request__mach_port_insert_member_t Request_mach_port_insert_member;
- __Request__mach_port_extract_member_t Request_mach_port_extract_member;
- __Request__mach_port_get_context_t Request_mach_port_get_context;
- __Request__mach_port_set_context_t Request_mach_port_set_context;
- __Request__mach_port_kobject_t Request_mach_port_kobject;
- __Request__mach_port_construct_t Request_mach_port_construct;
- __Request__mach_port_destruct_t Request_mach_port_destruct;
- __Request__mach_port_guard_t Request_mach_port_guard;
- __Request__mach_port_unguard_t Request_mach_port_unguard;
- __Request__mach_port_space_basic_info_t Request_mach_port_space_basic_info;
- __Request__mach_port_guard_with_flags_t Request_mach_port_guard_with_flags;
- __Request__mach_port_swap_guard_t Request_mach_port_swap_guard;
- __Request__mach_port_kobject_description_t Request_mach_port_kobject_description;
-};
-#endif /* !__RequestUnion__mach_port_subsystem__defined */
-/* typedefs for all replies */
-
-#ifndef __Reply__mach_port_subsystem__defined
-#define __Reply__mach_port_subsystem__defined
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_ool_descriptor_t names;
- mach_msg_ool_descriptor_t types;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- mach_msg_type_number_t namesCnt;
- mach_msg_type_number_t typesCnt;
- } __Reply__mach_port_names_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_port_type_t ptype;
- } __Reply__mach_port_type_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_rename_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_allocate_name_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_port_name_t name;
- } __Reply__mach_port_allocate_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_destroy_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_deallocate_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_port_urefs_t refs;
- } __Reply__mach_port_get_refs_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_mod_refs_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_port_seqno_t request_seqnop;
- mach_msg_size_t msg_sizep;
- mach_msg_id_t msg_idp;
- mach_msg_type_number_t trailer_infopCnt;
- char trailer_infop[68];
- } __Reply__mach_port_peek_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_set_mscount_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_ool_descriptor_t members;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- mach_msg_type_number_t membersCnt;
- } __Reply__mach_port_get_set_status_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_move_member_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t previous;
- /* end of the kernel processed data */
- } __Reply__mach_port_request_notification_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_insert_right_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t poly;
- /* end of the kernel processed data */
- } __Reply__mach_port_extract_right_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_set_seqno_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_msg_type_number_t port_info_outCnt;
- integer_t port_info_out[17];
- } __Reply__mach_port_get_attributes_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_set_attributes_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_port_qos_t qos;
- mach_port_name_t name;
- } __Reply__mach_port_allocate_qos_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_port_qos_t qos;
- mach_port_name_t name;
- } __Reply__mach_port_allocate_full_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__task_set_port_space_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_port_rights_t srights;
- } __Reply__mach_port_get_srights_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_ool_descriptor_t table_info;
- mach_msg_ool_descriptor_t tree_info;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- ipc_info_space_t space_info;
- mach_msg_type_number_t table_infoCnt;
- mach_msg_type_number_t tree_infoCnt;
- } __Reply__mach_port_space_info_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- unsigned dnr_total;
- unsigned dnr_used;
- } __Reply__mach_port_dnrequest_info_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- unsigned object_type;
- unsigned object_addr;
- } __Reply__mach_port_kernel_object_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_insert_member_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_extract_member_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_port_context_t context;
- } __Reply__mach_port_get_context_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_set_context_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- natural_t object_type;
- mach_vm_address_t object_addr;
- } __Reply__mach_port_kobject_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- mach_port_name_t name;
- } __Reply__mach_port_construct_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_destruct_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_guard_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_unguard_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- ipc_info_space_basic_t basic_info;
- } __Reply__mach_port_space_basic_info_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_guard_with_flags_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_port_swap_guard_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(push, 4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- natural_t object_type;
- mach_vm_address_t object_addr;
- mach_msg_type_number_t descriptionOffset; /* MiG doesn't use it */
- mach_msg_type_number_t descriptionCnt;
- char description[512];
- } __Reply__mach_port_kobject_description_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack(pop)
-#endif
-#endif /* !__Reply__mach_port_subsystem__defined */
-
-/* union of all replies */
-
-#ifndef __ReplyUnion__mach_port_subsystem__defined
-#define __ReplyUnion__mach_port_subsystem__defined
-union __ReplyUnion__mach_port_subsystem {
- __Reply__mach_port_names_t Reply_mach_port_names;
- __Reply__mach_port_type_t Reply_mach_port_type;
- __Reply__mach_port_rename_t Reply_mach_port_rename;
- __Reply__mach_port_allocate_name_t Reply_mach_port_allocate_name;
- __Reply__mach_port_allocate_t Reply_mach_port_allocate;
- __Reply__mach_port_destroy_t Reply_mach_port_destroy;
- __Reply__mach_port_deallocate_t Reply_mach_port_deallocate;
- __Reply__mach_port_get_refs_t Reply_mach_port_get_refs;
- __Reply__mach_port_mod_refs_t Reply_mach_port_mod_refs;
- __Reply__mach_port_peek_t Reply_mach_port_peek;
- __Reply__mach_port_set_mscount_t Reply_mach_port_set_mscount;
- __Reply__mach_port_get_set_status_t Reply_mach_port_get_set_status;
- __Reply__mach_port_move_member_t Reply_mach_port_move_member;
- __Reply__mach_port_request_notification_t Reply_mach_port_request_notification;
- __Reply__mach_port_insert_right_t Reply_mach_port_insert_right;
- __Reply__mach_port_extract_right_t Reply_mach_port_extract_right;
- __Reply__mach_port_set_seqno_t Reply_mach_port_set_seqno;
- __Reply__mach_port_get_attributes_t Reply_mach_port_get_attributes;
- __Reply__mach_port_set_attributes_t Reply_mach_port_set_attributes;
- __Reply__mach_port_allocate_qos_t Reply_mach_port_allocate_qos;
- __Reply__mach_port_allocate_full_t Reply_mach_port_allocate_full;
- __Reply__task_set_port_space_t Reply_task_set_port_space;
- __Reply__mach_port_get_srights_t Reply_mach_port_get_srights;
- __Reply__mach_port_space_info_t Reply_mach_port_space_info;
- __Reply__mach_port_dnrequest_info_t Reply_mach_port_dnrequest_info;
- __Reply__mach_port_kernel_object_t Reply_mach_port_kernel_object;
- __Reply__mach_port_insert_member_t Reply_mach_port_insert_member;
- __Reply__mach_port_extract_member_t Reply_mach_port_extract_member;
- __Reply__mach_port_get_context_t Reply_mach_port_get_context;
- __Reply__mach_port_set_context_t Reply_mach_port_set_context;
- __Reply__mach_port_kobject_t Reply_mach_port_kobject;
- __Reply__mach_port_construct_t Reply_mach_port_construct;
- __Reply__mach_port_destruct_t Reply_mach_port_destruct;
- __Reply__mach_port_guard_t Reply_mach_port_guard;
- __Reply__mach_port_unguard_t Reply_mach_port_unguard;
- __Reply__mach_port_space_basic_info_t Reply_mach_port_space_basic_info;
- __Reply__mach_port_guard_with_flags_t Reply_mach_port_guard_with_flags;
- __Reply__mach_port_swap_guard_t Reply_mach_port_swap_guard;
- __Reply__mach_port_kobject_description_t Reply_mach_port_kobject_description;
-};
-#endif /* !__RequestUnion__mach_port_subsystem__defined */
-
-#ifndef subsystem_to_name_map_mach_port
-#define subsystem_to_name_map_mach_port \
- { "mach_port_names", 3200 },\
- { "mach_port_type", 3201 },\
- { "mach_port_rename", 3202 },\
- { "mach_port_allocate_name", 3203 },\
- { "mach_port_allocate", 3204 },\
- { "mach_port_destroy", 3205 },\
- { "mach_port_deallocate", 3206 },\
- { "mach_port_get_refs", 3207 },\
- { "mach_port_mod_refs", 3208 },\
- { "mach_port_peek", 3209 },\
- { "mach_port_set_mscount", 3210 },\
- { "mach_port_get_set_status", 3211 },\
- { "mach_port_move_member", 3212 },\
- { "mach_port_request_notification", 3213 },\
- { "mach_port_insert_right", 3214 },\
- { "mach_port_extract_right", 3215 },\
- { "mach_port_set_seqno", 3216 },\
- { "mach_port_get_attributes", 3217 },\
- { "mach_port_set_attributes", 3218 },\
- { "mach_port_allocate_qos", 3219 },\
- { "mach_port_allocate_full", 3220 },\
- { "task_set_port_space", 3221 },\
- { "mach_port_get_srights", 3222 },\
- { "mach_port_space_info", 3223 },\
- { "mach_port_dnrequest_info", 3224 },\
- { "mach_port_kernel_object", 3225 },\
- { "mach_port_insert_member", 3226 },\
- { "mach_port_extract_member", 3227 },\
- { "mach_port_get_context", 3228 },\
- { "mach_port_set_context", 3229 },\
- { "mach_port_kobject", 3230 },\
- { "mach_port_construct", 3231 },\
- { "mach_port_destruct", 3232 },\
- { "mach_port_guard", 3233 },\
- { "mach_port_unguard", 3234 },\
- { "mach_port_space_basic_info", 3235 },\
- { "mach_port_guard_with_flags", 3237 },\
- { "mach_port_swap_guard", 3238 },\
- { "mach_port_kobject_description", 3239 }
-#endif
-
-#ifdef __AfterMigUserHeader
-__AfterMigUserHeader
-#endif /* __AfterMigUserHeader */
-
-#endif /* _mach_port_user_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/mach_traps.h b/lib/libc/include/x86_64-macos-gnu/mach/mach_traps.h
deleted file mode 100644
index d3aaf577ed..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/mach_traps.h
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- */
-/*
- * Definitions of general Mach system traps.
- *
- * These are the definitions as seen from user-space.
- * The kernel definitions are in .
- * Kernel RPC functions are defined in .
- */
-
-#ifndef _MACH_MACH_TRAPS_H_
-#define _MACH_MACH_TRAPS_H_
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include
-
-__BEGIN_DECLS
-
-
-
-extern kern_return_t clock_sleep_trap(
- mach_port_name_t clock_name,
- sleep_type_t sleep_type,
- int sleep_sec,
- int sleep_nsec,
- mach_timespec_t *wakeup_time);
-
-extern kern_return_t _kernelrpc_mach_vm_allocate_trap(
- mach_port_name_t target,
- mach_vm_offset_t *addr,
- mach_vm_size_t size,
- int flags);
-
-extern kern_return_t _kernelrpc_mach_vm_deallocate_trap(
- mach_port_name_t target,
- mach_vm_address_t address,
- mach_vm_size_t size
- );
-
-extern kern_return_t _kernelrpc_mach_vm_protect_trap(
- mach_port_name_t target,
- mach_vm_address_t address,
- mach_vm_size_t size,
- boolean_t set_maximum,
- vm_prot_t new_protection
- );
-
-extern kern_return_t _kernelrpc_mach_vm_map_trap(
- mach_port_name_t target,
- mach_vm_offset_t *address,
- mach_vm_size_t size,
- mach_vm_offset_t mask,
- int flags,
- vm_prot_t cur_protection
- );
-
-extern kern_return_t _kernelrpc_mach_vm_purgable_control_trap(
- mach_port_name_t target,
- mach_vm_offset_t address,
- vm_purgable_t control,
- int *state);
-
-extern kern_return_t _kernelrpc_mach_port_allocate_trap(
- mach_port_name_t target,
- mach_port_right_t right,
- mach_port_name_t *name
- );
-
-
-extern kern_return_t _kernelrpc_mach_port_destroy_trap(
- mach_port_name_t target,
- mach_port_name_t name
- );
-
-extern kern_return_t _kernelrpc_mach_port_deallocate_trap(
- mach_port_name_t target,
- mach_port_name_t name
- );
-
-extern kern_return_t _kernelrpc_mach_port_mod_refs_trap(
- mach_port_name_t target,
- mach_port_name_t name,
- mach_port_right_t right,
- mach_port_delta_t delta
- );
-
-extern kern_return_t _kernelrpc_mach_port_move_member_trap(
- mach_port_name_t target,
- mach_port_name_t member,
- mach_port_name_t after
- );
-
-extern kern_return_t _kernelrpc_mach_port_insert_right_trap(
- mach_port_name_t target,
- mach_port_name_t name,
- mach_port_name_t poly,
- mach_msg_type_name_t polyPoly
- );
-
-extern kern_return_t _kernelrpc_mach_port_get_attributes_trap(
- mach_port_name_t target,
- mach_port_name_t name,
- mach_port_flavor_t flavor,
- mach_port_info_t port_info_out,
- mach_msg_type_number_t *port_info_outCnt
- );
-
-extern kern_return_t _kernelrpc_mach_port_insert_member_trap(
- mach_port_name_t target,
- mach_port_name_t name,
- mach_port_name_t pset
- );
-
-extern kern_return_t _kernelrpc_mach_port_extract_member_trap(
- mach_port_name_t target,
- mach_port_name_t name,
- mach_port_name_t pset
- );
-
-extern kern_return_t _kernelrpc_mach_port_construct_trap(
- mach_port_name_t target,
- mach_port_options_t *options,
- uint64_t context,
- mach_port_name_t *name
- );
-
-extern kern_return_t _kernelrpc_mach_port_destruct_trap(
- mach_port_name_t target,
- mach_port_name_t name,
- mach_port_delta_t srdelta,
- uint64_t guard
- );
-
-extern kern_return_t _kernelrpc_mach_port_guard_trap(
- mach_port_name_t target,
- mach_port_name_t name,
- uint64_t guard,
- boolean_t strict
- );
-
-extern kern_return_t _kernelrpc_mach_port_unguard_trap(
- mach_port_name_t target,
- mach_port_name_t name,
- uint64_t guard
- );
-
-extern kern_return_t mach_generate_activity_id(
- mach_port_name_t target,
- int count,
- uint64_t *activity_id
- );
-
-extern kern_return_t macx_swapon(
- uint64_t filename,
- int flags,
- int size,
- int priority);
-
-extern kern_return_t macx_swapoff(
- uint64_t filename,
- int flags);
-
-extern kern_return_t macx_triggers(
- int hi_water,
- int low_water,
- int flags,
- mach_port_t alert_port);
-
-extern kern_return_t macx_backing_store_suspend(
- boolean_t suspend);
-
-extern kern_return_t macx_backing_store_recovery(
- int pid);
-
-extern boolean_t swtch_pri(int pri);
-
-extern boolean_t swtch(void);
-
-extern kern_return_t thread_switch(
- mach_port_name_t thread_name,
- int option,
- mach_msg_timeout_t option_time);
-
-extern mach_port_name_t task_self_trap(void);
-
-extern kern_return_t host_create_mach_voucher_trap(
- mach_port_name_t host,
- mach_voucher_attr_raw_recipe_array_t recipes,
- int recipes_size,
- mach_port_name_t *voucher);
-
-extern kern_return_t mach_voucher_extract_attr_recipe_trap(
- mach_port_name_t voucher_name,
- mach_voucher_attr_key_t key,
- mach_voucher_attr_raw_recipe_t recipe,
- mach_msg_type_number_t *recipe_size);
-
-extern kern_return_t _kernelrpc_mach_port_type_trap(
- ipc_space_t task,
- mach_port_name_t name,
- mach_port_type_t *ptype);
-
-extern kern_return_t _kernelrpc_mach_port_request_notification_trap(
- ipc_space_t task,
- mach_port_name_t name,
- mach_msg_id_t msgid,
- mach_port_mscount_t sync,
- mach_port_name_t notify,
- mach_msg_type_name_t notifyPoly,
- mach_port_name_t *previous);
-
-/*
- * Obsolete interfaces.
- */
-
-extern kern_return_t task_for_pid(
- mach_port_name_t target_tport,
- int pid,
- mach_port_name_t *t);
-
-extern kern_return_t task_name_for_pid(
- mach_port_name_t target_tport,
- int pid,
- mach_port_name_t *tn);
-
-extern kern_return_t pid_for_task(
- mach_port_name_t t,
- int *x);
-
-extern kern_return_t debug_control_port_for_pid(
- mach_port_name_t target_tport,
- int pid,
- mach_port_name_t *t);
-
-
-__END_DECLS
-
-#endif /* _MACH_MACH_TRAPS_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/mach_types.h b/lib/libc/include/x86_64-macos-gnu/mach/mach_types.h
deleted file mode 100644
index 0c35705acf..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/mach_types.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- */
-/*
- * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
- * support for mandatory and extensible security protections. This notice
- * is included in support of clause 2.2 (b) of the Apple Public License,
- * Version 2.0.
- */
-/*
- * File: mach/mach_types.h
- * Author: Avadis Tevanian, Jr., Michael Wayne Young
- * Date: 1986
- *
- * Mach external interface definitions.
- *
- */
-
-#ifndef _MACH_MACH_TYPES_H_
-#define _MACH_MACH_TYPES_H_
-
-#include
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-/*
- * If we are not in the kernel, then these will all be represented by
- * ports at user-space.
- */
-typedef mach_port_t task_t;
-typedef mach_port_t task_name_t;
-typedef mach_port_t task_inspect_t;
-typedef mach_port_t task_suspension_token_t;
-typedef mach_port_t thread_t;
-typedef mach_port_t thread_act_t;
-typedef mach_port_t thread_inspect_t;
-typedef mach_port_t ipc_space_t;
-typedef mach_port_t ipc_space_inspect_t;
-typedef mach_port_t coalition_t;
-typedef mach_port_t host_t;
-typedef mach_port_t host_priv_t;
-typedef mach_port_t host_security_t;
-typedef mach_port_t processor_t;
-typedef mach_port_t processor_set_t;
-typedef mach_port_t processor_set_control_t;
-typedef mach_port_t semaphore_t;
-typedef mach_port_t lock_set_t;
-typedef mach_port_t ledger_t;
-typedef mach_port_t alarm_t;
-typedef mach_port_t clock_serv_t;
-typedef mach_port_t clock_ctrl_t;
-typedef mach_port_t arcade_register_t;
-typedef mach_port_t suid_cred_t;
-
-
-/*
- * These aren't really unique types. They are just called
- * out as unique types at one point in history. So we list
- * them here for compatibility.
- */
-typedef processor_set_t processor_set_name_t;
-
-/*
- * These types are just hard-coded as ports
- */
-typedef mach_port_t clock_reply_t;
-typedef mach_port_t bootstrap_t;
-typedef mach_port_t mem_entry_name_port_t;
-typedef mach_port_t exception_handler_t;
-typedef exception_handler_t *exception_handler_array_t;
-typedef mach_port_t vm_task_entry_t;
-typedef mach_port_t io_master_t;
-typedef mach_port_t UNDServerRef;
-
-/*
- * Mig doesn't translate the components of an array.
- * For example, Mig won't use the thread_t translations
- * to translate a thread_array_t argument. So, these definitions
- * are not completely accurate at the moment for other kernel
- * components.
- */
-typedef task_t *task_array_t;
-typedef thread_t *thread_array_t;
-typedef processor_set_t *processor_set_array_t;
-typedef processor_set_t *processor_set_name_array_t;
-typedef processor_t *processor_array_t;
-typedef thread_act_t *thread_act_array_t;
-typedef ledger_t *ledger_array_t;
-
-/*
- * However the real mach_types got declared, we also have to declare
- * types with "port" in the name for compatability with the way OSF
- * had declared the user interfaces at one point. Someday these should
- * go away.
- */
-typedef task_t task_port_t;
-typedef task_array_t task_port_array_t;
-typedef thread_t thread_port_t;
-typedef thread_array_t thread_port_array_t;
-typedef ipc_space_t ipc_space_port_t;
-typedef host_t host_name_t;
-typedef host_t host_name_port_t;
-typedef processor_set_t processor_set_port_t;
-typedef processor_set_t processor_set_name_port_t;
-typedef processor_set_array_t processor_set_name_port_array_t;
-typedef processor_set_t processor_set_control_port_t;
-typedef processor_t processor_port_t;
-typedef processor_array_t processor_port_array_t;
-typedef thread_act_t thread_act_port_t;
-typedef thread_act_array_t thread_act_port_array_t;
-typedef semaphore_t semaphore_port_t;
-typedef lock_set_t lock_set_port_t;
-typedef ledger_t ledger_port_t;
-typedef ledger_array_t ledger_port_array_t;
-typedef alarm_t alarm_port_t;
-typedef clock_serv_t clock_serv_port_t;
-typedef clock_ctrl_t clock_ctrl_port_t;
-typedef exception_handler_t exception_port_t;
-typedef exception_handler_array_t exception_port_arrary_t;
-typedef char vfs_path_t[4096];
-typedef char nspace_path_t[1024]; /* 1024 == PATH_MAX */
-typedef char suid_cred_path_t[1024];
-typedef uint32_t suid_cred_uid_t;
-
-#define TASK_NULL ((task_t) 0)
-#define TASK_NAME_NULL ((task_name_t) 0)
-#define TASK_INSPECT_NULL ((task_inspect_t) 0)
-#define THREAD_NULL ((thread_t) 0)
-#define THREAD_INSPECT_NULL ((thread_inspect_t) 0)
-#define TID_NULL ((uint64_t) 0)
-#define THR_ACT_NULL ((thread_act_t) 0)
-#define IPC_SPACE_NULL ((ipc_space_t) 0)
-#define IPC_SPACE_INSPECT_NULL ((ipc_space_inspect_t) 0)
-#define COALITION_NULL ((coalition_t) 0)
-#define HOST_NULL ((host_t) 0)
-#define HOST_PRIV_NULL ((host_priv_t) 0)
-#define HOST_SECURITY_NULL ((host_security_t) 0)
-#define PROCESSOR_SET_NULL ((processor_set_t) 0)
-#define PROCESSOR_NULL ((processor_t) 0)
-#define SEMAPHORE_NULL ((semaphore_t) 0)
-#define LOCK_SET_NULL ((lock_set_t) 0)
-#define LEDGER_NULL ((ledger_t) 0)
-#define ALARM_NULL ((alarm_t) 0)
-#define CLOCK_NULL ((clock_t) 0)
-#define UND_SERVER_NULL ((UNDServerRef) 0)
-#define ARCADE_REG_NULL ((arcade_register_t) 0)
-#define SUID_CRED_NULL ((suid_cred_t) 0)
-
-/* DEPRECATED */
-typedef natural_t ledger_item_t;
-#define LEDGER_ITEM_INFINITY ((ledger_item_t) (~0))
-
-typedef int64_t ledger_amount_t;
-#define LEDGER_LIMIT_INFINITY ((ledger_amount_t)((1ULL << 63) - 1))
-
-typedef mach_vm_offset_t *emulation_vector_t;
-typedef char *user_subsystem_t;
-
-typedef char *labelstr_t;
-/*
- * Backwards compatibility, for those programs written
- * before mach/{std,mach}_types.{defs,h} were set up.
- */
-#include
-
-#endif /* _MACH_MACH_TYPES_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine.h b/lib/libc/include/x86_64-macos-gnu/mach/machine.h
deleted file mode 100644
index 30aafcc812..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine.h
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (c) 2007-2016 Apple, Inc. All rights reserved.
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/* File: machine.h
- * Author: Avadis Tevanian, Jr.
- * Date: 1986
- *
- * Machine independent machine abstraction.
- */
-
-#ifndef _MACH_MACHINE_H_
-#define _MACH_MACHINE_H_
-
-#ifndef __ASSEMBLER__
-
-#include
-#include
-#include
-
-typedef integer_t cpu_type_t;
-typedef integer_t cpu_subtype_t;
-typedef integer_t cpu_threadtype_t;
-
-#define CPU_STATE_MAX 4
-
-#define CPU_STATE_USER 0
-#define CPU_STATE_SYSTEM 1
-#define CPU_STATE_IDLE 2
-#define CPU_STATE_NICE 3
-
-
-
-/*
- * Capability bits used in the definition of cpu_type.
- */
-#define CPU_ARCH_MASK 0xff000000 /* mask for architecture bits */
-#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */
-#define CPU_ARCH_ABI64_32 0x02000000 /* ABI for 64-bit hardware with 32-bit types; LP32 */
-
-/*
- * Machine types known by all.
- */
-
-#define CPU_TYPE_ANY ((cpu_type_t) -1)
-
-#define CPU_TYPE_VAX ((cpu_type_t) 1)
-/* skip ((cpu_type_t) 2) */
-/* skip ((cpu_type_t) 3) */
-/* skip ((cpu_type_t) 4) */
-/* skip ((cpu_type_t) 5) */
-#define CPU_TYPE_MC680x0 ((cpu_type_t) 6)
-#define CPU_TYPE_X86 ((cpu_type_t) 7)
-#define CPU_TYPE_I386 CPU_TYPE_X86 /* compatibility */
-#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64)
-
-/* skip CPU_TYPE_MIPS ((cpu_type_t) 8) */
-/* skip ((cpu_type_t) 9) */
-#define CPU_TYPE_MC98000 ((cpu_type_t) 10)
-#define CPU_TYPE_HPPA ((cpu_type_t) 11)
-#define CPU_TYPE_ARM ((cpu_type_t) 12)
-#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
-#define CPU_TYPE_ARM64_32 (CPU_TYPE_ARM | CPU_ARCH_ABI64_32)
-#define CPU_TYPE_MC88000 ((cpu_type_t) 13)
-#define CPU_TYPE_SPARC ((cpu_type_t) 14)
-#define CPU_TYPE_I860 ((cpu_type_t) 15)
-/* skip CPU_TYPE_ALPHA ((cpu_type_t) 16) */
-/* skip ((cpu_type_t) 17) */
-#define CPU_TYPE_POWERPC ((cpu_type_t) 18)
-#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
-/* skip ((cpu_type_t) 19) */
-
-/*
- * Machine subtypes (these are defined here, instead of in a machine
- * dependent directory, so that any program can get all definitions
- * regardless of where is it compiled).
- */
-
-/*
- * Capability bits used in the definition of cpu_subtype.
- */
-#define CPU_SUBTYPE_MASK 0xff000000 /* mask for feature flags */
-#define CPU_SUBTYPE_LIB64 0x80000000 /* 64 bit libraries */
-
-
-/*
- * Object files that are hand-crafted to run on any
- * implementation of an architecture are tagged with
- * CPU_SUBTYPE_MULTIPLE. This functions essentially the same as
- * the "ALL" subtype of an architecture except that it allows us
- * to easily find object files that may need to be modified
- * whenever a new implementation of an architecture comes out.
- *
- * It is the responsibility of the implementor to make sure the
- * software handles unsupported implementations elegantly.
- */
-#define CPU_SUBTYPE_MULTIPLE ((cpu_subtype_t) -1)
-#define CPU_SUBTYPE_LITTLE_ENDIAN ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_BIG_ENDIAN ((cpu_subtype_t) 1)
-
-/*
- * Machine threadtypes.
- * This is none - not defined - for most machine types/subtypes.
- */
-#define CPU_THREADTYPE_NONE ((cpu_threadtype_t) 0)
-
-/*
- * VAX subtypes (these do *not* necessary conform to the actual cpu
- * ID assigned by DEC available via the SID register).
- */
-
-#define CPU_SUBTYPE_VAX_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_VAX780 ((cpu_subtype_t) 1)
-#define CPU_SUBTYPE_VAX785 ((cpu_subtype_t) 2)
-#define CPU_SUBTYPE_VAX750 ((cpu_subtype_t) 3)
-#define CPU_SUBTYPE_VAX730 ((cpu_subtype_t) 4)
-#define CPU_SUBTYPE_UVAXI ((cpu_subtype_t) 5)
-#define CPU_SUBTYPE_UVAXII ((cpu_subtype_t) 6)
-#define CPU_SUBTYPE_VAX8200 ((cpu_subtype_t) 7)
-#define CPU_SUBTYPE_VAX8500 ((cpu_subtype_t) 8)
-#define CPU_SUBTYPE_VAX8600 ((cpu_subtype_t) 9)
-#define CPU_SUBTYPE_VAX8650 ((cpu_subtype_t) 10)
-#define CPU_SUBTYPE_VAX8800 ((cpu_subtype_t) 11)
-#define CPU_SUBTYPE_UVAXIII ((cpu_subtype_t) 12)
-
-/*
- * 680x0 subtypes
- *
- * The subtype definitions here are unusual for historical reasons.
- * NeXT used to consider 68030 code as generic 68000 code. For
- * backwards compatability:
- *
- * CPU_SUBTYPE_MC68030 symbol has been preserved for source code
- * compatability.
- *
- * CPU_SUBTYPE_MC680x0_ALL has been defined to be the same
- * subtype as CPU_SUBTYPE_MC68030 for binary comatability.
- *
- * CPU_SUBTYPE_MC68030_ONLY has been added to allow new object
- * files to be tagged as containing 68030-specific instructions.
- */
-
-#define CPU_SUBTYPE_MC680x0_ALL ((cpu_subtype_t) 1)
-#define CPU_SUBTYPE_MC68030 ((cpu_subtype_t) 1) /* compat */
-#define CPU_SUBTYPE_MC68040 ((cpu_subtype_t) 2)
-#define CPU_SUBTYPE_MC68030_ONLY ((cpu_subtype_t) 3)
-
-/*
- * I386 subtypes
- */
-
-#define CPU_SUBTYPE_INTEL(f, m) ((cpu_subtype_t) (f) + ((m) << 4))
-
-#define CPU_SUBTYPE_I386_ALL CPU_SUBTYPE_INTEL(3, 0)
-#define CPU_SUBTYPE_386 CPU_SUBTYPE_INTEL(3, 0)
-#define CPU_SUBTYPE_486 CPU_SUBTYPE_INTEL(4, 0)
-#define CPU_SUBTYPE_486SX CPU_SUBTYPE_INTEL(4, 8) // 8 << 4 = 128
-#define CPU_SUBTYPE_586 CPU_SUBTYPE_INTEL(5, 0)
-#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0)
-#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1)
-#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3)
-#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5)
-#define CPU_SUBTYPE_CELERON CPU_SUBTYPE_INTEL(7, 6)
-#define CPU_SUBTYPE_CELERON_MOBILE CPU_SUBTYPE_INTEL(7, 7)
-#define CPU_SUBTYPE_PENTIUM_3 CPU_SUBTYPE_INTEL(8, 0)
-#define CPU_SUBTYPE_PENTIUM_3_M CPU_SUBTYPE_INTEL(8, 1)
-#define CPU_SUBTYPE_PENTIUM_3_XEON CPU_SUBTYPE_INTEL(8, 2)
-#define CPU_SUBTYPE_PENTIUM_M CPU_SUBTYPE_INTEL(9, 0)
-#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0)
-#define CPU_SUBTYPE_PENTIUM_4_M CPU_SUBTYPE_INTEL(10, 1)
-#define CPU_SUBTYPE_ITANIUM CPU_SUBTYPE_INTEL(11, 0)
-#define CPU_SUBTYPE_ITANIUM_2 CPU_SUBTYPE_INTEL(11, 1)
-#define CPU_SUBTYPE_XEON CPU_SUBTYPE_INTEL(12, 0)
-#define CPU_SUBTYPE_XEON_MP CPU_SUBTYPE_INTEL(12, 1)
-
-#define CPU_SUBTYPE_INTEL_FAMILY(x) ((x) & 15)
-#define CPU_SUBTYPE_INTEL_FAMILY_MAX 15
-
-#define CPU_SUBTYPE_INTEL_MODEL(x) ((x) >> 4)
-#define CPU_SUBTYPE_INTEL_MODEL_ALL 0
-
-/*
- * X86 subtypes.
- */
-
-#define CPU_SUBTYPE_X86_ALL ((cpu_subtype_t)3)
-#define CPU_SUBTYPE_X86_64_ALL ((cpu_subtype_t)3)
-#define CPU_SUBTYPE_X86_ARCH1 ((cpu_subtype_t)4)
-#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell feature subset */
-
-
-#define CPU_THREADTYPE_INTEL_HTT ((cpu_threadtype_t) 1)
-
-/*
- * Mips subtypes.
- */
-
-#define CPU_SUBTYPE_MIPS_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_MIPS_R2300 ((cpu_subtype_t) 1)
-#define CPU_SUBTYPE_MIPS_R2600 ((cpu_subtype_t) 2)
-#define CPU_SUBTYPE_MIPS_R2800 ((cpu_subtype_t) 3)
-#define CPU_SUBTYPE_MIPS_R2000a ((cpu_subtype_t) 4) /* pmax */
-#define CPU_SUBTYPE_MIPS_R2000 ((cpu_subtype_t) 5)
-#define CPU_SUBTYPE_MIPS_R3000a ((cpu_subtype_t) 6) /* 3max */
-#define CPU_SUBTYPE_MIPS_R3000 ((cpu_subtype_t) 7)
-
-/*
- * MC98000 (PowerPC) subtypes
- */
-#define CPU_SUBTYPE_MC98000_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_MC98601 ((cpu_subtype_t) 1)
-
-/*
- * HPPA subtypes for Hewlett-Packard HP-PA family of
- * risc processors. Port by NeXT to 700 series.
- */
-
-#define CPU_SUBTYPE_HPPA_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_HPPA_7100 ((cpu_subtype_t) 0) /* compat */
-#define CPU_SUBTYPE_HPPA_7100LC ((cpu_subtype_t) 1)
-
-/*
- * MC88000 subtypes.
- */
-#define CPU_SUBTYPE_MC88000_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_MC88100 ((cpu_subtype_t) 1)
-#define CPU_SUBTYPE_MC88110 ((cpu_subtype_t) 2)
-
-/*
- * SPARC subtypes
- */
-#define CPU_SUBTYPE_SPARC_ALL ((cpu_subtype_t) 0)
-
-/*
- * I860 subtypes
- */
-#define CPU_SUBTYPE_I860_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_I860_860 ((cpu_subtype_t) 1)
-
-/*
- * PowerPC subtypes
- */
-#define CPU_SUBTYPE_POWERPC_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_POWERPC_601 ((cpu_subtype_t) 1)
-#define CPU_SUBTYPE_POWERPC_602 ((cpu_subtype_t) 2)
-#define CPU_SUBTYPE_POWERPC_603 ((cpu_subtype_t) 3)
-#define CPU_SUBTYPE_POWERPC_603e ((cpu_subtype_t) 4)
-#define CPU_SUBTYPE_POWERPC_603ev ((cpu_subtype_t) 5)
-#define CPU_SUBTYPE_POWERPC_604 ((cpu_subtype_t) 6)
-#define CPU_SUBTYPE_POWERPC_604e ((cpu_subtype_t) 7)
-#define CPU_SUBTYPE_POWERPC_620 ((cpu_subtype_t) 8)
-#define CPU_SUBTYPE_POWERPC_750 ((cpu_subtype_t) 9)
-#define CPU_SUBTYPE_POWERPC_7400 ((cpu_subtype_t) 10)
-#define CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t) 11)
-#define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100)
-
-/*
- * ARM subtypes
- */
-#define CPU_SUBTYPE_ARM_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_ARM_V4T ((cpu_subtype_t) 5)
-#define CPU_SUBTYPE_ARM_V6 ((cpu_subtype_t) 6)
-#define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7)
-#define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8)
-#define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9) /* ARMv7-A and ARMv7-R */
-#define CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) /* Cortex A9 */
-#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) /* Swift */
-#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12)
-#define CPU_SUBTYPE_ARM_V8 ((cpu_subtype_t) 13)
-#define CPU_SUBTYPE_ARM_V6M ((cpu_subtype_t) 14) /* Not meant to be run under xnu */
-#define CPU_SUBTYPE_ARM_V7M ((cpu_subtype_t) 15) /* Not meant to be run under xnu */
-#define CPU_SUBTYPE_ARM_V7EM ((cpu_subtype_t) 16) /* Not meant to be run under xnu */
-#define CPU_SUBTYPE_ARM_V8M ((cpu_subtype_t) 17) /* Not meant to be run under xnu */
-
-/*
- * ARM64 subtypes
- */
-#define CPU_SUBTYPE_ARM64_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_ARM64_V8 ((cpu_subtype_t) 1)
-#define CPU_SUBTYPE_ARM64E ((cpu_subtype_t) 2)
-
-/* CPU subtype feature flags for ptrauth on arm64e platforms */
-#define CPU_SUBTYPE_ARM64_PTR_AUTH_MASK 0x0f000000
-#define CPU_SUBTYPE_ARM64_PTR_AUTH_VERSION(x) (((x) & CPU_SUBTYPE_ARM64_PTR_AUTH_MASK) >> 24)
-
-/*
- * ARM64_32 subtypes
- */
-#define CPU_SUBTYPE_ARM64_32_ALL ((cpu_subtype_t) 0)
-#define CPU_SUBTYPE_ARM64_32_V8 ((cpu_subtype_t) 1)
-
-#endif /* !__ASSEMBLER__ */
-
-/*
- * CPU families (sysctl hw.cpufamily)
- *
- * These are meant to identify the CPU's marketing name - an
- * application can map these to (possibly) localized strings.
- * NB: the encodings of the CPU families are intentionally arbitrary.
- * There is no ordering, and you should never try to deduce whether
- * or not some feature is available based on the family.
- * Use feature flags (eg, hw.optional.altivec) to test for optional
- * functionality.
- */
-#define CPUFAMILY_UNKNOWN 0
-#define CPUFAMILY_POWERPC_G3 0xcee41549
-#define CPUFAMILY_POWERPC_G4 0x77c184ae
-#define CPUFAMILY_POWERPC_G5 0xed76d8aa
-#define CPUFAMILY_INTEL_6_13 0xaa33392b
-#define CPUFAMILY_INTEL_PENRYN 0x78ea4fbc
-#define CPUFAMILY_INTEL_NEHALEM 0x6b5a4cd2
-#define CPUFAMILY_INTEL_WESTMERE 0x573b5eec
-#define CPUFAMILY_INTEL_SANDYBRIDGE 0x5490b78c
-#define CPUFAMILY_INTEL_IVYBRIDGE 0x1f65e835
-#define CPUFAMILY_INTEL_HASWELL 0x10b282dc
-#define CPUFAMILY_INTEL_BROADWELL 0x582ed09c
-#define CPUFAMILY_INTEL_SKYLAKE 0x37fc219f
-#define CPUFAMILY_INTEL_KABYLAKE 0x0f817246
-#if !defined(RC_HIDE_XNU_ICELAKE)
-#define CPUFAMILY_INTEL_ICELAKE 0x38435547
-#endif /* not RC_HIDE_XNU_ICELAKE */
-#if !defined(RC_HIDE_XNU_COMETLAKE)
-#define CPUFAMILY_INTEL_COMETLAKE 0x1cf8a03e
-#endif /* not RC_HIDE_XNU_COMETLAKE */
-#define CPUFAMILY_ARM_9 0xe73283ae
-#define CPUFAMILY_ARM_11 0x8ff620d8
-#define CPUFAMILY_ARM_XSCALE 0x53b005f5
-#define CPUFAMILY_ARM_12 0xbd1b0ae9
-#define CPUFAMILY_ARM_13 0x0cc90e64
-#define CPUFAMILY_ARM_14 0x96077ef1
-#define CPUFAMILY_ARM_15 0xa8511bca
-#define CPUFAMILY_ARM_SWIFT 0x1e2d6381
-#define CPUFAMILY_ARM_CYCLONE 0x37a09642
-#define CPUFAMILY_ARM_TYPHOON 0x2c91a47e
-#define CPUFAMILY_ARM_TWISTER 0x92fb37c8
-#define CPUFAMILY_ARM_HURRICANE 0x67ceee93
-#define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6
-#define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f
-#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2
-
-/* The following synonyms are deprecated: */
-#define CPUFAMILY_INTEL_6_23 CPUFAMILY_INTEL_PENRYN
-#define CPUFAMILY_INTEL_6_26 CPUFAMILY_INTEL_NEHALEM
-
-
-#endif /* _MACH_MACHINE_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/_structs.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/_structs.h
deleted file mode 100644
index 0a61125417..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/_structs.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2017 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE__STRUCTS_H_
-#define _MACH_MACHINE__STRUCTS_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/_structs.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE__STRUCTS_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/boolean.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/boolean.h
deleted file mode 100644
index d373913b40..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/boolean.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE_BOOLEAN_H_
-#define _MACH_MACHINE_BOOLEAN_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/boolean.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE_BOOLEAN_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/exception.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/exception.h
deleted file mode 100644
index f3e960d436..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/exception.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE_EXCEPTION_H_
-#define _MACH_MACHINE_EXCEPTION_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/exception.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE_EXCEPTION_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/kern_return.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/kern_return.h
deleted file mode 100644
index b764492d29..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/kern_return.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE_KERN_RETURN_H_
-#define _MACH_MACHINE_KERN_RETURN_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/kern_return.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE_KERN_RETURN_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/processor_info.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/processor_info.h
deleted file mode 100644
index 4e5028d24d..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/processor_info.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE_PROCESSOR_INFO_H_
-#define _MACH_MACHINE_PROCESSOR_INFO_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/processor_info.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE_PROCESSOR_INFO_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/rpc.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/rpc.h
deleted file mode 100644
index 7d6ccee5f8..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/rpc.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE_RPC_H_
-#define _MACH_MACHINE_RPC_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/rpc.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE_RPC_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/thread_state.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/thread_state.h
deleted file mode 100644
index 91daad8671..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/thread_state.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE_THREAD_STATE_H_
-#define _MACH_MACHINE_THREAD_STATE_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/thread_state.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE_THREAD_STATE_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/thread_status.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/thread_status.h
deleted file mode 100644
index 7e65df246e..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/thread_status.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE_THREAD_STATUS_H_
-#define _MACH_MACHINE_THREAD_STATUS_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/thread_status.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE_THREAD_STATUS_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/vm_param.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/vm_param.h
deleted file mode 100644
index 7f272f5b70..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/vm_param.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE_VM_PARAM_H_
-#define _MACH_MACHINE_VM_PARAM_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/vm_param.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE_VM_PARAM_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/machine/vm_types.h b/lib/libc/include/x86_64-macos-gnu/mach/machine/vm_types.h
deleted file mode 100644
index 5d16a871ea..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/machine/vm_types.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _MACH_MACHINE_VM_TYPES_H_
-#define _MACH_MACHINE_VM_TYPES_H_
-
-#if defined (__i386__) || defined(__x86_64__)
-#include "mach/i386/vm_types.h"
-#else
-#error architecture not supported
-#endif
-
-#endif /* _MACH_MACHINE_VM_TYPES_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/memory_object_types.h b/lib/libc/include/x86_64-macos-gnu/mach/memory_object_types.h
deleted file mode 100644
index fec6e53593..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/memory_object_types.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2000-2016 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- */
-/*
- * File: memory_object.h
- * Author: Michael Wayne Young
- *
- * External memory management interface definition.
- */
-
-#ifndef _MACH_MEMORY_OBJECT_TYPES_H_
-#define _MACH_MEMORY_OBJECT_TYPES_H_
-
-/*
- * User-visible types used in the external memory
- * management interface:
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#define VM_64_BIT_DATA_OBJECTS
-
-typedef unsigned long long memory_object_offset_t;
-typedef unsigned long long memory_object_size_t;
-typedef natural_t memory_object_cluster_size_t;
-typedef natural_t * memory_object_fault_info_t;
-
-typedef unsigned long long vm_object_id_t;
-
-
-/*
- * Temporary until real EMMI version gets re-implemented
- */
-
-
-typedef mach_port_t memory_object_t;
-typedef mach_port_t memory_object_control_t;
-
-
-typedef memory_object_t *memory_object_array_t;
-/* A memory object ... */
-/* Used by the kernel to retrieve */
-/* or store data */
-
-typedef mach_port_t memory_object_name_t;
-/* Used to describe the memory ... */
-/* object in vm_regions() calls */
-
-typedef mach_port_t memory_object_default_t;
-/* Registered with the host ... */
-/* for creating new internal objects */
-
-#define MEMORY_OBJECT_NULL ((memory_object_t) 0)
-#define MEMORY_OBJECT_CONTROL_NULL ((memory_object_control_t) 0)
-#define MEMORY_OBJECT_NAME_NULL ((memory_object_name_t) 0)
-#define MEMORY_OBJECT_DEFAULT_NULL ((memory_object_default_t) 0)
-
-
-typedef int memory_object_copy_strategy_t;
-/* How memory manager handles copy: */
-#define MEMORY_OBJECT_COPY_NONE 0
-/* ... No special support */
-#define MEMORY_OBJECT_COPY_CALL 1
-/* ... Make call on memory manager */
-#define MEMORY_OBJECT_COPY_DELAY 2
-/* ... Memory manager doesn't
- * change data externally.
- */
-#define MEMORY_OBJECT_COPY_TEMPORARY 3
-/* ... Memory manager doesn't
- * change data externally, and
- * doesn't need to see changes.
- */
-#define MEMORY_OBJECT_COPY_SYMMETRIC 4
-/* ... Memory manager doesn't
- * change data externally,
- * doesn't need to see changes,
- * and object will not be
- * multiply mapped.
- *
- * XXX
- * Not yet safe for non-kernel use.
- */
-
-#define MEMORY_OBJECT_COPY_INVALID 5
-/* ... An invalid copy strategy,
- * for external objects which
- * have not been initialized.
- * Allows copy_strategy to be
- * examined without also
- * examining pager_ready and
- * internal.
- */
-
-typedef int memory_object_return_t;
-/* Which pages to return to manager
- * this time (lock_request) */
-#define MEMORY_OBJECT_RETURN_NONE 0
-/* ... don't return any. */
-#define MEMORY_OBJECT_RETURN_DIRTY 1
-/* ... only dirty pages. */
-#define MEMORY_OBJECT_RETURN_ALL 2
-/* ... dirty and precious pages. */
-#define MEMORY_OBJECT_RETURN_ANYTHING 3
-/* ... any resident page. */
-
-/*
- * Data lock request flags
- */
-
-#define MEMORY_OBJECT_DATA_FLUSH 0x1
-#define MEMORY_OBJECT_DATA_NO_CHANGE 0x2
-#define MEMORY_OBJECT_DATA_PURGE 0x4
-#define MEMORY_OBJECT_COPY_SYNC 0x8
-#define MEMORY_OBJECT_DATA_SYNC 0x10
-#define MEMORY_OBJECT_IO_SYNC 0x20
-#define MEMORY_OBJECT_DATA_FLUSH_ALL 0x40
-
-/*
- * Types for the memory object flavor interfaces
- */
-
-#define MEMORY_OBJECT_INFO_MAX (1024)
-typedef int *memory_object_info_t;
-typedef int memory_object_flavor_t;
-typedef int memory_object_info_data_t[MEMORY_OBJECT_INFO_MAX];
-
-
-#define MEMORY_OBJECT_PERFORMANCE_INFO 11
-#define MEMORY_OBJECT_ATTRIBUTE_INFO 14
-#define MEMORY_OBJECT_BEHAVIOR_INFO 15
-
-
-struct memory_object_perf_info {
- memory_object_cluster_size_t cluster_size;
- boolean_t may_cache;
-};
-
-struct memory_object_attr_info {
- memory_object_copy_strategy_t copy_strategy;
- memory_object_cluster_size_t cluster_size;
- boolean_t may_cache_object;
- boolean_t temporary;
-};
-
-struct memory_object_behave_info {
- memory_object_copy_strategy_t copy_strategy;
- boolean_t temporary;
- boolean_t invalidate;
- boolean_t silent_overwrite;
- boolean_t advisory_pageout;
-};
-
-
-typedef struct memory_object_behave_info *memory_object_behave_info_t;
-typedef struct memory_object_behave_info memory_object_behave_info_data_t;
-
-typedef struct memory_object_perf_info *memory_object_perf_info_t;
-typedef struct memory_object_perf_info memory_object_perf_info_data_t;
-
-typedef struct memory_object_attr_info *memory_object_attr_info_t;
-typedef struct memory_object_attr_info memory_object_attr_info_data_t;
-
-#define MEMORY_OBJECT_BEHAVE_INFO_COUNT ((mach_msg_type_number_t) \
- (sizeof(memory_object_behave_info_data_t)/sizeof(int)))
-#define MEMORY_OBJECT_PERF_INFO_COUNT ((mach_msg_type_number_t) \
- (sizeof(memory_object_perf_info_data_t)/sizeof(int)))
-#define MEMORY_OBJECT_ATTR_INFO_COUNT ((mach_msg_type_number_t) \
- (sizeof(memory_object_attr_info_data_t)/sizeof(int)))
-
-#define invalid_memory_object_flavor(f) \
- (f != MEMORY_OBJECT_ATTRIBUTE_INFO && \
- f != MEMORY_OBJECT_PERFORMANCE_INFO && \
- f != OLD_MEMORY_OBJECT_BEHAVIOR_INFO && \
- f != MEMORY_OBJECT_BEHAVIOR_INFO && \
- f != OLD_MEMORY_OBJECT_ATTRIBUTE_INFO)
-
-
-/*
- * Used to support options on memory_object_release_name call
- */
-#define MEMORY_OBJECT_TERMINATE_IDLE 0x1
-#define MEMORY_OBJECT_RESPECT_CACHE 0x2
-#define MEMORY_OBJECT_RELEASE_NO_OP 0x4
-
-
-/* named entry processor mapping options */
-/* enumerated */
-#define MAP_MEM_NOOP 0
-#define MAP_MEM_COPYBACK 1
-#define MAP_MEM_IO 2
-#define MAP_MEM_WTHRU 3
-#define MAP_MEM_WCOMB 4 /* Write combining mode */
- /* aka store gather */
-#define MAP_MEM_INNERWBACK 5
-#define MAP_MEM_POSTED 6
-#define MAP_MEM_RT 7
-#define MAP_MEM_POSTED_REORDERED 8
-#define MAP_MEM_POSTED_COMBINED_REORDERED 9
-
-#define GET_MAP_MEM(flags) \
- ((((unsigned int)(flags)) >> 24) & 0xFF)
-
-#define SET_MAP_MEM(caching, flags) \
- ((flags) = ((((unsigned int)(caching)) << 24) \
- & 0xFF000000) | ((flags) & 0xFFFFFF));
-
-/* leave room for vm_prot bits (0xFF ?) */
-#define MAP_MEM_LEDGER_TAGGED 0x002000 /* object owned by a specific task and ledger */
-#define MAP_MEM_PURGABLE_KERNEL_ONLY 0x004000 /* volatility controlled by kernel */
-#define MAP_MEM_GRAB_SECLUDED 0x008000 /* can grab secluded pages */
-#define MAP_MEM_ONLY 0x010000 /* change processor caching */
-#define MAP_MEM_NAMED_CREATE 0x020000 /* create extant object */
-#define MAP_MEM_PURGABLE 0x040000 /* create a purgable VM object */
-#define MAP_MEM_NAMED_REUSE 0x080000 /* reuse provided entry if identical */
-#define MAP_MEM_USE_DATA_ADDR 0x100000 /* preserve address of data, rather than base of page */
-#define MAP_MEM_VM_COPY 0x200000 /* make a copy of a VM range */
-#define MAP_MEM_VM_SHARE 0x400000 /* extract a VM range for remap */
-#define MAP_MEM_4K_DATA_ADDR 0x800000 /* preserve 4K aligned address of data */
-
-#define MAP_MEM_FLAGS_MASK 0x00FFFF00
-#define MAP_MEM_FLAGS_USER ( \
- MAP_MEM_PURGABLE_KERNEL_ONLY | \
- MAP_MEM_GRAB_SECLUDED | \
- MAP_MEM_ONLY | \
- MAP_MEM_NAMED_CREATE | \
- MAP_MEM_PURGABLE | \
- MAP_MEM_NAMED_REUSE | \
- MAP_MEM_USE_DATA_ADDR | \
- MAP_MEM_VM_COPY | \
- MAP_MEM_VM_SHARE | \
- MAP_MEM_LEDGER_TAGGED | \
- MAP_MEM_4K_DATA_ADDR)
-#define MAP_MEM_FLAGS_ALL ( \
- MAP_MEM_FLAGS_USER)
-
-
-#endif /* _MACH_MEMORY_OBJECT_TYPES_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/message.h b/lib/libc/include/x86_64-macos-gnu/mach/message.h
deleted file mode 100644
index 3f9f9a0605..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/message.h
+++ /dev/null
@@ -1,902 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- * NOTICE: This file was modified by McAfee Research in 2004 to introduce
- * support for mandatory and extensible security protections. This notice
- * is included in support of clause 2.2 (b) of the Apple Public License,
- * Version 2.0.
- * Copyright (c) 2005 SPARTA, Inc.
- */
-/*
- */
-/*
- * File: mach/message.h
- *
- * Mach IPC message and primitive function definitions.
- */
-
-#ifndef _MACH_MESSAGE_H_
-#define _MACH_MESSAGE_H_
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-/*
- * The timeout mechanism uses mach_msg_timeout_t values,
- * passed by value. The timeout units are milliseconds.
- * It is controlled with the MACH_SEND_TIMEOUT
- * and MACH_RCV_TIMEOUT options.
- */
-
-typedef natural_t mach_msg_timeout_t;
-
-/*
- * The value to be used when there is no timeout.
- * (No MACH_SEND_TIMEOUT/MACH_RCV_TIMEOUT option.)
- */
-
-#define MACH_MSG_TIMEOUT_NONE ((mach_msg_timeout_t) 0)
-
-/*
- * The kernel uses MACH_MSGH_BITS_COMPLEX as a hint. If it isn't on, it
- * assumes the body of the message doesn't contain port rights or OOL
- * data. The field is set in received messages. A user task must
- * use caution in interpreting the body of a message if the bit isn't
- * on, because the mach_msg_type's in the body might "lie" about the
- * contents. If the bit isn't on, but the mach_msg_types
- * in the body specify rights or OOL data, the behavior is undefined.
- * (Ie, an error may or may not be produced.)
- *
- * The value of MACH_MSGH_BITS_REMOTE determines the interpretation
- * of the msgh_remote_port field. It is handled like a msgt_name,
- * but must result in a send or send-once type right.
- *
- * The value of MACH_MSGH_BITS_LOCAL determines the interpretation
- * of the msgh_local_port field. It is handled like a msgt_name,
- * and also must result in a send or send-once type right.
- *
- * The value of MACH_MSGH_BITS_VOUCHER determines the interpretation
- * of the msgh_voucher_port field. It is handled like a msgt_name,
- * but must result in a send right (and the msgh_voucher_port field
- * must be the name of a send right to a Mach voucher kernel object.
- *
- * MACH_MSGH_BITS() combines two MACH_MSG_TYPE_* values, for the remote
- * and local fields, into a single value suitable for msgh_bits.
- *
- * MACH_MSGH_BITS_CIRCULAR should be zero; is is used internally.
- *
- * The unused bits should be zero and are reserved for the kernel
- * or for future interface expansion.
- */
-
-#define MACH_MSGH_BITS_ZERO 0x00000000
-
-#define MACH_MSGH_BITS_REMOTE_MASK 0x0000001f
-#define MACH_MSGH_BITS_LOCAL_MASK 0x00001f00
-#define MACH_MSGH_BITS_VOUCHER_MASK 0x001f0000
-
-#define MACH_MSGH_BITS_PORTS_MASK \
- (MACH_MSGH_BITS_REMOTE_MASK | \
- MACH_MSGH_BITS_LOCAL_MASK | \
- MACH_MSGH_BITS_VOUCHER_MASK)
-
-#define MACH_MSGH_BITS_COMPLEX 0x80000000U /* message is complex */
-
-#define MACH_MSGH_BITS_USER 0x801f1f1fU /* allowed bits user->kernel */
-
-#define MACH_MSGH_BITS_RAISEIMP 0x20000000U /* importance raised due to msg */
-#define MACH_MSGH_BITS_DENAP MACH_MSGH_BITS_RAISEIMP
-
-#define MACH_MSGH_BITS_IMPHOLDASRT 0x10000000U /* assertion help, userland private */
-#define MACH_MSGH_BITS_DENAPHOLDASRT MACH_MSGH_BITS_IMPHOLDASRT
-
-#define MACH_MSGH_BITS_CIRCULAR 0x10000000U /* message circular, kernel private */
-
-#define MACH_MSGH_BITS_USED 0xb01f1f1fU
-
-/* setter macros for the bits */
-#define MACH_MSGH_BITS(remote, local) /* legacy */ \
- ((remote) | ((local) << 8))
-#define MACH_MSGH_BITS_SET_PORTS(remote, local, voucher) \
- (((remote) & MACH_MSGH_BITS_REMOTE_MASK) | \
- (((local) << 8) & MACH_MSGH_BITS_LOCAL_MASK) | \
- (((voucher) << 16) & MACH_MSGH_BITS_VOUCHER_MASK))
-#define MACH_MSGH_BITS_SET(remote, local, voucher, other) \
- (MACH_MSGH_BITS_SET_PORTS((remote), (local), (voucher)) \
- | ((other) &~ MACH_MSGH_BITS_PORTS_MASK))
-
-/* getter macros for pulling values out of the bits field */
-#define MACH_MSGH_BITS_REMOTE(bits) \
- ((bits) & MACH_MSGH_BITS_REMOTE_MASK)
-#define MACH_MSGH_BITS_LOCAL(bits) \
- (((bits) & MACH_MSGH_BITS_LOCAL_MASK) >> 8)
-#define MACH_MSGH_BITS_VOUCHER(bits) \
- (((bits) & MACH_MSGH_BITS_VOUCHER_MASK) >> 16)
-#define MACH_MSGH_BITS_PORTS(bits) \
- ((bits) & MACH_MSGH_BITS_PORTS_MASK)
-#define MACH_MSGH_BITS_OTHER(bits) \
- ((bits) &~ MACH_MSGH_BITS_PORTS_MASK)
-
-/* checking macros */
-#define MACH_MSGH_BITS_HAS_REMOTE(bits) \
- (MACH_MSGH_BITS_REMOTE(bits) != MACH_MSGH_BITS_ZERO)
-#define MACH_MSGH_BITS_HAS_LOCAL(bits) \
- (MACH_MSGH_BITS_LOCAL(bits) != MACH_MSGH_BITS_ZERO)
-#define MACH_MSGH_BITS_HAS_VOUCHER(bits) \
- (MACH_MSGH_BITS_VOUCHER(bits) != MACH_MSGH_BITS_ZERO)
-#define MACH_MSGH_BITS_IS_COMPLEX(bits) \
- (((bits) & MACH_MSGH_BITS_COMPLEX) != MACH_MSGH_BITS_ZERO)
-
-/* importance checking macros */
-#define MACH_MSGH_BITS_RAISED_IMPORTANCE(bits) \
- (((bits) & MACH_MSGH_BITS_RAISEIMP) != MACH_MSGH_BITS_ZERO)
-#define MACH_MSGH_BITS_HOLDS_IMPORTANCE_ASSERTION(bits) \
- (((bits) & MACH_MSGH_BITS_IMPHOLDASRT) != MACH_MSGH_BITS_ZERO)
-
-/*
- * Every message starts with a message header.
- * Following the message header, if the message is complex, are a count
- * of type descriptors and the type descriptors themselves
- * (mach_msg_descriptor_t). The size of the message must be specified in
- * bytes, and includes the message header, descriptor count, descriptors,
- * and inline data.
- *
- * The msgh_remote_port field specifies the destination of the message.
- * It must specify a valid send or send-once right for a port.
- *
- * The msgh_local_port field specifies a "reply port". Normally,
- * This field carries a send-once right that the receiver will use
- * to reply to the message. It may carry the values MACH_PORT_NULL,
- * MACH_PORT_DEAD, a send-once right, or a send right.
- *
- * The msgh_voucher_port field specifies a Mach voucher port. Only
- * send rights to kernel-implemented Mach Voucher kernel objects in
- * addition to MACH_PORT_NULL or MACH_PORT_DEAD may be passed.
- *
- * The msgh_id field is uninterpreted by the message primitives.
- * It normally carries information specifying the format
- * or meaning of the message.
- */
-
-typedef unsigned int mach_msg_bits_t;
-typedef natural_t mach_msg_size_t;
-typedef integer_t mach_msg_id_t;
-
-#define MACH_MSG_SIZE_NULL (mach_msg_size_t *) 0
-
-typedef unsigned int mach_msg_priority_t;
-
-#define MACH_MSG_PRIORITY_UNSPECIFIED (mach_msg_priority_t) 0
-
-typedef unsigned int mach_msg_type_name_t;
-
-#define MACH_MSG_TYPE_MOVE_RECEIVE 16 /* Must hold receive right */
-#define MACH_MSG_TYPE_MOVE_SEND 17 /* Must hold send right(s) */
-#define MACH_MSG_TYPE_MOVE_SEND_ONCE 18 /* Must hold sendonce right */
-#define MACH_MSG_TYPE_COPY_SEND 19 /* Must hold send right(s) */
-#define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */
-#define MACH_MSG_TYPE_MAKE_SEND_ONCE 21 /* Must hold receive right */
-#define MACH_MSG_TYPE_COPY_RECEIVE 22 /* NOT VALID */
-#define MACH_MSG_TYPE_DISPOSE_RECEIVE 24 /* must hold receive right */
-#define MACH_MSG_TYPE_DISPOSE_SEND 25 /* must hold send right(s) */
-#define MACH_MSG_TYPE_DISPOSE_SEND_ONCE 26 /* must hold sendonce right */
-
-typedef unsigned int mach_msg_copy_options_t;
-
-#define MACH_MSG_PHYSICAL_COPY 0
-#define MACH_MSG_VIRTUAL_COPY 1
-#define MACH_MSG_ALLOCATE 2
-#define MACH_MSG_OVERWRITE 3 /* deprecated */
-#ifdef MACH_KERNEL
-#define MACH_MSG_KALLOC_COPY_T 4
-#endif /* MACH_KERNEL */
-
-#define MACH_MSG_GUARD_FLAGS_NONE 0x0000
-#define MACH_MSG_GUARD_FLAGS_IMMOVABLE_RECEIVE 0x0001 /* Move the receive right and mark it as immovable */
-#define MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND 0x0002 /* Verify that the port is unguarded */
-#define MACH_MSG_GUARD_FLAGS_MASK 0x0003 /* Valid flag bits */
-typedef unsigned int mach_msg_guard_flags_t;
-
-/*
- * In a complex mach message, the mach_msg_header_t is followed by
- * a descriptor count, then an array of that number of descriptors
- * (mach_msg_*_descriptor_t). The type field of mach_msg_type_descriptor_t
- * (which any descriptor can be cast to) indicates the flavor of the
- * descriptor.
- *
- * Note that in LP64, the various types of descriptors are no longer all
- * the same size as mach_msg_descriptor_t, so the array cannot be indexed
- * as expected.
- */
-
-typedef unsigned int mach_msg_descriptor_type_t;
-
-#define MACH_MSG_PORT_DESCRIPTOR 0
-#define MACH_MSG_OOL_DESCRIPTOR 1
-#define MACH_MSG_OOL_PORTS_DESCRIPTOR 2
-#define MACH_MSG_OOL_VOLATILE_DESCRIPTOR 3
-#define MACH_MSG_GUARDED_PORT_DESCRIPTOR 4
-
-#pragma pack(push, 4)
-
-typedef struct{
- natural_t pad1;
- mach_msg_size_t pad2;
- unsigned int pad3 : 24;
- mach_msg_descriptor_type_t type : 8;
-} mach_msg_type_descriptor_t;
-
-typedef struct{
- mach_port_t name;
-// Pad to 8 bytes everywhere except the K64 kernel where mach_port_t is 8 bytes
- mach_msg_size_t pad1;
- unsigned int pad2 : 16;
- mach_msg_type_name_t disposition : 8;
- mach_msg_descriptor_type_t type : 8;
-} mach_msg_port_descriptor_t;
-
-typedef struct{
- uint32_t address;
- mach_msg_size_t size;
- boolean_t deallocate: 8;
- mach_msg_copy_options_t copy: 8;
- unsigned int pad1: 8;
- mach_msg_descriptor_type_t type: 8;
-} mach_msg_ool_descriptor32_t;
-
-typedef struct{
- uint64_t address;
- boolean_t deallocate: 8;
- mach_msg_copy_options_t copy: 8;
- unsigned int pad1: 8;
- mach_msg_descriptor_type_t type: 8;
- mach_msg_size_t size;
-} mach_msg_ool_descriptor64_t;
-
-typedef struct{
- void* address;
-#if !defined(__LP64__)
- mach_msg_size_t size;
-#endif
- boolean_t deallocate: 8;
- mach_msg_copy_options_t copy: 8;
- unsigned int pad1: 8;
- mach_msg_descriptor_type_t type: 8;
-#if defined(__LP64__)
- mach_msg_size_t size;
-#endif
-} mach_msg_ool_descriptor_t;
-
-typedef struct{
- uint32_t address;
- mach_msg_size_t count;
- boolean_t deallocate: 8;
- mach_msg_copy_options_t copy: 8;
- mach_msg_type_name_t disposition : 8;
- mach_msg_descriptor_type_t type : 8;
-} mach_msg_ool_ports_descriptor32_t;
-
-typedef struct{
- uint64_t address;
- boolean_t deallocate: 8;
- mach_msg_copy_options_t copy: 8;
- mach_msg_type_name_t disposition : 8;
- mach_msg_descriptor_type_t type : 8;
- mach_msg_size_t count;
-} mach_msg_ool_ports_descriptor64_t;
-
-typedef struct{
- void* address;
-#if !defined(__LP64__)
- mach_msg_size_t count;
-#endif
- boolean_t deallocate: 8;
- mach_msg_copy_options_t copy: 8;
- mach_msg_type_name_t disposition : 8;
- mach_msg_descriptor_type_t type : 8;
-#if defined(__LP64__)
- mach_msg_size_t count;
-#endif
-} mach_msg_ool_ports_descriptor_t;
-
-typedef struct{
- uint32_t context;
- mach_port_name_t name;
- mach_msg_guard_flags_t flags : 16;
- mach_msg_type_name_t disposition : 8;
- mach_msg_descriptor_type_t type : 8;
-} mach_msg_guarded_port_descriptor32_t;
-
-typedef struct{
- uint64_t context;
- mach_msg_guard_flags_t flags : 16;
- mach_msg_type_name_t disposition : 8;
- mach_msg_descriptor_type_t type : 8;
- mach_port_name_t name;
-} mach_msg_guarded_port_descriptor64_t;
-
-typedef struct{
- mach_port_context_t context;
-#if !defined(__LP64__)
- mach_port_name_t name;
-#endif
- mach_msg_guard_flags_t flags : 16;
- mach_msg_type_name_t disposition : 8;
- mach_msg_descriptor_type_t type : 8;
-#if defined(__LP64__)
- mach_port_name_t name;
-#endif /* defined(__LP64__) */
-} mach_msg_guarded_port_descriptor_t;
-
-/*
- * LP64support - This union definition is not really
- * appropriate in LP64 mode because not all descriptors
- * are of the same size in that environment.
- */
-typedef union{
- mach_msg_port_descriptor_t port;
- mach_msg_ool_descriptor_t out_of_line;
- mach_msg_ool_ports_descriptor_t ool_ports;
- mach_msg_type_descriptor_t type;
- mach_msg_guarded_port_descriptor_t guarded_port;
-} mach_msg_descriptor_t;
-
-typedef struct{
- mach_msg_size_t msgh_descriptor_count;
-} mach_msg_body_t;
-
-#define MACH_MSG_BODY_NULL (mach_msg_body_t *) 0
-#define MACH_MSG_DESCRIPTOR_NULL (mach_msg_descriptor_t *) 0
-
-typedef struct{
- mach_msg_bits_t msgh_bits;
- mach_msg_size_t msgh_size;
- mach_port_t msgh_remote_port;
- mach_port_t msgh_local_port;
- mach_port_name_t msgh_voucher_port;
- mach_msg_id_t msgh_id;
-} mach_msg_header_t;
-
-#define msgh_reserved msgh_voucher_port
-#define MACH_MSG_NULL (mach_msg_header_t *) 0
-
-typedef struct{
- mach_msg_header_t header;
- mach_msg_body_t body;
-} mach_msg_base_t;
-
-typedef unsigned int mach_msg_trailer_type_t;
-
-#define MACH_MSG_TRAILER_FORMAT_0 0
-
-typedef unsigned int mach_msg_trailer_size_t;
-typedef char *mach_msg_trailer_info_t;
-
-typedef struct{
- mach_msg_trailer_type_t msgh_trailer_type;
- mach_msg_trailer_size_t msgh_trailer_size;
-} mach_msg_trailer_t;
-
-/*
- * The msgh_seqno field carries a sequence number
- * associated with the received-from port. A port's
- * sequence number is incremented every time a message
- * is received from it and included in the received
- * trailer to help put messages back in sequence if
- * multiple threads receive and/or process received
- * messages.
- */
-typedef struct{
- mach_msg_trailer_type_t msgh_trailer_type;
- mach_msg_trailer_size_t msgh_trailer_size;
- mach_port_seqno_t msgh_seqno;
-} mach_msg_seqno_trailer_t;
-
-typedef struct{
- unsigned int val[2];
-} security_token_t;
-
-typedef struct{
- mach_msg_trailer_type_t msgh_trailer_type;
- mach_msg_trailer_size_t msgh_trailer_size;
- mach_port_seqno_t msgh_seqno;
- security_token_t msgh_sender;
-} mach_msg_security_trailer_t;
-
-/*
- * The audit token is an opaque token which identifies
- * Mach tasks and senders of Mach messages as subjects
- * to the BSM audit system. Only the appropriate BSM
- * library routines should be used to interpret the
- * contents of the audit token as the representation
- * of the subject identity within the token may change
- * over time.
- */
-typedef struct{
- unsigned int val[8];
-} audit_token_t;
-
-typedef struct{
- mach_msg_trailer_type_t msgh_trailer_type;
- mach_msg_trailer_size_t msgh_trailer_size;
- mach_port_seqno_t msgh_seqno;
- security_token_t msgh_sender;
- audit_token_t msgh_audit;
-} mach_msg_audit_trailer_t;
-
-typedef struct{
- mach_msg_trailer_type_t msgh_trailer_type;
- mach_msg_trailer_size_t msgh_trailer_size;
- mach_port_seqno_t msgh_seqno;
- security_token_t msgh_sender;
- audit_token_t msgh_audit;
- mach_port_context_t msgh_context;
-} mach_msg_context_trailer_t;
-
-
-
-typedef struct{
- mach_port_name_t sender;
-} msg_labels_t;
-
-/*
- * Trailer type to pass MAC policy label info as a mach message trailer.
- *
- */
-
-typedef struct{
- mach_msg_trailer_type_t msgh_trailer_type;
- mach_msg_trailer_size_t msgh_trailer_size;
- mach_port_seqno_t msgh_seqno;
- security_token_t msgh_sender;
- audit_token_t msgh_audit;
- mach_port_context_t msgh_context;
- int msgh_ad;
- msg_labels_t msgh_labels;
-} mach_msg_mac_trailer_t;
-
-
-#define MACH_MSG_TRAILER_MINIMUM_SIZE sizeof(mach_msg_trailer_t)
-
-/*
- * These values can change from release to release - but clearly
- * code cannot request additional trailer elements one was not
- * compiled to understand. Therefore, it is safe to use this
- * constant when the same module specified the receive options.
- * Otherwise, you run the risk that the options requested by
- * another module may exceed the local modules notion of
- * MAX_TRAILER_SIZE.
- */
-
-typedef mach_msg_mac_trailer_t mach_msg_max_trailer_t;
-#define MAX_TRAILER_SIZE ((mach_msg_size_t)sizeof(mach_msg_max_trailer_t))
-
-/*
- * Legacy requirements keep us from ever updating these defines (even
- * when the format_0 trailers gain new option data fields in the future).
- * Therefore, they shouldn't be used going forward. Instead, the sizes
- * should be compared against the specific element size requested using
- * REQUESTED_TRAILER_SIZE.
- */
-typedef mach_msg_security_trailer_t mach_msg_format_0_trailer_t;
-
-/*typedef mach_msg_mac_trailer_t mach_msg_format_0_trailer_t;
- */
-
-#define MACH_MSG_TRAILER_FORMAT_0_SIZE sizeof(mach_msg_format_0_trailer_t)
-
-#define KERNEL_SECURITY_TOKEN_VALUE { {0, 1} }
-extern const security_token_t KERNEL_SECURITY_TOKEN;
-
-#define KERNEL_AUDIT_TOKEN_VALUE { {0, 0, 0, 0, 0, 0, 0, 0} }
-extern const audit_token_t KERNEL_AUDIT_TOKEN;
-
-typedef integer_t mach_msg_options_t;
-
-typedef struct{
- mach_msg_header_t header;
-} mach_msg_empty_send_t;
-
-typedef struct{
- mach_msg_header_t header;
- mach_msg_trailer_t trailer;
-} mach_msg_empty_rcv_t;
-
-typedef union{
- mach_msg_empty_send_t send;
- mach_msg_empty_rcv_t rcv;
-} mach_msg_empty_t;
-
-#pragma pack(pop)
-
-/* utility to round the message size - will become machine dependent */
-#define round_msg(x) (((mach_msg_size_t)(x) + sizeof (natural_t) - 1) & \
- ~(sizeof (natural_t) - 1))
-
-
-/*
- * There is no fixed upper bound to the size of Mach messages.
- */
-#define MACH_MSG_SIZE_MAX ((mach_msg_size_t) ~0)
-
-#if defined(__APPLE_API_PRIVATE)
-/*
- * But architectural limits of a given implementation, or
- * temporal conditions may cause unpredictable send failures
- * for messages larger than MACH_MSG_SIZE_RELIABLE.
- *
- * In either case, waiting for memory is [currently] outside
- * the scope of send timeout values provided to IPC.
- */
-#define MACH_MSG_SIZE_RELIABLE ((mach_msg_size_t) 256 * 1024)
-#endif
-/*
- * Compatibility definitions, for code written
- * when there was a msgh_kind instead of msgh_seqno.
- */
-#define MACH_MSGH_KIND_NORMAL 0x00000000
-#define MACH_MSGH_KIND_NOTIFICATION 0x00000001
-#define msgh_kind msgh_seqno
-#define mach_msg_kind_t mach_port_seqno_t
-
-typedef natural_t mach_msg_type_size_t;
-typedef natural_t mach_msg_type_number_t;
-
-/*
- * Values received/carried in messages. Tells the receiver what
- * sort of port right he now has.
- *
- * MACH_MSG_TYPE_PORT_NAME is used to transfer a port name
- * which should remain uninterpreted by the kernel. (Port rights
- * are not transferred, just the port name.)
- */
-
-#define MACH_MSG_TYPE_PORT_NONE 0
-
-#define MACH_MSG_TYPE_PORT_NAME 15
-#define MACH_MSG_TYPE_PORT_RECEIVE MACH_MSG_TYPE_MOVE_RECEIVE
-#define MACH_MSG_TYPE_PORT_SEND MACH_MSG_TYPE_MOVE_SEND
-#define MACH_MSG_TYPE_PORT_SEND_ONCE MACH_MSG_TYPE_MOVE_SEND_ONCE
-
-#define MACH_MSG_TYPE_LAST 22 /* Last assigned */
-
-/*
- * A dummy value. Mostly used to indicate that the actual value
- * will be filled in later, dynamically.
- */
-
-#define MACH_MSG_TYPE_POLYMORPHIC ((mach_msg_type_name_t) -1)
-
-/*
- * Is a given item a port type?
- */
-
-#define MACH_MSG_TYPE_PORT_ANY(x) \
- (((x) >= MACH_MSG_TYPE_MOVE_RECEIVE) && \
- ((x) <= MACH_MSG_TYPE_MAKE_SEND_ONCE))
-
-#define MACH_MSG_TYPE_PORT_ANY_SEND(x) \
- (((x) >= MACH_MSG_TYPE_MOVE_SEND) && \
- ((x) <= MACH_MSG_TYPE_MAKE_SEND_ONCE))
-
-#define MACH_MSG_TYPE_PORT_ANY_RIGHT(x) \
- (((x) >= MACH_MSG_TYPE_MOVE_RECEIVE) && \
- ((x) <= MACH_MSG_TYPE_MOVE_SEND_ONCE))
-
-typedef integer_t mach_msg_option_t;
-
-#define MACH_MSG_OPTION_NONE 0x00000000
-
-#define MACH_SEND_MSG 0x00000001
-#define MACH_RCV_MSG 0x00000002
-
-#define MACH_RCV_LARGE 0x00000004 /* report large message sizes */
-#define MACH_RCV_LARGE_IDENTITY 0x00000008 /* identify source of large messages */
-
-#define MACH_SEND_TIMEOUT 0x00000010 /* timeout value applies to send */
-#define MACH_SEND_OVERRIDE 0x00000020 /* priority override for send */
-#define MACH_SEND_INTERRUPT 0x00000040 /* don't restart interrupted sends */
-#define MACH_SEND_NOTIFY 0x00000080 /* arm send-possible notify */
-#define MACH_SEND_ALWAYS 0x00010000 /* ignore qlimits - kernel only */
-#define MACH_SEND_TRAILER 0x00020000 /* sender-provided trailer */
-#define MACH_SEND_NOIMPORTANCE 0x00040000 /* msg won't carry importance */
-#define MACH_SEND_NODENAP MACH_SEND_NOIMPORTANCE
-#define MACH_SEND_IMPORTANCE 0x00080000 /* msg carries importance - kernel only */
-#define MACH_SEND_SYNC_OVERRIDE 0x00100000 /* msg should do sync ipc override */
-#define MACH_SEND_PROPAGATE_QOS 0x00200000 /* IPC should propagate the caller's QoS */
-#define MACH_SEND_SYNC_USE_THRPRI MACH_SEND_PROPAGATE_QOS /* obsolete name */
-#define MACH_SEND_KERNEL 0x00400000 /* full send from kernel space - kernel only */
-#define MACH_SEND_SYNC_BOOTSTRAP_CHECKIN 0x00800000 /* special reply port should boost thread doing sync bootstrap checkin */
-
-#define MACH_RCV_TIMEOUT 0x00000100 /* timeout value applies to receive */
-#define MACH_RCV_NOTIFY 0x00000000 /* legacy name (value was: 0x00000200) */
-#define MACH_RCV_INTERRUPT 0x00000400 /* don't restart interrupted receive */
-#define MACH_RCV_VOUCHER 0x00000800 /* willing to receive voucher port */
-#define MACH_RCV_OVERWRITE 0x00000000 /* scatter receive (deprecated) */
-#define MACH_RCV_GUARDED_DESC 0x00001000 /* Can receive new guarded descriptor */
-#define MACH_RCV_SYNC_WAIT 0x00004000 /* sync waiter waiting for rcv */
-#define MACH_RCV_SYNC_PEEK 0x00008000 /* sync waiter waiting to peek */
-
-#define MACH_MSG_STRICT_REPLY 0x00000200 /* Enforce specific properties about the reply port, and
- * the context in which a thread replies to a message.
- * This flag must be passed on both the SEND and RCV */
-
-
-/*
- * NOTE: a 0x00------ RCV mask implies to ask for
- * a MACH_MSG_TRAILER_FORMAT_0 with 0 Elements,
- * which is equivalent to a mach_msg_trailer_t.
- *
- * XXXMAC: unlike the rest of the MACH_RCV_* flags, MACH_RCV_TRAILER_LABELS
- * needs its own private bit since we only calculate its fields when absolutely
- * required.
- */
-#define MACH_RCV_TRAILER_NULL 0
-#define MACH_RCV_TRAILER_SEQNO 1
-#define MACH_RCV_TRAILER_SENDER 2
-#define MACH_RCV_TRAILER_AUDIT 3
-#define MACH_RCV_TRAILER_CTX 4
-#define MACH_RCV_TRAILER_AV 7
-#define MACH_RCV_TRAILER_LABELS 8
-
-#define MACH_RCV_TRAILER_TYPE(x) (((x) & 0xf) << 28)
-#define MACH_RCV_TRAILER_ELEMENTS(x) (((x) & 0xf) << 24)
-#define MACH_RCV_TRAILER_MASK ((0xf << 24))
-
-#define GET_RCV_ELEMENTS(y) (((y) >> 24) & 0xf)
-
-
-/*
- * XXXMAC: note that in the case of MACH_RCV_TRAILER_LABELS,
- * we just fall through to mach_msg_max_trailer_t.
- * This is correct behavior since mach_msg_max_trailer_t is defined as
- * mac_msg_mac_trailer_t which is used for the LABELS trailer.
- * It also makes things work properly if MACH_RCV_TRAILER_LABELS is ORed
- * with one of the other options.
- */
-
-#define REQUESTED_TRAILER_SIZE_NATIVE(y) \
- ((mach_msg_trailer_size_t) \
- ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_NULL) ? \
- sizeof(mach_msg_trailer_t) : \
- ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_SEQNO) ? \
- sizeof(mach_msg_seqno_trailer_t) : \
- ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_SENDER) ? \
- sizeof(mach_msg_security_trailer_t) : \
- ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_AUDIT) ? \
- sizeof(mach_msg_audit_trailer_t) : \
- ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_CTX) ? \
- sizeof(mach_msg_context_trailer_t) : \
- ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_AV) ? \
- sizeof(mach_msg_mac_trailer_t) : \
- sizeof(mach_msg_max_trailer_t))))))))
-
-
-#define REQUESTED_TRAILER_SIZE(y) REQUESTED_TRAILER_SIZE_NATIVE(y)
-
-/*
- * Much code assumes that mach_msg_return_t == kern_return_t.
- * This definition is useful for descriptive purposes.
- *
- * See for the format of error codes.
- * IPC errors are system 4. Send errors are subsystem 0;
- * receive errors are subsystem 1. The code field is always non-zero.
- * The high bits of the code field communicate extra information
- * for some error codes. MACH_MSG_MASK masks off these special bits.
- */
-
-typedef kern_return_t mach_msg_return_t;
-
-#define MACH_MSG_SUCCESS 0x00000000
-
-
-#define MACH_MSG_MASK 0x00003e00
-/* All special error code bits defined below. */
-#define MACH_MSG_IPC_SPACE 0x00002000
-/* No room in IPC name space for another capability name. */
-#define MACH_MSG_VM_SPACE 0x00001000
-/* No room in VM address space for out-of-line memory. */
-#define MACH_MSG_IPC_KERNEL 0x00000800
-/* Kernel resource shortage handling an IPC capability. */
-#define MACH_MSG_VM_KERNEL 0x00000400
-/* Kernel resource shortage handling out-of-line memory. */
-
-#define MACH_SEND_IN_PROGRESS 0x10000001
-/* Thread is waiting to send. (Internal use only.) */
-#define MACH_SEND_INVALID_DATA 0x10000002
-/* Bogus in-line data. */
-#define MACH_SEND_INVALID_DEST 0x10000003
-/* Bogus destination port. */
-#define MACH_SEND_TIMED_OUT 0x10000004
-/* Message not sent before timeout expired. */
-#define MACH_SEND_INVALID_VOUCHER 0x10000005
-/* Bogus voucher port. */
-#define MACH_SEND_INTERRUPTED 0x10000007
-/* Software interrupt. */
-#define MACH_SEND_MSG_TOO_SMALL 0x10000008
-/* Data doesn't contain a complete message. */
-#define MACH_SEND_INVALID_REPLY 0x10000009
-/* Bogus reply port. */
-#define MACH_SEND_INVALID_RIGHT 0x1000000a
-/* Bogus port rights in the message body. */
-#define MACH_SEND_INVALID_NOTIFY 0x1000000b
-/* Bogus notify port argument. */
-#define MACH_SEND_INVALID_MEMORY 0x1000000c
-/* Invalid out-of-line memory pointer. */
-#define MACH_SEND_NO_BUFFER 0x1000000d
-/* No message buffer is available. */
-#define MACH_SEND_TOO_LARGE 0x1000000e
-/* Send is too large for port */
-#define MACH_SEND_INVALID_TYPE 0x1000000f
-/* Invalid msg-type specification. */
-#define MACH_SEND_INVALID_HEADER 0x10000010
-/* A field in the header had a bad value. */
-#define MACH_SEND_INVALID_TRAILER 0x10000011
-/* The trailer to be sent does not match kernel format. */
-#define MACH_SEND_INVALID_CONTEXT 0x10000012
-/* The sending thread context did not match the context on the dest port */
-#define MACH_SEND_INVALID_RT_OOL_SIZE 0x10000015
-/* compatibility: no longer a returned error */
-#define MACH_SEND_NO_GRANT_DEST 0x10000016
-/* The destination port doesn't accept ports in body */
-
-#define MACH_RCV_IN_PROGRESS 0x10004001
-/* Thread is waiting for receive. (Internal use only.) */
-#define MACH_RCV_INVALID_NAME 0x10004002
-/* Bogus name for receive port/port-set. */
-#define MACH_RCV_TIMED_OUT 0x10004003
-/* Didn't get a message within the timeout value. */
-#define MACH_RCV_TOO_LARGE 0x10004004
-/* Message buffer is not large enough for inline data. */
-#define MACH_RCV_INTERRUPTED 0x10004005
-/* Software interrupt. */
-#define MACH_RCV_PORT_CHANGED 0x10004006
-/* compatibility: no longer a returned error */
-#define MACH_RCV_INVALID_NOTIFY 0x10004007
-/* Bogus notify port argument. */
-#define MACH_RCV_INVALID_DATA 0x10004008
-/* Bogus message buffer for inline data. */
-#define MACH_RCV_PORT_DIED 0x10004009
-/* Port/set was sent away/died during receive. */
-#define MACH_RCV_IN_SET 0x1000400a
-/* compatibility: no longer a returned error */
-#define MACH_RCV_HEADER_ERROR 0x1000400b
-/* Error receiving message header. See special bits. */
-#define MACH_RCV_BODY_ERROR 0x1000400c
-/* Error receiving message body. See special bits. */
-#define MACH_RCV_INVALID_TYPE 0x1000400d
-/* Invalid msg-type specification in scatter list. */
-#define MACH_RCV_SCATTER_SMALL 0x1000400e
-/* Out-of-line overwrite region is not large enough */
-#define MACH_RCV_INVALID_TRAILER 0x1000400f
-/* trailer type or number of trailer elements not supported */
-#define MACH_RCV_IN_PROGRESS_TIMED 0x10004011
-/* Waiting for receive with timeout. (Internal use only.) */
-#define MACH_RCV_INVALID_REPLY 0x10004012
-/* invalid reply port used in a STRICT_REPLY message */
-
-
-
-__BEGIN_DECLS
-
-/*
- * Routine: mach_msg_overwrite
- * Purpose:
- * Send and/or receive a message. If the message operation
- * is interrupted, and the user did not request an indication
- * of that fact, then restart the appropriate parts of the
- * operation silently (trap version does not restart).
- *
- * Distinct send and receive buffers may be specified. If
- * no separate receive buffer is specified, the msg parameter
- * will be used for both send and receive operations.
- *
- * In addition to a distinct receive buffer, that buffer may
- * already contain scatter control information to direct the
- * receiving of the message.
- */
-__WATCHOS_PROHIBITED __TVOS_PROHIBITED
-extern mach_msg_return_t mach_msg_overwrite(
- mach_msg_header_t *msg,
- mach_msg_option_t option,
- mach_msg_size_t send_size,
- mach_msg_size_t rcv_size,
- mach_port_name_t rcv_name,
- mach_msg_timeout_t timeout,
- mach_port_name_t notify,
- mach_msg_header_t *rcv_msg,
- mach_msg_size_t rcv_limit);
-
-
-/*
- * Routine: mach_msg
- * Purpose:
- * Send and/or receive a message. If the message operation
- * is interrupted, and the user did not request an indication
- * of that fact, then restart the appropriate parts of the
- * operation silently (trap version does not restart).
- */
-__WATCHOS_PROHIBITED __TVOS_PROHIBITED
-extern mach_msg_return_t mach_msg(
- mach_msg_header_t *msg,
- mach_msg_option_t option,
- mach_msg_size_t send_size,
- mach_msg_size_t rcv_size,
- mach_port_name_t rcv_name,
- mach_msg_timeout_t timeout,
- mach_port_name_t notify);
-
-/*
- * Routine: mach_voucher_deallocate
- * Purpose:
- * Deallocate a mach voucher created or received in a message. Drops
- * one (send right) reference to the voucher.
- */
-__WATCHOS_PROHIBITED __TVOS_PROHIBITED
-extern kern_return_t mach_voucher_deallocate(
- mach_port_name_t voucher);
-
-
-__END_DECLS
-
-#endif /* _MACH_MESSAGE_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-macos-gnu/mach/port.h b/lib/libc/include/x86_64-macos-gnu/mach/port.h
deleted file mode 100644
index 3547576e80..0000000000
--- a/lib/libc/include/x86_64-macos-gnu/mach/port.h
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- * NOTICE: This file was modified by McAfee Research in 2004 to introduce
- * support for mandatory and extensible security protections. This notice
- * is included in support of clause 2.2 (b) of the Apple Public License,
- * Version 2.0.
- */
-/*
- */
-/*
- * File: mach/port.h
- *
- * Definition of a Mach port
- *
- * Mach ports are the endpoints to Mach-implemented communications
- * channels (usually uni-directional message queues, but other types
- * also exist).
- *
- * Unique collections of these endpoints are maintained for each
- * Mach task. Each Mach port in the task's collection is given a
- * [task-local] name to identify it - and the the various "rights"
- * held by the task for that specific endpoint.
- *
- * This header defines the types used to identify these Mach ports
- * and the various rights associated with them. For more info see:
- *
- * - manipulation of port rights in a given space
- * - message queue [and port right passing] mechanism
- *
- */
-
-#ifndef _MACH_PORT_H_
-#define _MACH_PORT_H_
-
-#include
-#include