mirror of
https://github.com/ziglang/zig.git
synced 2026-01-02 03:25:01 +00:00
stage2: implement anyframe, anyframe->T and fix assembly
* AstGen: implement `anyframe_literal` and `anyframe_type`.
* Introduce `makeSubBlock` to avoid redundant AstGen code for GenZir
scopes. Allows adding/removing a field without possibility of
accidentally introducing a bug of forgetting to set the new field.
* Add to GenZir `nosuspend_node` and `suspend_node` in preparation for
implementing `suspend` blocks and `nosuspend` blocks.
* AstGen: fix assembly to support clobbers, multiple outputs, and
outputs without `->` syntax.
- `asm` and `asm_volatile` move to `Extended` enum with `small` being
repurposed for a few things. This frees up 2 ZIR tags, 1 of which
is used in this commit and 1 is leftover.
* AstGen: fix `simple_types` incorrectly having multiple conflicting
values for "undefined" and "null".
- Also add "anyframe" to `simple_types`.
* Add `anyframe_type` to type.zig, value.zig and `Zir.Inst.Ref`.
- Also add i128 and u128 types to `Zir.Inst.Ref` and `simple_types`.
* Sema/Zir: Fix incorrect math causing the function body to be messed
up for Extended-encoded functions.
* Zir: support `i32` fields for "extra" payloads.
This commit is contained in:
parent
183ee0965f
commit
b40a8efb9a
422
src/AstGen.zig
422
src/AstGen.zig
@ -723,8 +723,12 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
|
||||
},
|
||||
.enum_literal => return simpleStrTok(gz, scope, rl, main_tokens[node], node, .enum_literal),
|
||||
.error_value => return simpleStrTok(gz, scope, rl, node_datas[node].rhs, node, .error_value),
|
||||
.anyframe_literal => return astgen.failNode(node, "async and related features are not yet supported", .{}),
|
||||
.anyframe_type => return astgen.failNode(node, "async and related features are not yet supported", .{}),
|
||||
.anyframe_literal => return rvalue(gz, scope, rl, .anyframe_type, node),
|
||||
.anyframe_type => {
|
||||
const return_type = try typeExpr(gz, scope, node_datas[node].rhs);
|
||||
const result = try gz.addUnNode(.anyframe_type, return_type, node);
|
||||
return rvalue(gz, scope, rl, result, node);
|
||||
},
|
||||
.@"catch" => {
|
||||
const catch_token = main_tokens[node];
|
||||
const payload_token: ?ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe)
|
||||
@ -1546,18 +1550,10 @@ fn labeledBlockExpr(
|
||||
const block_inst = try gz.addBlock(zir_tag, block_node);
|
||||
try gz.instructions.append(astgen.gpa, block_inst);
|
||||
|
||||
var block_scope: GenZir = .{
|
||||
.parent = parent_scope,
|
||||
.decl_node_index = gz.decl_node_index,
|
||||
.astgen = gz.astgen,
|
||||
.force_comptime = gz.force_comptime,
|
||||
.ref_start_index = gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
// TODO @as here is working around a stage1 miscompilation bug :(
|
||||
.label = @as(?GenZir.Label, GenZir.Label{
|
||||
.token = label_token,
|
||||
.block_inst = block_inst,
|
||||
}),
|
||||
var block_scope = gz.makeSubBlock(parent_scope);
|
||||
block_scope.label = GenZir.Label{
|
||||
.token = label_token,
|
||||
.block_inst = block_inst,
|
||||
};
|
||||
block_scope.setBreakResultLoc(rl);
|
||||
defer block_scope.instructions.deinit(astgen.gpa);
|
||||
@ -1695,10 +1691,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
|
||||
.array_type_sentinel,
|
||||
.elem_type,
|
||||
.indexable_ptr_len,
|
||||
.anyframe_type,
|
||||
.as,
|
||||
.as_node,
|
||||
.@"asm",
|
||||
.asm_volatile,
|
||||
.bit_and,
|
||||
.bitcast,
|
||||
.bitcast_result_ptr,
|
||||
@ -2095,13 +2090,7 @@ fn varDecl(
|
||||
|
||||
// Detect whether the initialization expression actually uses the
|
||||
// result location pointer.
|
||||
var init_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = gz.decl_node_index,
|
||||
.force_comptime = gz.force_comptime,
|
||||
.ref_start_index = gz.ref_start_index,
|
||||
.astgen = astgen,
|
||||
};
|
||||
var init_scope = gz.makeSubBlock(scope);
|
||||
defer init_scope.instructions.deinit(gpa);
|
||||
|
||||
var resolve_inferred_alloc: Zir.Inst.Ref = .none;
|
||||
@ -3778,14 +3767,7 @@ fn tryExpr(
|
||||
return astgen.failNode(node, "invalid 'try' outside function scope", .{});
|
||||
};
|
||||
|
||||
var block_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = parent_gz.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var block_scope = parent_gz.makeSubBlock(scope);
|
||||
block_scope.setBreakResultLoc(rl);
|
||||
defer block_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
@ -3811,28 +3793,14 @@ fn tryExpr(
|
||||
try parent_gz.instructions.append(astgen.gpa, block);
|
||||
try block_scope.setBlockBody(block);
|
||||
|
||||
var then_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = block_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var then_scope = parent_gz.makeSubBlock(scope);
|
||||
defer then_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
const err_code = try then_scope.addUnNode(err_ops[1], operand, node);
|
||||
try genDefers(&then_scope, &fn_block.base, scope, err_code);
|
||||
const then_result = try then_scope.addUnNode(.ret_node, err_code, node);
|
||||
|
||||
var else_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = block_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var else_scope = parent_gz.makeSubBlock(scope);
|
||||
defer else_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
block_scope.break_count += 1;
|
||||
@ -3878,14 +3846,7 @@ fn orelseCatchExpr(
|
||||
const astgen = parent_gz.astgen;
|
||||
const tree = &astgen.file.tree;
|
||||
|
||||
var block_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = parent_gz.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var block_scope = parent_gz.makeSubBlock(scope);
|
||||
block_scope.setBreakResultLoc(rl);
|
||||
defer block_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
@ -3906,14 +3867,7 @@ fn orelseCatchExpr(
|
||||
try parent_gz.instructions.append(astgen.gpa, block);
|
||||
try block_scope.setBlockBody(block);
|
||||
|
||||
var then_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = block_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var then_scope = parent_gz.makeSubBlock(scope);
|
||||
defer then_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
var err_val_scope: Scope.LocalVal = undefined;
|
||||
@ -3939,14 +3893,7 @@ fn orelseCatchExpr(
|
||||
// instructions into place until we know whether to keep store_to_block_ptr
|
||||
// instructions or not.
|
||||
|
||||
var else_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = block_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var else_scope = parent_gz.makeSubBlock(scope);
|
||||
defer else_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
// This could be a pointer or value depending on `unwrap_op`.
|
||||
@ -4140,13 +4087,7 @@ fn boolBinOp(
|
||||
const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs);
|
||||
const bool_br = try gz.addBoolBr(zir_tag, lhs);
|
||||
|
||||
var rhs_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = gz.decl_node_index,
|
||||
.astgen = gz.astgen,
|
||||
.force_comptime = gz.force_comptime,
|
||||
.ref_start_index = gz.ref_start_index,
|
||||
};
|
||||
var rhs_scope = gz.makeSubBlock(scope);
|
||||
defer rhs_scope.instructions.deinit(gz.astgen.gpa);
|
||||
const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);
|
||||
_ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);
|
||||
@ -4167,14 +4108,7 @@ fn ifExpr(
|
||||
const tree = &astgen.file.tree;
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
var block_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = parent_gz.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var block_scope = parent_gz.makeSubBlock(scope);
|
||||
block_scope.setBreakResultLoc(rl);
|
||||
defer block_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
@ -4218,14 +4152,7 @@ fn ifExpr(
|
||||
try parent_gz.instructions.append(astgen.gpa, block);
|
||||
try block_scope.setBlockBody(block);
|
||||
|
||||
var then_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = block_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var then_scope = parent_gz.makeSubBlock(scope);
|
||||
defer then_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
var payload_val_scope: Scope.LocalVal = undefined;
|
||||
@ -4273,14 +4200,7 @@ fn ifExpr(
|
||||
// instructions into place until we know whether to keep store_to_block_ptr
|
||||
// instructions or not.
|
||||
|
||||
var else_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = block_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var else_scope = parent_gz.makeSubBlock(scope);
|
||||
defer else_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
const else_node = if_full.ast.else_expr;
|
||||
@ -4424,25 +4344,11 @@ fn whileExpr(
|
||||
const loop_block = try parent_gz.addBlock(loop_tag, node);
|
||||
try parent_gz.instructions.append(astgen.gpa, loop_block);
|
||||
|
||||
var loop_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = parent_gz.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var loop_scope = parent_gz.makeSubBlock(scope);
|
||||
loop_scope.setBreakResultLoc(rl);
|
||||
defer loop_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
var continue_scope: GenZir = .{
|
||||
.parent = &loop_scope.base,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = loop_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var continue_scope = parent_gz.makeSubBlock(&loop_scope.base);
|
||||
defer continue_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
const payload_is_ref = if (while_full.payload_token) |payload_token|
|
||||
@ -4505,14 +4411,7 @@ fn whileExpr(
|
||||
});
|
||||
}
|
||||
|
||||
var then_scope: GenZir = .{
|
||||
.parent = &continue_scope.base,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = continue_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var then_scope = parent_gz.makeSubBlock(&continue_scope.base);
|
||||
defer then_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
var payload_val_scope: Scope.LocalVal = undefined;
|
||||
@ -4557,14 +4456,7 @@ fn whileExpr(
|
||||
loop_scope.break_count += 1;
|
||||
const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr);
|
||||
|
||||
var else_scope: GenZir = .{
|
||||
.parent = &continue_scope.base,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = continue_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var else_scope = parent_gz.makeSubBlock(&continue_scope.base);
|
||||
defer else_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
const else_node = while_full.ast.else_expr;
|
||||
@ -4659,25 +4551,11 @@ fn forExpr(
|
||||
const loop_block = try parent_gz.addBlock(loop_tag, node);
|
||||
try parent_gz.instructions.append(astgen.gpa, loop_block);
|
||||
|
||||
var loop_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = parent_gz.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var loop_scope = parent_gz.makeSubBlock(scope);
|
||||
loop_scope.setBreakResultLoc(rl);
|
||||
defer loop_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
var cond_scope: GenZir = .{
|
||||
.parent = &loop_scope.base,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = loop_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var cond_scope = parent_gz.makeSubBlock(&loop_scope.base);
|
||||
defer cond_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
// check condition i < array_expr.len
|
||||
@ -4714,14 +4592,7 @@ fn forExpr(
|
||||
});
|
||||
}
|
||||
|
||||
var then_scope: GenZir = .{
|
||||
.parent = &cond_scope.base,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = cond_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var then_scope = parent_gz.makeSubBlock(&cond_scope.base);
|
||||
defer then_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
var payload_val_scope: Scope.LocalVal = undefined;
|
||||
@ -4773,14 +4644,7 @@ fn forExpr(
|
||||
loop_scope.break_count += 1;
|
||||
const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr);
|
||||
|
||||
var else_scope: GenZir = .{
|
||||
.parent = &cond_scope.base,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = cond_scope.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
|
||||
defer else_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
const else_node = for_full.ast.else_expr;
|
||||
@ -5076,14 +4940,7 @@ fn switchExpr(
|
||||
var multi_cases_payload = ArrayListUnmanaged(u32){};
|
||||
defer multi_cases_payload.deinit(gpa);
|
||||
|
||||
var block_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = parent_gz.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var block_scope = parent_gz.makeSubBlock(scope);
|
||||
block_scope.setBreakResultLoc(rl);
|
||||
defer block_scope.instructions.deinit(gpa);
|
||||
|
||||
@ -5091,14 +4948,7 @@ fn switchExpr(
|
||||
const switch_block = try parent_gz.addBlock(undefined, switch_node);
|
||||
|
||||
// We re-use this same scope for all cases, including the special prong, if any.
|
||||
var case_scope: GenZir = .{
|
||||
.parent = &block_scope.base,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = parent_gz.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var case_scope = parent_gz.makeSubBlock(&block_scope.base);
|
||||
defer case_scope.instructions.deinit(gpa);
|
||||
|
||||
// Do the else/`_` first because it goes first in the payload.
|
||||
@ -5846,57 +5696,109 @@ fn asmExpr(
|
||||
const tree = &astgen.file.tree;
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const asm_source = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, full.ast.template);
|
||||
|
||||
// See https://github.com/ziglang/zig/issues/215 and related issues discussing
|
||||
// possible inline assembly improvements. Until this is settled, I am avoiding
|
||||
// potentially wasting time implementing status quo assembly that is not used by
|
||||
// any of the standard library.
|
||||
if (full.outputs.len > 1) {
|
||||
return astgen.failNode(node, "TODO more than 1 asm output", .{});
|
||||
// possible inline assembly improvements. Until then here is status quo AstGen
|
||||
// for assembly syntax. It's used by std lib crypto aesni.zig.
|
||||
|
||||
if (full.outputs.len > 32) {
|
||||
return astgen.failNode(full.outputs[32], "too many asm outputs", .{});
|
||||
}
|
||||
const output: struct {
|
||||
ty: Zir.Inst.Ref = .none,
|
||||
constraint: u32 = 0,
|
||||
} = if (full.outputs.len == 0) .{} else blk: {
|
||||
const output_node = full.outputs[0];
|
||||
const out_type_node = node_datas[output_node].lhs;
|
||||
if (out_type_node == 0) {
|
||||
return astgen.failNode(out_type_node, "TODO asm with non -> output", .{});
|
||||
var outputs_buffer: [32]Zir.Inst.Asm.Output = undefined;
|
||||
const outputs = outputs_buffer[0..full.outputs.len];
|
||||
|
||||
var output_type_bits: u32 = 0;
|
||||
|
||||
for (full.outputs) |output_node, i| {
|
||||
const symbolic_name = main_tokens[output_node];
|
||||
const name = try gz.identAsString(symbolic_name);
|
||||
const constraint_token = symbolic_name + 2;
|
||||
const constraint = (try gz.strLitAsString(constraint_token)).index;
|
||||
const has_arrow = token_tags[symbolic_name + 4] == .arrow;
|
||||
if (has_arrow) {
|
||||
output_type_bits |= @as(u32, 1) << @intCast(u5, i);
|
||||
const out_type_node = node_datas[output_node].lhs;
|
||||
const out_type_inst = try typeExpr(gz, scope, out_type_node);
|
||||
outputs[i] = .{
|
||||
.name = name,
|
||||
.constraint = constraint,
|
||||
.operand = out_type_inst,
|
||||
};
|
||||
} else {
|
||||
const ident_token = symbolic_name + 4;
|
||||
const str_index = try gz.identAsString(ident_token);
|
||||
// TODO this needs extra code for local variables. Have a look at #215 and related
|
||||
// issues and decide how to handle outputs. Do we want this to be identifiers?
|
||||
// Or maybe we want to force this to be expressions with a pointer type.
|
||||
// Until that is figured out this is only hooked up for referencing Decls.
|
||||
const operand = try gz.addStrTok(.decl_ref, str_index, ident_token);
|
||||
outputs[i] = .{
|
||||
.name = name,
|
||||
.constraint = constraint,
|
||||
.operand = operand,
|
||||
};
|
||||
}
|
||||
const constraint_token = main_tokens[output_node] + 2;
|
||||
break :blk .{
|
||||
.ty = try typeExpr(gz, scope, out_type_node),
|
||||
.constraint = (try gz.strLitAsString(constraint_token)).index,
|
||||
}
|
||||
|
||||
if (full.inputs.len > 32) {
|
||||
return astgen.failNode(full.inputs[32], "too many asm inputs", .{});
|
||||
}
|
||||
var inputs_buffer: [32]Zir.Inst.Asm.Input = undefined;
|
||||
const inputs = inputs_buffer[0..full.inputs.len];
|
||||
|
||||
for (full.inputs) |input_node, i| {
|
||||
const symbolic_name = main_tokens[input_node];
|
||||
const name = try gz.identAsString(symbolic_name);
|
||||
const constraint_token = symbolic_name + 2;
|
||||
const constraint = (try gz.strLitAsString(constraint_token)).index;
|
||||
const has_arrow = token_tags[symbolic_name + 4] == .arrow;
|
||||
const operand = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input_node].lhs);
|
||||
inputs[i] = .{
|
||||
.name = name,
|
||||
.constraint = constraint,
|
||||
.operand = operand,
|
||||
};
|
||||
};
|
||||
|
||||
const constraints = try arena.alloc(u32, full.inputs.len);
|
||||
const args = try arena.alloc(Zir.Inst.Ref, full.inputs.len);
|
||||
|
||||
for (full.inputs) |input, i| {
|
||||
const constraint_token = main_tokens[input] + 2;
|
||||
constraints[i] = (try gz.strLitAsString(constraint_token)).index;
|
||||
args[i] = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input].lhs);
|
||||
}
|
||||
|
||||
const tag: Zir.Inst.Tag = if (full.volatile_token != null) .asm_volatile else .@"asm";
|
||||
const result = try gz.addPlNode(tag, node, Zir.Inst.Asm{
|
||||
var clobbers_buffer: [32]u32 = undefined;
|
||||
var clobber_i: usize = 0;
|
||||
if (full.first_clobber) |first_clobber| clobbers: {
|
||||
// asm ("foo" ::: "a", "b")
|
||||
// asm ("foo" ::: "a", "b",)
|
||||
var tok_i = first_clobber;
|
||||
while (true) : (tok_i += 1) {
|
||||
if (clobber_i >= clobbers_buffer.len) {
|
||||
return astgen.failTok(tok_i, "too many asm clobbers", .{});
|
||||
}
|
||||
clobbers_buffer[clobber_i] = (try gz.strLitAsString(tok_i)).index;
|
||||
clobber_i += 1;
|
||||
tok_i += 1;
|
||||
switch (token_tags[tok_i]) {
|
||||
.r_paren => break :clobbers,
|
||||
.comma => {
|
||||
if (token_tags[tok_i + 1] == .r_paren) {
|
||||
break :clobbers;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = try gz.addAsm(.{
|
||||
.node = node,
|
||||
.asm_source = asm_source,
|
||||
.output_type = output.ty,
|
||||
.args_len = @intCast(u32, full.inputs.len),
|
||||
.clobbers_len = 0, // TODO implement asm clobbers
|
||||
.is_volatile = full.volatile_token != null,
|
||||
.output_type_bits = output_type_bits,
|
||||
.outputs = outputs,
|
||||
.inputs = inputs,
|
||||
.clobbers = clobbers_buffer[0..clobber_i],
|
||||
});
|
||||
|
||||
try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len +
|
||||
args.len + constraints.len + @boolToInt(output.ty != .none));
|
||||
if (output.ty != .none) {
|
||||
astgen.extra.appendAssumeCapacity(output.constraint);
|
||||
}
|
||||
astgen.appendRefsAssumeCapacity(args);
|
||||
astgen.extra.appendSliceAssumeCapacity(constraints);
|
||||
|
||||
return rvalue(gz, scope, rl, result, node);
|
||||
}
|
||||
|
||||
@ -5982,14 +5884,7 @@ fn asRlPtr(
|
||||
// as well as the store instruction, instead passing the result as an rvalue.
|
||||
const astgen = parent_gz.astgen;
|
||||
|
||||
var as_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = parent_gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = parent_gz.force_comptime,
|
||||
.ref_start_index = parent_gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var as_scope = parent_gz.makeSubBlock(scope);
|
||||
defer as_scope.instructions.deinit(astgen.gpa);
|
||||
|
||||
as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr);
|
||||
@ -6701,14 +6596,8 @@ fn cImport(
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
|
||||
var block_scope: GenZir = .{
|
||||
.parent = scope,
|
||||
.decl_node_index = gz.decl_node_index,
|
||||
.astgen = astgen,
|
||||
.force_comptime = true,
|
||||
.ref_start_index = gz.ref_start_index,
|
||||
.instructions = .{},
|
||||
};
|
||||
var block_scope = gz.makeSubBlock(scope);
|
||||
block_scope.force_comptime = true;
|
||||
defer block_scope.instructions.deinit(gpa);
|
||||
|
||||
const block_inst = try gz.addBlock(.c_import, node);
|
||||
@ -6802,43 +6691,44 @@ fn callExpr(
|
||||
}
|
||||
|
||||
pub const simple_types = std.ComptimeStringMap(Zir.Inst.Ref, .{
|
||||
.{ "u8", .u8_type },
|
||||
.{ "i8", .i8_type },
|
||||
.{ "u16", .u16_type },
|
||||
.{ "i16", .i16_type },
|
||||
.{ "u32", .u32_type },
|
||||
.{ "i32", .i32_type },
|
||||
.{ "u64", .u64_type },
|
||||
.{ "i64", .i64_type },
|
||||
.{ "usize", .usize_type },
|
||||
.{ "isize", .isize_type },
|
||||
.{ "c_short", .c_short_type },
|
||||
.{ "c_ushort", .c_ushort_type },
|
||||
.{ "anyerror", .anyerror_type },
|
||||
.{ "anyframe", .anyframe_type },
|
||||
.{ "bool", .bool_type },
|
||||
.{ "c_int", .c_int_type },
|
||||
.{ "c_uint", .c_uint_type },
|
||||
.{ "c_long", .c_long_type },
|
||||
.{ "c_ulong", .c_ulong_type },
|
||||
.{ "c_longlong", .c_longlong_type },
|
||||
.{ "c_ulonglong", .c_ulonglong_type },
|
||||
.{ "c_longdouble", .c_longdouble_type },
|
||||
.{ "c_longlong", .c_longlong_type },
|
||||
.{ "c_short", .c_short_type },
|
||||
.{ "c_uint", .c_uint_type },
|
||||
.{ "c_ulong", .c_ulong_type },
|
||||
.{ "c_ulonglong", .c_ulonglong_type },
|
||||
.{ "c_ushort", .c_ushort_type },
|
||||
.{ "c_void", .c_void_type },
|
||||
.{ "comptime_float", .comptime_float_type },
|
||||
.{ "comptime_int", .comptime_int_type },
|
||||
.{ "f128", .f128_type },
|
||||
.{ "f16", .f16_type },
|
||||
.{ "f32", .f32_type },
|
||||
.{ "f64", .f64_type },
|
||||
.{ "f128", .f128_type },
|
||||
.{ "c_void", .c_void_type },
|
||||
.{ "bool", .bool_type },
|
||||
.{ "void", .void_type },
|
||||
.{ "type", .type_type },
|
||||
.{ "anyerror", .anyerror_type },
|
||||
.{ "comptime_int", .comptime_int_type },
|
||||
.{ "comptime_float", .comptime_float_type },
|
||||
.{ "false", .bool_false },
|
||||
.{ "i16", .i16_type },
|
||||
.{ "i32", .i32_type },
|
||||
.{ "i64", .i64_type },
|
||||
.{ "i128", .i128_type },
|
||||
.{ "i8", .i8_type },
|
||||
.{ "isize", .isize_type },
|
||||
.{ "noreturn", .noreturn_type },
|
||||
.{ "null", .null_type },
|
||||
.{ "undefined", .undefined_type },
|
||||
.{ "undefined", .undef },
|
||||
.{ "null", .null_value },
|
||||
.{ "true", .bool_true },
|
||||
.{ "false", .bool_false },
|
||||
.{ "type", .type_type },
|
||||
.{ "u16", .u16_type },
|
||||
.{ "u32", .u32_type },
|
||||
.{ "u64", .u64_type },
|
||||
.{ "u128", .u128_type },
|
||||
.{ "u8", .u8_type },
|
||||
.{ "undefined", .undef },
|
||||
.{ "usize", .usize_type },
|
||||
.{ "void", .void_type },
|
||||
});
|
||||
|
||||
fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index) bool {
|
||||
|
||||
@ -1085,6 +1085,21 @@ pub const Scope = struct {
|
||||
/// a result location pointer.
|
||||
labeled_store_to_block_ptr_list: ArrayListUnmanaged(Zir.Inst.Index) = .{},
|
||||
|
||||
suspend_node: ast.Node.Index = 0,
|
||||
nosuspend_node: ast.Node.Index = 0,
|
||||
|
||||
pub fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {
|
||||
return .{
|
||||
.force_comptime = gz.force_comptime,
|
||||
.ref_start_index = gz.ref_start_index,
|
||||
.decl_node_index = gz.decl_node_index,
|
||||
.parent = scope,
|
||||
.astgen = gz.astgen,
|
||||
.suspend_node = gz.suspend_node,
|
||||
.nosuspend_node = gz.nosuspend_node,
|
||||
};
|
||||
}
|
||||
|
||||
pub const Label = struct {
|
||||
token: ast.TokenIndex,
|
||||
block_inst: Zir.Inst.Index,
|
||||
@ -1674,9 +1689,9 @@ pub const Scope = struct {
|
||||
@as(usize, @boolToInt(args.type_inst != .none)) +
|
||||
@as(usize, @boolToInt(args.align_inst != .none)),
|
||||
);
|
||||
const payload_index = gz.astgen.addExtra(Zir.Inst.AllocExtended{
|
||||
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.AllocExtended{
|
||||
.src_node = gz.nodeIndexToRelative(args.node),
|
||||
}) catch unreachable; // ensureUnusedCapacity above
|
||||
});
|
||||
if (args.type_inst != .none) {
|
||||
astgen.extra.appendAssumeCapacity(@enumToInt(args.type_inst));
|
||||
}
|
||||
@ -1703,6 +1718,64 @@ pub const Scope = struct {
|
||||
return gz.indexToRef(new_index);
|
||||
}
|
||||
|
||||
pub fn addAsm(
|
||||
gz: *GenZir,
|
||||
args: struct {
|
||||
/// Absolute node index. This function does the conversion to offset from Decl.
|
||||
node: ast.Node.Index,
|
||||
asm_source: Zir.Inst.Ref,
|
||||
output_type_bits: u32,
|
||||
is_volatile: bool,
|
||||
outputs: []const Zir.Inst.Asm.Output,
|
||||
inputs: []const Zir.Inst.Asm.Input,
|
||||
clobbers: []const u32,
|
||||
},
|
||||
) !Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
|
||||
try gz.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Asm).Struct.fields.len +
|
||||
args.outputs.len * @typeInfo(Zir.Inst.Asm.Output).Struct.fields.len +
|
||||
args.inputs.len * @typeInfo(Zir.Inst.Asm.Input).Struct.fields.len +
|
||||
args.clobbers.len);
|
||||
|
||||
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Asm{
|
||||
.src_node = gz.nodeIndexToRelative(args.node),
|
||||
.asm_source = args.asm_source,
|
||||
.output_type_bits = args.output_type_bits,
|
||||
});
|
||||
for (args.outputs) |output| {
|
||||
_ = gz.astgen.addExtraAssumeCapacity(output);
|
||||
}
|
||||
for (args.inputs) |input| {
|
||||
_ = gz.astgen.addExtraAssumeCapacity(input);
|
||||
}
|
||||
gz.astgen.extra.appendSliceAssumeCapacity(args.clobbers);
|
||||
|
||||
// * 0b00000000_000XXXXX - `outputs_len`.
|
||||
// * 0b000000XX_XXX00000 - `inputs_len`.
|
||||
// * 0b0XXXXX00_00000000 - `clobbers_len`.
|
||||
// * 0bX0000000_00000000 - is volatile
|
||||
const small: u16 = @intCast(u16, args.outputs.len) |
|
||||
@intCast(u16, args.inputs.len << 5) |
|
||||
@intCast(u16, args.clobbers.len << 10) |
|
||||
(@as(u16, @boolToInt(args.is_volatile)) << 15);
|
||||
|
||||
const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
|
||||
astgen.instructions.appendAssumeCapacity(.{
|
||||
.tag = .extended,
|
||||
.data = .{ .extended = .{
|
||||
.opcode = .@"asm",
|
||||
.small = small,
|
||||
.operand = payload_index,
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return gz.indexToRef(new_index);
|
||||
}
|
||||
|
||||
/// Note that this returns a `Zir.Inst.Index` not a ref.
|
||||
/// Does *not* append the block instruction to the scope.
|
||||
/// Leaves the `payload_index` field undefined.
|
||||
@ -2209,6 +2282,18 @@ pub const SrcLoc = struct {
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
return token_starts[tok_index];
|
||||
},
|
||||
|
||||
.node_offset_anyframe_type => |node_off| {
|
||||
const tree = src_loc.file_scope.tree;
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
const node = node_datas[parent_node].rhs;
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const tok_index = main_tokens[node];
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
return token_starts[tok_index];
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -2368,6 +2453,12 @@ pub const LazySrcLoc = union(enum) {
|
||||
/// the return type node.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_fn_type_ret_ty: i32,
|
||||
/// The source location points to the type expression of an `anyframe->T`
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate
|
||||
/// to the type expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_anyframe_type: i32,
|
||||
|
||||
/// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.
|
||||
pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {
|
||||
@ -2407,6 +2498,7 @@ pub const LazySrcLoc = union(enum) {
|
||||
.node_offset_switch_range,
|
||||
.node_offset_fn_type_cc,
|
||||
.node_offset_fn_type_ret_ty,
|
||||
.node_offset_anyframe_type,
|
||||
=> .{
|
||||
.file_scope = scope.getFileScope(),
|
||||
.parent_decl_node = scope.srcDecl().?.src_node,
|
||||
@ -2453,6 +2545,7 @@ pub const LazySrcLoc = union(enum) {
|
||||
.node_offset_switch_range,
|
||||
.node_offset_fn_type_cc,
|
||||
.node_offset_fn_type_ret_ty,
|
||||
.node_offset_anyframe_type,
|
||||
=> .{
|
||||
.file_scope = decl.getFileScope(),
|
||||
.parent_decl_node = decl.src_node,
|
||||
|
||||
85
src/Sema.zig
85
src/Sema.zig
@ -138,14 +138,13 @@ pub fn analyzeBody(
|
||||
.alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst),
|
||||
.alloc_mut => try sema.zirAllocMut(block, inst),
|
||||
.alloc_comptime => try sema.zirAllocComptime(block, inst),
|
||||
.anyframe_type => try sema.zirAnyframeType(block, inst),
|
||||
.array_cat => try sema.zirArrayCat(block, inst),
|
||||
.array_mul => try sema.zirArrayMul(block, inst),
|
||||
.array_type => try sema.zirArrayType(block, inst),
|
||||
.array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
|
||||
.as => try sema.zirAs(block, inst),
|
||||
.as_node => try sema.zirAsNode(block, inst),
|
||||
.@"asm" => try sema.zirAsm(block, inst, false),
|
||||
.asm_volatile => try sema.zirAsm(block, inst, true),
|
||||
.bit_and => try sema.zirBitwise(block, inst, .bit_and),
|
||||
.bit_not => try sema.zirBitNot(block, inst),
|
||||
.bit_or => try sema.zirBitwise(block, inst, .bit_or),
|
||||
@ -518,6 +517,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
|
||||
.frame_address => return sema.zirFrameAddress( block, extended),
|
||||
.alloc => return sema.zirAllocExtended( block, extended),
|
||||
.builtin_extern => return sema.zirBuiltinExtern( block, extended),
|
||||
.@"asm" => return sema.zirAsm( block, extended),
|
||||
.c_undef => return sema.zirCUndef( block, extended),
|
||||
.c_include => return sema.zirCInclude( block, extended),
|
||||
.c_define => return sema.zirCDefine( block, extended),
|
||||
@ -2173,6 +2173,19 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
|
||||
return sema.mod.constType(sema.arena, .unneeded, array_ty);
|
||||
}
|
||||
|
||||
fn zirAnyframeType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node };
|
||||
const return_type = try sema.resolveType(block, operand_src, inst_data.operand);
|
||||
const anyframe_type = try Type.Tag.anyframe_T.create(sema.arena, return_type);
|
||||
|
||||
return sema.mod.constType(sema.arena, src, anyframe_type);
|
||||
}
|
||||
|
||||
fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
@ -4394,42 +4407,62 @@ fn zirLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*I
|
||||
fn zirAsm(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
inst: Zir.Inst.Index,
|
||||
is_volatile: bool,
|
||||
extended: Zir.Inst.Extended.InstData,
|
||||
) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const asm_source_src: LazySrcLoc = .{ .node_offset_asm_source = inst_data.src_node };
|
||||
const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Asm, inst_data.payload_index);
|
||||
const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand);
|
||||
const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
|
||||
const asm_source_src: LazySrcLoc = .{ .node_offset_asm_source = extra.data.src_node };
|
||||
const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = extra.data.src_node };
|
||||
const asm_source = try sema.resolveConstString(block, asm_source_src, extra.data.asm_source);
|
||||
const outputs_len = @truncate(u5, extended.small);
|
||||
const inputs_len = @truncate(u5, extended.small >> 5);
|
||||
const clobbers_len = @truncate(u5, extended.small >> 10);
|
||||
const is_volatile = @truncate(u1, extended.small >> 15) != 0;
|
||||
|
||||
if (outputs_len > 1) {
|
||||
return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with more than 1 output", .{});
|
||||
}
|
||||
|
||||
var extra_i = extra.end;
|
||||
var output_type_bits = extra.data.output_type_bits;
|
||||
|
||||
const Output = struct { constraint: []const u8, ty: Type };
|
||||
const output: ?Output = if (extra.data.output_type != .none) blk: {
|
||||
const constraint = sema.code.nullTerminatedString(sema.code.extra[extra_i]);
|
||||
extra_i += 1;
|
||||
const output: ?Output = if (outputs_len == 0) null else blk: {
|
||||
const output = sema.code.extraData(Zir.Inst.Asm.Output, extra_i);
|
||||
extra_i = output.end;
|
||||
|
||||
const is_type = @truncate(u1, output_type_bits) != 0;
|
||||
output_type_bits >>= 1;
|
||||
|
||||
if (!is_type) {
|
||||
return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with non `->` output", .{});
|
||||
}
|
||||
|
||||
const constraint = sema.code.nullTerminatedString(output.data.constraint);
|
||||
break :blk Output{
|
||||
.constraint = constraint,
|
||||
.ty = try sema.resolveType(block, ret_ty_src, extra.data.output_type),
|
||||
.ty = try sema.resolveType(block, ret_ty_src, output.data.operand),
|
||||
};
|
||||
} else null;
|
||||
};
|
||||
|
||||
const args = try sema.arena.alloc(*Inst, extra.data.args_len);
|
||||
const inputs = try sema.arena.alloc([]const u8, extra.data.args_len);
|
||||
const clobbers = try sema.arena.alloc([]const u8, extra.data.clobbers_len);
|
||||
const args = try sema.arena.alloc(*Inst, inputs_len);
|
||||
const inputs = try sema.arena.alloc([]const u8, inputs_len);
|
||||
|
||||
for (args) |*arg| {
|
||||
arg.* = try sema.resolveInst(@intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]));
|
||||
extra_i += 1;
|
||||
}
|
||||
for (inputs) |*name| {
|
||||
name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]);
|
||||
extra_i += 1;
|
||||
for (args) |*arg, arg_i| {
|
||||
const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i);
|
||||
extra_i = input.end;
|
||||
|
||||
const name = sema.code.nullTerminatedString(input.data.name);
|
||||
_ = name; // TODO: use the name
|
||||
|
||||
arg.* = try sema.resolveInst(input.data.operand);
|
||||
inputs[arg_i] = sema.code.nullTerminatedString(input.data.constraint);
|
||||
}
|
||||
|
||||
const clobbers = try sema.arena.alloc([]const u8, clobbers_len);
|
||||
for (clobbers) |*name| {
|
||||
name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]);
|
||||
extra_i += 1;
|
||||
@ -5408,7 +5441,7 @@ fn zirFuncExtended(
|
||||
|
||||
var extra_index: usize = extra.end;
|
||||
if (small.has_lib_name) {
|
||||
const lib_name = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
|
||||
const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
return sema.mod.fail(&block.base, src, "TODO: implement Sema func lib name", .{});
|
||||
}
|
||||
@ -5428,7 +5461,7 @@ fn zirFuncExtended(
|
||||
} else .Unspecified;
|
||||
|
||||
const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
|
||||
extra_index += 1;
|
||||
extra_index += param_types.len;
|
||||
|
||||
const body = sema.code.extra[extra_index..][0..extra.data.body_len];
|
||||
|
||||
|
||||
210
src/Zir.zig
210
src/Zir.zig
@ -60,7 +60,8 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
|
||||
@field(result, field.name) = switch (field.field_type) {
|
||||
u32 => code.extra[i],
|
||||
Inst.Ref => @intToEnum(Inst.Ref, code.extra[i]),
|
||||
else => unreachable,
|
||||
i32 => @bitCast(i32, code.extra[i]),
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
@ -165,18 +166,15 @@ pub const Inst = struct {
|
||||
/// error if the indexable object is not indexable.
|
||||
/// Uses the `un_node` field. The AST node is the for loop node.
|
||||
indexable_ptr_len,
|
||||
/// Create a `anyframe->T` type.
|
||||
/// Uses the `un_node` field.
|
||||
anyframe_type,
|
||||
/// Type coercion. No source location attached.
|
||||
/// Uses the `bin` field.
|
||||
as,
|
||||
/// Type coercion to the function's return type.
|
||||
/// Uses the `pl_node` field. Payload is `As`. AST node could be many things.
|
||||
as_node,
|
||||
/// Inline assembly. Non-volatile.
|
||||
/// Uses the `pl_node` union field. Payload is `Asm`. AST node is the assembly node.
|
||||
@"asm",
|
||||
/// Inline assembly with the volatile attribute.
|
||||
/// Uses the `pl_node` union field. Payload is `Asm`. AST node is the assembly node.
|
||||
asm_volatile,
|
||||
/// Bitwise AND. `&`
|
||||
bit_and,
|
||||
/// Bitcast a value to a different type.
|
||||
@ -967,10 +965,9 @@ pub const Inst = struct {
|
||||
.array_type_sentinel,
|
||||
.elem_type,
|
||||
.indexable_ptr_len,
|
||||
.anyframe_type,
|
||||
.as,
|
||||
.as_node,
|
||||
.@"asm",
|
||||
.asm_volatile,
|
||||
.bit_and,
|
||||
.bitcast,
|
||||
.bitcast_result_ptr,
|
||||
@ -1259,6 +1256,14 @@ pub const Inst = struct {
|
||||
/// The `@extern` builtin.
|
||||
/// `operand` is payload index to `BinNode`.
|
||||
builtin_extern,
|
||||
/// Inline assembly.
|
||||
/// `small`:
|
||||
/// * 0b00000000_000XXXXX - `outputs_len`.
|
||||
/// * 0b000000XX_XXX00000 - `inputs_len`.
|
||||
/// * 0b0XXXXX00_00000000 - `clobbers_len`.
|
||||
/// * 0bX0000000_00000000 - is volatile
|
||||
/// `operand` is payload index to `Asm`.
|
||||
@"asm",
|
||||
/// `operand` is payload index to `UnNode`.
|
||||
c_undef,
|
||||
/// `operand` is payload index to `UnNode`.
|
||||
@ -1313,6 +1318,8 @@ pub const Inst = struct {
|
||||
i32_type,
|
||||
u64_type,
|
||||
i64_type,
|
||||
u128_type,
|
||||
i128_type,
|
||||
usize_type,
|
||||
isize_type,
|
||||
c_short_type,
|
||||
@ -1336,17 +1343,10 @@ pub const Inst = struct {
|
||||
comptime_int_type,
|
||||
comptime_float_type,
|
||||
noreturn_type,
|
||||
anyframe_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,
|
||||
const_slice_u8_type,
|
||||
enum_literal_type,
|
||||
manyptr_u8_type,
|
||||
manyptr_const_u8_type,
|
||||
atomic_ordering_type,
|
||||
atomic_rmw_op_type,
|
||||
calling_convention_type,
|
||||
@ -1355,6 +1355,14 @@ pub const Inst = struct {
|
||||
call_options_type,
|
||||
export_options_type,
|
||||
extern_options_type,
|
||||
manyptr_u8_type,
|
||||
manyptr_const_u8_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,
|
||||
const_slice_u8_type,
|
||||
|
||||
/// `undefined` (untyped)
|
||||
undef,
|
||||
@ -1418,6 +1426,14 @@ pub const Inst = struct {
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.i64_type),
|
||||
},
|
||||
.u128_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.u128_type),
|
||||
},
|
||||
.i128_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.i128_type),
|
||||
},
|
||||
.usize_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.usize_type),
|
||||
@ -1510,6 +1526,10 @@ pub const Inst = struct {
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.noreturn_type),
|
||||
},
|
||||
.anyframe_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.anyframe_type),
|
||||
},
|
||||
.null_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.null_type),
|
||||
@ -1806,17 +1826,35 @@ pub const Inst = struct {
|
||||
}
|
||||
};
|
||||
|
||||
/// Stored in extra. Trailing is:
|
||||
/// * output_constraint: u32 // index into string_bytes (null terminated) if output is present
|
||||
/// * arg: Ref // for every args_len.
|
||||
/// * constraint: u32 // index into string_bytes (null terminated) for every args_len.
|
||||
/// * clobber: u32 // index into string_bytes (null terminated) for every clobbers_len.
|
||||
/// Trailing:
|
||||
/// 0. Output for every outputs_len
|
||||
/// 1. Input for every inputs_len
|
||||
/// 2. clobber: u32 // index into string_bytes (null terminated) for every clobbers_len.
|
||||
pub const Asm = struct {
|
||||
src_node: i32,
|
||||
asm_source: Ref,
|
||||
/// May be omitted.
|
||||
output_type: Ref,
|
||||
args_len: u32,
|
||||
clobbers_len: u32,
|
||||
/// 1 bit for each outputs_len: whether it uses `-> T` or not.
|
||||
/// 0b0 - operand is a pointer to where to store the output.
|
||||
/// 0b1 - operand is a type; asm expression has the output as the result.
|
||||
/// 0b0X is the first output, 0bX0 is the second, etc.
|
||||
output_type_bits: u32,
|
||||
|
||||
pub const Output = struct {
|
||||
/// index into string_bytes (null terminated)
|
||||
name: u32,
|
||||
/// index into string_bytes (null terminated)
|
||||
constraint: u32,
|
||||
/// How to interpret this is determined by `output_type_bits`.
|
||||
operand: Ref,
|
||||
};
|
||||
|
||||
pub const Input = struct {
|
||||
/// index into string_bytes (null terminated)
|
||||
name: u32,
|
||||
/// index into string_bytes (null terminated)
|
||||
constraint: u32,
|
||||
operand: Ref,
|
||||
};
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
@ -2298,6 +2336,7 @@ const Writer = struct {
|
||||
.alloc_mut,
|
||||
.alloc_comptime,
|
||||
.indexable_ptr_len,
|
||||
.anyframe_type,
|
||||
.bit_not,
|
||||
.bool_not,
|
||||
.negate,
|
||||
@ -2430,10 +2469,6 @@ const Writer = struct {
|
||||
.builtin_async_call,
|
||||
=> try self.writePlNode(stream, inst),
|
||||
|
||||
.@"asm",
|
||||
.asm_volatile,
|
||||
=> try self.writePlNodeAsm(stream, inst),
|
||||
|
||||
.error_set_decl => try self.writePlNodeErrorSetDecl(stream, inst),
|
||||
|
||||
.add_with_overflow,
|
||||
@ -2603,7 +2638,9 @@ const Writer = struct {
|
||||
.builtin_src,
|
||||
=> try self.writeExtNode(stream, extended),
|
||||
|
||||
.func,
|
||||
.@"asm" => try self.writeAsm(stream, extended),
|
||||
.func => try self.writeFuncExtended(stream, extended),
|
||||
|
||||
.alloc,
|
||||
.builtin_extern,
|
||||
.c_undef,
|
||||
@ -2794,49 +2831,74 @@ const Writer = struct {
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
fn writePlNodeAsm(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.Asm, inst_data.payload_index);
|
||||
var extra_i: usize = extra.end;
|
||||
fn writeAsm(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
|
||||
const extra = self.code.extraData(Inst.Asm, extended.operand);
|
||||
const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
|
||||
const outputs_len = @truncate(u5, extended.small);
|
||||
const inputs_len = @truncate(u5, extended.small >> 5);
|
||||
const clobbers_len = @truncate(u5, extended.small >> 10);
|
||||
const is_volatile = @truncate(u1, extended.small >> 15) != 0;
|
||||
|
||||
if (extra.data.output_type != .none) {
|
||||
const constraint_str_index = self.code.extra[extra_i];
|
||||
extra_i += 1;
|
||||
const constraint = self.code.nullTerminatedString(constraint_str_index);
|
||||
try stream.print("\"{}\"->", .{std.zig.fmtEscapes(constraint)});
|
||||
try self.writeInstRef(stream, extra.data.output_type);
|
||||
try stream.writeAll(", ");
|
||||
}
|
||||
try self.writeFlag(stream, "volatile, ", is_volatile);
|
||||
try self.writeInstRef(stream, extra.data.asm_source);
|
||||
try stream.writeAll(", ");
|
||||
|
||||
var extra_i: usize = extra.end;
|
||||
var output_type_bits = extra.data.output_type_bits;
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < extra.data.args_len) : (i += 1) {
|
||||
const arg = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_i]);
|
||||
extra_i += 1;
|
||||
try self.writeInstRef(stream, arg);
|
||||
try stream.writeAll(", ");
|
||||
while (i < outputs_len) : (i += 1) {
|
||||
const output = self.code.extraData(Inst.Asm.Output, extra_i);
|
||||
extra_i = output.end;
|
||||
|
||||
const is_type = @truncate(u1, output_type_bits) != 0;
|
||||
output_type_bits >>= 1;
|
||||
|
||||
const name = self.code.nullTerminatedString(output.data.name);
|
||||
const constraint = self.code.nullTerminatedString(output.data.constraint);
|
||||
try stream.print("output({}, \"{}\", ", .{
|
||||
std.zig.fmtId(name), std.zig.fmtEscapes(constraint),
|
||||
});
|
||||
try self.writeFlag(stream, "->", is_type);
|
||||
try self.writeInstRef(stream, output.data.operand);
|
||||
try stream.writeAll(")");
|
||||
if (i + 1 < outputs_len) {
|
||||
try stream.writeAll("), ");
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < extra.data.args_len) : (i += 1) {
|
||||
const str_index = self.code.extra[extra_i];
|
||||
extra_i += 1;
|
||||
const constraint = self.code.nullTerminatedString(str_index);
|
||||
try stream.print("\"{}\", ", .{std.zig.fmtEscapes(constraint)});
|
||||
while (i < inputs_len) : (i += 1) {
|
||||
const input = self.code.extraData(Inst.Asm.Input, extra_i);
|
||||
extra_i = input.end;
|
||||
|
||||
const name = self.code.nullTerminatedString(input.data.name);
|
||||
const constraint = self.code.nullTerminatedString(input.data.constraint);
|
||||
try stream.print("input({}, \"{}\", ", .{
|
||||
std.zig.fmtId(name), std.zig.fmtEscapes(constraint),
|
||||
});
|
||||
try self.writeInstRef(stream, input.data.operand);
|
||||
try stream.writeAll(")");
|
||||
if (i + 1 < inputs_len) {
|
||||
try stream.writeAll(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < extra.data.clobbers_len) : (i += 1) {
|
||||
while (i < clobbers_len) : (i += 1) {
|
||||
const str_index = self.code.extra[extra_i];
|
||||
extra_i += 1;
|
||||
const clobber = self.code.nullTerminatedString(str_index);
|
||||
try stream.print("{}, ", .{std.zig.fmtId(clobber)});
|
||||
try stream.print("{}", .{std.zig.fmtId(clobber)});
|
||||
if (i + 1 < clobbers_len) {
|
||||
try stream.writeAll(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
try self.writeInstRef(stream, extra.data.asm_source);
|
||||
try stream.writeAll(") ");
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
try self.writeSrc(stream, src);
|
||||
}
|
||||
|
||||
fn writePlNodeOverflowArithmetic(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
@ -3467,6 +3529,40 @@ const Writer = struct {
|
||||
);
|
||||
}
|
||||
|
||||
fn writeFuncExtended(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
|
||||
const extra = self.code.extraData(Inst.ExtendedFunc, extended.operand);
|
||||
const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
|
||||
const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);
|
||||
|
||||
var extra_index: usize = extra.end;
|
||||
if (small.has_lib_name) {
|
||||
const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});
|
||||
}
|
||||
const cc: Inst.Ref = if (!small.has_cc) .none else blk: {
|
||||
const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
break :blk cc;
|
||||
};
|
||||
|
||||
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];
|
||||
|
||||
return self.writeFuncCommon(
|
||||
stream,
|
||||
param_types,
|
||||
extra.data.return_type,
|
||||
small.is_inferred_error,
|
||||
small.is_var_args,
|
||||
cc,
|
||||
body,
|
||||
src,
|
||||
);
|
||||
}
|
||||
|
||||
fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].bool_br;
|
||||
const extra = self.code.extraData(Inst.Block, inst_data.payload_index);
|
||||
|
||||
44
src/type.zig
44
src/type.zig
@ -95,6 +95,8 @@ pub const Type = extern union {
|
||||
|
||||
.anyerror_void_error_union, .error_union => return .ErrorUnion,
|
||||
|
||||
.anyframe_T, .@"anyframe" => return .AnyFrame,
|
||||
|
||||
.empty_struct,
|
||||
.empty_struct_literal,
|
||||
.@"struct",
|
||||
@ -620,6 +622,7 @@ pub const Type = extern union {
|
||||
.call_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
.@"anyframe",
|
||||
=> unreachable,
|
||||
|
||||
.array_u8,
|
||||
@ -637,6 +640,7 @@ pub const Type = extern union {
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
.anyframe_T,
|
||||
=> return self.copyPayloadShallow(allocator, Payload.ElemType),
|
||||
|
||||
.int_signed,
|
||||
@ -754,6 +758,7 @@ pub const Type = extern union {
|
||||
.void,
|
||||
.type,
|
||||
.anyerror,
|
||||
.@"anyframe",
|
||||
.comptime_int,
|
||||
.comptime_float,
|
||||
.noreturn,
|
||||
@ -820,6 +825,12 @@ pub const Type = extern union {
|
||||
continue;
|
||||
},
|
||||
|
||||
.anyframe_T => {
|
||||
const return_type = ty.castTag(.anyframe_T).?.data;
|
||||
try writer.print("anyframe->", .{});
|
||||
ty = return_type;
|
||||
continue;
|
||||
},
|
||||
.array_u8 => {
|
||||
const len = ty.castTag(.array_u8).?.data;
|
||||
return writer.print("[{d}]u8", .{len});
|
||||
@ -994,6 +1005,7 @@ pub const Type = extern union {
|
||||
.void => return Value.initTag(.void_type),
|
||||
.type => return Value.initTag(.type_type),
|
||||
.anyerror => return Value.initTag(.anyerror_type),
|
||||
.@"anyframe" => return Value.initTag(.anyframe_type),
|
||||
.comptime_int => return Value.initTag(.comptime_int_type),
|
||||
.comptime_float => return Value.initTag(.comptime_float_type),
|
||||
.noreturn => return Value.initTag(.noreturn_type),
|
||||
@ -1075,6 +1087,8 @@ pub const Type = extern union {
|
||||
.call_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
.@"anyframe",
|
||||
.anyframe_T,
|
||||
=> true,
|
||||
|
||||
.@"struct" => {
|
||||
@ -1223,6 +1237,8 @@ pub const Type = extern union {
|
||||
.pointer,
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.@"anyframe",
|
||||
.anyframe_T,
|
||||
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
|
||||
.c_short => return @divExact(CType.short.sizeInBits(target), 8),
|
||||
@ -1388,7 +1404,11 @@ pub const Type = extern union {
|
||||
.i64, .u64 => return 8,
|
||||
.u128, .i128 => return 16,
|
||||
|
||||
.isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
.isize,
|
||||
.usize,
|
||||
.@"anyframe",
|
||||
.anyframe_T,
|
||||
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
|
||||
.const_slice,
|
||||
.mut_slice,
|
||||
@ -1536,7 +1556,11 @@ pub const Type = extern union {
|
||||
.i64, .u64, .f64 => 64,
|
||||
.u128, .i128, .f128 => 128,
|
||||
|
||||
.isize, .usize => target.cpu.arch.ptrBitWidth(),
|
||||
.isize,
|
||||
.usize,
|
||||
.@"anyframe",
|
||||
.anyframe_T,
|
||||
=> target.cpu.arch.ptrBitWidth(),
|
||||
|
||||
.const_slice,
|
||||
.mut_slice,
|
||||
@ -2256,6 +2280,8 @@ pub const Type = extern union {
|
||||
.call_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
.@"anyframe",
|
||||
.anyframe_T,
|
||||
=> return null,
|
||||
|
||||
.@"struct" => {
|
||||
@ -2666,9 +2692,10 @@ pub const Type = extern union {
|
||||
comptime_int,
|
||||
comptime_float,
|
||||
noreturn,
|
||||
@"anyframe",
|
||||
@"null",
|
||||
@"undefined",
|
||||
enum_literal,
|
||||
manyptr_u8,
|
||||
manyptr_const_u8,
|
||||
atomic_ordering,
|
||||
atomic_rmw_op,
|
||||
calling_convention,
|
||||
@ -2677,15 +2704,15 @@ pub const Type = extern union {
|
||||
call_options,
|
||||
export_options,
|
||||
extern_options,
|
||||
@"null",
|
||||
@"undefined",
|
||||
manyptr_u8,
|
||||
manyptr_const_u8,
|
||||
fn_noreturn_no_args,
|
||||
fn_void_no_args,
|
||||
fn_naked_noreturn_no_args,
|
||||
fn_ccc_void_no_args,
|
||||
single_const_pointer_to_comptime_int,
|
||||
anyerror_void_error_union,
|
||||
const_slice_u8,
|
||||
anyerror_void_error_union,
|
||||
/// This is a special type for variadic parameters of a function call.
|
||||
/// Casts to it will validate that the type can be passed to a c calling convetion function.
|
||||
var_args_param,
|
||||
@ -2719,6 +2746,7 @@ pub const Type = extern union {
|
||||
optional_single_mut_pointer,
|
||||
optional_single_const_pointer,
|
||||
error_union,
|
||||
anyframe_T,
|
||||
error_set,
|
||||
error_set_single,
|
||||
empty_struct,
|
||||
@ -2790,6 +2818,7 @@ pub const Type = extern union {
|
||||
.call_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
.@"anyframe",
|
||||
=> @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
|
||||
|
||||
.array_u8,
|
||||
@ -2807,6 +2836,7 @@ pub const Type = extern union {
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
.anyframe_T,
|
||||
=> Payload.ElemType,
|
||||
|
||||
.int_signed,
|
||||
|
||||
@ -55,17 +55,10 @@ pub const Value = extern union {
|
||||
comptime_int_type,
|
||||
comptime_float_type,
|
||||
noreturn_type,
|
||||
anyframe_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,
|
||||
const_slice_u8_type,
|
||||
enum_literal_type,
|
||||
manyptr_u8_type,
|
||||
manyptr_const_u8_type,
|
||||
atomic_ordering_type,
|
||||
atomic_rmw_op_type,
|
||||
calling_convention_type,
|
||||
@ -74,6 +67,14 @@ pub const Value = extern union {
|
||||
call_options_type,
|
||||
export_options_type,
|
||||
extern_options_type,
|
||||
manyptr_u8_type,
|
||||
manyptr_const_u8_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,
|
||||
const_slice_u8_type,
|
||||
|
||||
undef,
|
||||
zero,
|
||||
@ -166,6 +167,7 @@ pub const Value = extern union {
|
||||
.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,
|
||||
.undef,
|
||||
@ -334,6 +336,7 @@ pub const Value = extern union {
|
||||
.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,
|
||||
.undef,
|
||||
@ -502,6 +505,7 @@ pub const Value = extern union {
|
||||
.fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
|
||||
.fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),
|
||||
.single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
|
||||
.anyframe_type => return out_stream.writeAll("anyframe"),
|
||||
.const_slice_u8_type => return out_stream.writeAll("[]const u8"),
|
||||
.enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),
|
||||
.manyptr_u8_type => return out_stream.writeAll("[*]u8"),
|
||||
@ -633,6 +637,7 @@ pub const Value = extern union {
|
||||
.fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),
|
||||
.fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),
|
||||
.single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
|
||||
.anyframe_type => Type.initTag(.@"anyframe"),
|
||||
.const_slice_u8_type => Type.initTag(.const_slice_u8),
|
||||
.enum_literal_type => Type.initTag(.enum_literal),
|
||||
.manyptr_u8_type => Type.initTag(.manyptr_u8),
|
||||
@ -1070,6 +1075,7 @@ pub const Value = extern union {
|
||||
.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,
|
||||
@ -1338,6 +1344,7 @@ pub const Value = extern union {
|
||||
.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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user