use * for pointer type instead of &
See #770 To help automatically translate code, see the zig-fmt-pointer-reform-2 branch. This will convert all & into *. Due to the syntax ambiguity (which is why we are making this change), even address-of & will turn into *, so you'll have to manually fix thes instances. You will be guaranteed to get compile errors for them - expected 'type', found 'foo'
This commit is contained in:
@@ -374,7 +374,7 @@ enum NodeType {
|
||||
NodeTypeCharLiteral,
|
||||
NodeTypeSymbol,
|
||||
NodeTypePrefixOpExpr,
|
||||
NodeTypeAddrOfExpr,
|
||||
NodeTypePointerType,
|
||||
NodeTypeFnCallExpr,
|
||||
NodeTypeArrayAccessExpr,
|
||||
NodeTypeSliceExpr,
|
||||
@@ -616,6 +616,7 @@ enum PrefixOp {
|
||||
PrefixOpNegationWrap,
|
||||
PrefixOpMaybe,
|
||||
PrefixOpUnwrapMaybe,
|
||||
PrefixOpAddrOf,
|
||||
};
|
||||
|
||||
struct AstNodePrefixOpExpr {
|
||||
@@ -623,7 +624,7 @@ struct AstNodePrefixOpExpr {
|
||||
AstNode *primary_expr;
|
||||
};
|
||||
|
||||
struct AstNodeAddrOfExpr {
|
||||
struct AstNodePointerType {
|
||||
AstNode *align_expr;
|
||||
BigInt *bit_offset_start;
|
||||
BigInt *bit_offset_end;
|
||||
@@ -899,7 +900,7 @@ struct AstNode {
|
||||
AstNodeBinOpExpr bin_op_expr;
|
||||
AstNodeCatchExpr unwrap_err_expr;
|
||||
AstNodePrefixOpExpr prefix_op_expr;
|
||||
AstNodeAddrOfExpr addr_of_expr;
|
||||
AstNodePointerType pointer_type;
|
||||
AstNodeFnCallExpr fn_call_expr;
|
||||
AstNodeArrayAccessExpr array_access_expr;
|
||||
AstNodeSliceExpr slice_expr;
|
||||
@@ -2053,7 +2054,7 @@ enum IrInstructionId {
|
||||
IrInstructionIdTypeInfo,
|
||||
IrInstructionIdTypeId,
|
||||
IrInstructionIdSetEvalBranchQuota,
|
||||
IrInstructionIdPtrTypeOf,
|
||||
IrInstructionIdPtrType,
|
||||
IrInstructionIdAlignCast,
|
||||
IrInstructionIdOpaqueType,
|
||||
IrInstructionIdSetAlignStack,
|
||||
@@ -2412,6 +2413,17 @@ struct IrInstructionArrayType {
|
||||
IrInstruction *child_type;
|
||||
};
|
||||
|
||||
struct IrInstructionPtrType {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *align_value;
|
||||
IrInstruction *child_type;
|
||||
uint32_t bit_offset_start;
|
||||
uint32_t bit_offset_end;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
};
|
||||
|
||||
struct IrInstructionPromiseType {
|
||||
IrInstruction base;
|
||||
|
||||
@@ -2891,17 +2903,6 @@ struct IrInstructionSetEvalBranchQuota {
|
||||
IrInstruction *new_quota;
|
||||
};
|
||||
|
||||
struct IrInstructionPtrTypeOf {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *align_value;
|
||||
IrInstruction *child_type;
|
||||
uint32_t bit_offset_start;
|
||||
uint32_t bit_offset_end;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
};
|
||||
|
||||
struct IrInstructionAlignCast {
|
||||
IrInstruction base;
|
||||
|
||||
|
||||
@@ -418,12 +418,12 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
|
||||
const char *volatile_str = is_volatile ? "volatile " : "";
|
||||
buf_resize(&entry->name, 0);
|
||||
if (unaligned_bit_count == 0 && byte_alignment == abi_alignment) {
|
||||
buf_appendf(&entry->name, "&%s%s%s", const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
buf_appendf(&entry->name, "*%s%s%s", const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
} else if (unaligned_bit_count == 0) {
|
||||
buf_appendf(&entry->name, "&align(%" PRIu32 ") %s%s%s", byte_alignment,
|
||||
buf_appendf(&entry->name, "*align(%" PRIu32 ") %s%s%s", byte_alignment,
|
||||
const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
} else {
|
||||
buf_appendf(&entry->name, "&align(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", byte_alignment,
|
||||
buf_appendf(&entry->name, "*align(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", byte_alignment,
|
||||
bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
}
|
||||
|
||||
@@ -3270,7 +3270,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
|
||||
case NodeTypeThisLiteral:
|
||||
case NodeTypeSymbol:
|
||||
case NodeTypePrefixOpExpr:
|
||||
case NodeTypeAddrOfExpr:
|
||||
case NodeTypePointerType:
|
||||
case NodeTypeIfBoolExpr:
|
||||
case NodeTypeWhileExpr:
|
||||
case NodeTypeForExpr:
|
||||
|
||||
@@ -68,6 +68,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
|
||||
case PrefixOpBinNot: return "~";
|
||||
case PrefixOpMaybe: return "?";
|
||||
case PrefixOpUnwrapMaybe: return "??";
|
||||
case PrefixOpAddrOf: return "&";
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@@ -185,8 +186,6 @@ static const char *node_type_str(NodeType node_type) {
|
||||
return "Symbol";
|
||||
case NodeTypePrefixOpExpr:
|
||||
return "PrefixOpExpr";
|
||||
case NodeTypeAddrOfExpr:
|
||||
return "AddrOfExpr";
|
||||
case NodeTypeUse:
|
||||
return "Use";
|
||||
case NodeTypeBoolLiteral:
|
||||
@@ -251,6 +250,8 @@ static const char *node_type_str(NodeType node_type) {
|
||||
return "Suspend";
|
||||
case NodeTypePromiseType:
|
||||
return "PromiseType";
|
||||
case NodeTypePointerType:
|
||||
return "PointerType";
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@@ -616,41 +617,41 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
fprintf(ar->f, "%s", prefix_op_str(op));
|
||||
|
||||
AstNode *child_node = node->data.prefix_op_expr.primary_expr;
|
||||
bool new_grouped = child_node->type == NodeTypePrefixOpExpr || child_node->type == NodeTypeAddrOfExpr;
|
||||
bool new_grouped = child_node->type == NodeTypePrefixOpExpr || child_node->type == NodeTypePointerType;
|
||||
render_node_extra(ar, child_node, new_grouped);
|
||||
if (!grouped) fprintf(ar->f, ")");
|
||||
break;
|
||||
}
|
||||
case NodeTypeAddrOfExpr:
|
||||
case NodeTypePointerType:
|
||||
{
|
||||
if (!grouped) fprintf(ar->f, "(");
|
||||
fprintf(ar->f, "&");
|
||||
if (node->data.addr_of_expr.align_expr != nullptr) {
|
||||
fprintf(ar->f, "*");
|
||||
if (node->data.pointer_type.align_expr != nullptr) {
|
||||
fprintf(ar->f, "align(");
|
||||
render_node_grouped(ar, node->data.addr_of_expr.align_expr);
|
||||
if (node->data.addr_of_expr.bit_offset_start != nullptr) {
|
||||
assert(node->data.addr_of_expr.bit_offset_end != nullptr);
|
||||
render_node_grouped(ar, node->data.pointer_type.align_expr);
|
||||
if (node->data.pointer_type.bit_offset_start != nullptr) {
|
||||
assert(node->data.pointer_type.bit_offset_end != nullptr);
|
||||
|
||||
Buf offset_start_buf = BUF_INIT;
|
||||
buf_resize(&offset_start_buf, 0);
|
||||
bigint_append_buf(&offset_start_buf, node->data.addr_of_expr.bit_offset_start, 10);
|
||||
bigint_append_buf(&offset_start_buf, node->data.pointer_type.bit_offset_start, 10);
|
||||
|
||||
Buf offset_end_buf = BUF_INIT;
|
||||
buf_resize(&offset_end_buf, 0);
|
||||
bigint_append_buf(&offset_end_buf, node->data.addr_of_expr.bit_offset_end, 10);
|
||||
bigint_append_buf(&offset_end_buf, node->data.pointer_type.bit_offset_end, 10);
|
||||
|
||||
fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf));
|
||||
}
|
||||
fprintf(ar->f, ") ");
|
||||
}
|
||||
if (node->data.addr_of_expr.is_const) {
|
||||
if (node->data.pointer_type.is_const) {
|
||||
fprintf(ar->f, "const ");
|
||||
}
|
||||
if (node->data.addr_of_expr.is_volatile) {
|
||||
if (node->data.pointer_type.is_volatile) {
|
||||
fprintf(ar->f, "volatile ");
|
||||
}
|
||||
|
||||
render_node_ungrouped(ar, node->data.addr_of_expr.op_expr);
|
||||
render_node_ungrouped(ar, node->data.pointer_type.op_expr);
|
||||
if (!grouped) fprintf(ar->f, ")");
|
||||
break;
|
||||
}
|
||||
@@ -669,7 +670,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
fprintf(ar->f, " ");
|
||||
}
|
||||
AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
|
||||
bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypeAddrOfExpr);
|
||||
bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypePointerType);
|
||||
render_node_extra(ar, fn_ref_node, grouped);
|
||||
fprintf(ar->f, "(");
|
||||
for (size_t i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
|
||||
|
||||
@@ -4600,7 +4600,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
case IrInstructionIdTypeInfo:
|
||||
case IrInstructionIdTypeId:
|
||||
case IrInstructionIdSetEvalBranchQuota:
|
||||
case IrInstructionIdPtrTypeOf:
|
||||
case IrInstructionIdPtrType:
|
||||
case IrInstructionIdOpaqueType:
|
||||
case IrInstructionIdSetAlignStack:
|
||||
case IrInstructionIdArgType:
|
||||
|
||||
89
src/ir.cpp
89
src/ir.cpp
@@ -41,10 +41,6 @@ struct IrAnalyze {
|
||||
static const LVal LVAL_NONE = { false, false, false };
|
||||
static const LVal LVAL_PTR = { true, false, false };
|
||||
|
||||
static LVal make_lval_addr(bool is_const, bool is_volatile) {
|
||||
return { true, is_const, is_volatile };
|
||||
}
|
||||
|
||||
enum ConstCastResultId {
|
||||
ConstCastResultIdOk,
|
||||
ConstCastResultIdErrSet,
|
||||
@@ -629,8 +625,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetEvalBranchQuo
|
||||
return IrInstructionIdSetEvalBranchQuota;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeOf *) {
|
||||
return IrInstructionIdPtrTypeOf;
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrType *) {
|
||||
return IrInstructionIdPtrType;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) {
|
||||
@@ -1196,11 +1192,11 @@ static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instru
|
||||
return new_instruction;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_ptr_type_of(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value,
|
||||
uint32_t bit_offset_start, uint32_t bit_offset_end)
|
||||
{
|
||||
IrInstructionPtrTypeOf *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrTypeOf>(irb, scope, source_node);
|
||||
IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node);
|
||||
ptr_type_of_instruction->align_value = align_value;
|
||||
ptr_type_of_instruction->child_type = child_type;
|
||||
ptr_type_of_instruction->is_const = is_const;
|
||||
@@ -4609,14 +4605,8 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
|
||||
AstNode *expr_node;
|
||||
if (node->type == NodeTypePrefixOpExpr) {
|
||||
expr_node = node->data.prefix_op_expr.primary_expr;
|
||||
} else if (node->type == NodeTypePtrDeref) {
|
||||
expr_node = node->data.ptr_deref_expr.target;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
assert(node->type == NodeTypePrefixOpExpr);
|
||||
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
|
||||
|
||||
IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
|
||||
if (value == irb->codegen->invalid_instruction)
|
||||
@@ -4640,16 +4630,12 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
|
||||
return ir_build_ref(irb, scope, value->source_node, value, lval.is_const, lval.is_volatile);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||
assert(node->type == NodeTypeAddrOfExpr);
|
||||
bool is_const = node->data.addr_of_expr.is_const;
|
||||
bool is_volatile = node->data.addr_of_expr.is_volatile;
|
||||
AstNode *expr_node = node->data.addr_of_expr.op_expr;
|
||||
AstNode *align_expr = node->data.addr_of_expr.align_expr;
|
||||
|
||||
if (align_expr == nullptr && !is_const && !is_volatile) {
|
||||
return ir_gen_node_extra(irb, expr_node, scope, make_lval_addr(is_const, is_volatile));
|
||||
}
|
||||
static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||
assert(node->type == NodeTypePointerType);
|
||||
bool is_const = node->data.pointer_type.is_const;
|
||||
bool is_volatile = node->data.pointer_type.is_volatile;
|
||||
AstNode *expr_node = node->data.pointer_type.op_expr;
|
||||
AstNode *align_expr = node->data.pointer_type.align_expr;
|
||||
|
||||
IrInstruction *align_value;
|
||||
if (align_expr != nullptr) {
|
||||
@@ -4665,27 +4651,27 @@ static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *n
|
||||
return child_type;
|
||||
|
||||
uint32_t bit_offset_start = 0;
|
||||
if (node->data.addr_of_expr.bit_offset_start != nullptr) {
|
||||
if (!bigint_fits_in_bits(node->data.addr_of_expr.bit_offset_start, 32, false)) {
|
||||
if (node->data.pointer_type.bit_offset_start != nullptr) {
|
||||
if (!bigint_fits_in_bits(node->data.pointer_type.bit_offset_start, 32, false)) {
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, node->data.addr_of_expr.bit_offset_start, 10);
|
||||
bigint_append_buf(val_buf, node->data.pointer_type.bit_offset_start, 10);
|
||||
exec_add_error_node(irb->codegen, irb->exec, node,
|
||||
buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf)));
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
bit_offset_start = bigint_as_unsigned(node->data.addr_of_expr.bit_offset_start);
|
||||
bit_offset_start = bigint_as_unsigned(node->data.pointer_type.bit_offset_start);
|
||||
}
|
||||
|
||||
uint32_t bit_offset_end = 0;
|
||||
if (node->data.addr_of_expr.bit_offset_end != nullptr) {
|
||||
if (!bigint_fits_in_bits(node->data.addr_of_expr.bit_offset_end, 32, false)) {
|
||||
if (node->data.pointer_type.bit_offset_end != nullptr) {
|
||||
if (!bigint_fits_in_bits(node->data.pointer_type.bit_offset_end, 32, false)) {
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, node->data.addr_of_expr.bit_offset_end, 10);
|
||||
bigint_append_buf(val_buf, node->data.pointer_type.bit_offset_end, 10);
|
||||
exec_add_error_node(irb->codegen, irb->exec, node,
|
||||
buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf)));
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
bit_offset_end = bigint_as_unsigned(node->data.addr_of_expr.bit_offset_end);
|
||||
bit_offset_end = bigint_as_unsigned(node->data.pointer_type.bit_offset_end);
|
||||
}
|
||||
|
||||
if ((bit_offset_start != 0 || bit_offset_end != 0) && bit_offset_start >= bit_offset_end) {
|
||||
@@ -4694,7 +4680,7 @@ static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *n
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
return ir_build_ptr_type_of(irb, scope, node, child_type, is_const, is_volatile,
|
||||
return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile,
|
||||
align_value, bit_offset_start, bit_offset_end);
|
||||
}
|
||||
|
||||
@@ -4761,6 +4747,10 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval);
|
||||
case PrefixOpUnwrapMaybe:
|
||||
return ir_gen_maybe_assert_ok(irb, scope, node, lval);
|
||||
case PrefixOpAddrOf: {
|
||||
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
|
||||
return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR), lval);
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@@ -6568,8 +6558,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
|
||||
return ir_lval_wrap(irb, scope, ir_gen_if_bool_expr(irb, scope, node), lval);
|
||||
case NodeTypePrefixOpExpr:
|
||||
return ir_gen_prefix_op_expr(irb, scope, node, lval);
|
||||
case NodeTypeAddrOfExpr:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_address_of(irb, scope, node), lval);
|
||||
case NodeTypeContainerInitExpr:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval);
|
||||
case NodeTypeVariableDeclaration:
|
||||
@@ -6592,14 +6580,23 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
|
||||
|
||||
return ir_build_load_ptr(irb, scope, node, ptr_instruction);
|
||||
}
|
||||
case NodeTypePtrDeref:
|
||||
return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
|
||||
case NodeTypePtrDeref: {
|
||||
assert(node->type == NodeTypePtrDeref);
|
||||
AstNode *expr_node = node->data.ptr_deref_expr.target;
|
||||
IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
|
||||
if (value == irb->codegen->invalid_instruction)
|
||||
return value;
|
||||
|
||||
return ir_build_un_op(irb, scope, node, IrUnOpDereference, value);
|
||||
}
|
||||
case NodeTypeThisLiteral:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval);
|
||||
case NodeTypeBoolLiteral:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);
|
||||
case NodeTypeArrayType:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval);
|
||||
case NodeTypePointerType:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval);
|
||||
case NodeTypePromiseType:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_promise_type(irb, scope, node), lval);
|
||||
case NodeTypeStringLiteral:
|
||||
@@ -8961,6 +8958,7 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
|
||||
ConstExprValue *pointee, TypeTableEntry *pointee_type,
|
||||
ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile, uint32_t ptr_align)
|
||||
{
|
||||
// TODO remove this special case for types
|
||||
if (pointee_type->id == TypeTableEntryIdMetaType) {
|
||||
TypeTableEntry *type_entry = pointee->data.x_type;
|
||||
if (type_entry->id == TypeTableEntryIdUnreachable) {
|
||||
@@ -18778,11 +18776,16 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr
|
||||
return usize;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_ptr_type_of(IrAnalyze *ira, IrInstructionPtrTypeOf *instruction) {
|
||||
static TypeTableEntry *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtrType *instruction) {
|
||||
TypeTableEntry *child_type = ir_resolve_type(ira, instruction->child_type->other);
|
||||
if (type_is_invalid(child_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (child_type->id == TypeTableEntryIdUnreachable) {
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("pointer to noreturn not allowed"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
uint32_t align_bytes;
|
||||
if (instruction->align_value != nullptr) {
|
||||
if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes))
|
||||
@@ -19606,8 +19609,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
|
||||
return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction);
|
||||
case IrInstructionIdSetEvalBranchQuota:
|
||||
return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstructionSetEvalBranchQuota *)instruction);
|
||||
case IrInstructionIdPtrTypeOf:
|
||||
return ir_analyze_instruction_ptr_type_of(ira, (IrInstructionPtrTypeOf *)instruction);
|
||||
case IrInstructionIdPtrType:
|
||||
return ir_analyze_instruction_ptr_type(ira, (IrInstructionPtrType *)instruction);
|
||||
case IrInstructionIdAlignCast:
|
||||
return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
|
||||
case IrInstructionIdOpaqueType:
|
||||
@@ -19783,7 +19786,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
case IrInstructionIdCheckStatementIsVoid:
|
||||
case IrInstructionIdPanic:
|
||||
case IrInstructionIdSetEvalBranchQuota:
|
||||
case IrInstructionIdPtrTypeOf:
|
||||
case IrInstructionIdPtrType:
|
||||
case IrInstructionIdSetAlignStack:
|
||||
case IrInstructionIdExport:
|
||||
case IrInstructionIdCancel:
|
||||
|
||||
@@ -921,7 +921,7 @@ static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCas
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_ptr_type_of(IrPrint *irp, IrInstructionPtrTypeOf *instruction) {
|
||||
static void ir_print_ptr_type(IrPrint *irp, IrInstructionPtrType *instruction) {
|
||||
fprintf(irp->f, "&");
|
||||
if (instruction->align_value != nullptr) {
|
||||
fprintf(irp->f, "align(");
|
||||
@@ -1527,8 +1527,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdCanImplicitCast:
|
||||
ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction);
|
||||
break;
|
||||
case IrInstructionIdPtrTypeOf:
|
||||
ir_print_ptr_type_of(irp, (IrInstructionPtrTypeOf *)instruction);
|
||||
case IrInstructionIdPtrType:
|
||||
ir_print_ptr_type(irp, (IrInstructionPtrType *)instruction);
|
||||
break;
|
||||
case IrInstructionIdDeclRef:
|
||||
ir_print_decl_ref(irp, (IrInstructionDeclRef *)instruction);
|
||||
|
||||
@@ -1167,20 +1167,19 @@ static PrefixOp tok_to_prefix_op(Token *token) {
|
||||
case TokenIdTilde: return PrefixOpBinNot;
|
||||
case TokenIdMaybe: return PrefixOpMaybe;
|
||||
case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe;
|
||||
case TokenIdAmpersand: return PrefixOpAddrOf;
|
||||
default: return PrefixOpInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) {
|
||||
Token *ampersand_tok = ast_eat_token(pc, token_index, TokenIdAmpersand);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeAddrOfExpr, ampersand_tok);
|
||||
static AstNode *ast_parse_pointer_type(ParseContext *pc, size_t *token_index, Token *star_tok) {
|
||||
AstNode *node = ast_create_node(pc, NodeTypePointerType, star_tok);
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdKeywordAlign) {
|
||||
*token_index += 1;
|
||||
ast_eat_token(pc, token_index, TokenIdLParen);
|
||||
node->data.addr_of_expr.align_expr = ast_parse_expression(pc, token_index, true);
|
||||
node->data.pointer_type.align_expr = ast_parse_expression(pc, token_index, true);
|
||||
|
||||
token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdColon) {
|
||||
@@ -1189,24 +1188,24 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) {
|
||||
ast_eat_token(pc, token_index, TokenIdColon);
|
||||
Token *bit_offset_end_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral);
|
||||
|
||||
node->data.addr_of_expr.bit_offset_start = token_bigint(bit_offset_start_tok);
|
||||
node->data.addr_of_expr.bit_offset_end = token_bigint(bit_offset_end_tok);
|
||||
node->data.pointer_type.bit_offset_start = token_bigint(bit_offset_start_tok);
|
||||
node->data.pointer_type.bit_offset_end = token_bigint(bit_offset_end_tok);
|
||||
}
|
||||
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||
token = &pc->tokens->at(*token_index);
|
||||
}
|
||||
if (token->id == TokenIdKeywordConst) {
|
||||
*token_index += 1;
|
||||
node->data.addr_of_expr.is_const = true;
|
||||
node->data.pointer_type.is_const = true;
|
||||
|
||||
token = &pc->tokens->at(*token_index);
|
||||
}
|
||||
if (token->id == TokenIdKeywordVolatile) {
|
||||
*token_index += 1;
|
||||
node->data.addr_of_expr.is_volatile = true;
|
||||
node->data.pointer_type.is_volatile = true;
|
||||
}
|
||||
|
||||
node->data.addr_of_expr.op_expr = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
node->data.pointer_type.op_expr = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1216,8 +1215,17 @@ PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integ
|
||||
*/
|
||||
static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdAmpersand) {
|
||||
return ast_parse_addr_of(pc, token_index);
|
||||
if (token->id == TokenIdStar) {
|
||||
*token_index += 1;
|
||||
return ast_parse_pointer_type(pc, token_index, token);
|
||||
}
|
||||
if (token->id == TokenIdStarStar) {
|
||||
*token_index += 1;
|
||||
AstNode *child_node = ast_parse_pointer_type(pc, token_index, token);
|
||||
child_node->column += 1;
|
||||
AstNode *parent_node = ast_create_node(pc, NodeTypePointerType, token);
|
||||
parent_node->data.pointer_type.op_expr = child_node;
|
||||
return parent_node;
|
||||
}
|
||||
if (token->id == TokenIdKeywordTry) {
|
||||
return ast_parse_try_expr(pc, token_index);
|
||||
@@ -1234,13 +1242,12 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,
|
||||
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
|
||||
AstNode *parent_node = node;
|
||||
|
||||
AstNode *prefix_op_expr = ast_parse_error_set_expr(pc, token_index, true);
|
||||
node->data.prefix_op_expr.primary_expr = prefix_op_expr;
|
||||
node->data.prefix_op_expr.prefix_op = prefix_op;
|
||||
|
||||
return parent_node;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@@ -3121,9 +3128,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
||||
case NodeTypeErrorType:
|
||||
// none
|
||||
break;
|
||||
case NodeTypeAddrOfExpr:
|
||||
visit_field(&node->data.addr_of_expr.align_expr, visit, context);
|
||||
visit_field(&node->data.addr_of_expr.op_expr, visit, context);
|
||||
case NodeTypePointerType:
|
||||
visit_field(&node->data.pointer_type.align_expr, visit, context);
|
||||
visit_field(&node->data.pointer_type.op_expr, visit, context);
|
||||
break;
|
||||
case NodeTypeErrorSetDecl:
|
||||
visit_node_list(&node->data.err_set_decl.decls, visit, context);
|
||||
|
||||
@@ -276,11 +276,18 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod
|
||||
node);
|
||||
}
|
||||
|
||||
static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) {
|
||||
AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr);
|
||||
node->data.addr_of_expr.is_const = is_const;
|
||||
node->data.addr_of_expr.is_volatile = is_volatile;
|
||||
node->data.addr_of_expr.op_expr = child_node;
|
||||
static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node) {
|
||||
AstNode *node = trans_create_node(c, NodeTypePointerType);
|
||||
node->data.pointer_type.is_const = is_const;
|
||||
node->data.pointer_type.is_volatile = is_volatile;
|
||||
node->data.pointer_type.op_expr = child_node;
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *trans_create_node_addr_of(Context *c, AstNode *child_node) {
|
||||
AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
|
||||
node->data.prefix_op_expr.prefix_op = PrefixOpAddrOf;
|
||||
node->data.prefix_op_expr.primary_expr = child_node;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -848,7 +855,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
|
||||
return trans_create_node_prefix_op(c, PrefixOpMaybe, child_node);
|
||||
}
|
||||
|
||||
AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(),
|
||||
AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
|
||||
child_qt.isVolatileQualified(), child_node);
|
||||
return trans_create_node_prefix_op(c, PrefixOpMaybe, pointer_node);
|
||||
}
|
||||
@@ -1033,7 +1040,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
|
||||
emit_warning(c, source_loc, "unresolved array element type");
|
||||
return nullptr;
|
||||
}
|
||||
AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(),
|
||||
AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
|
||||
child_qt.isVolatileQualified(), child_type_node);
|
||||
return pointer_node;
|
||||
}
|
||||
@@ -1402,7 +1409,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
|
||||
// const _ref = &lhs;
|
||||
AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue);
|
||||
if (lhs == nullptr) return nullptr;
|
||||
AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
|
||||
AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);
|
||||
// TODO: avoid name collisions with generated variable names
|
||||
Buf* tmp_var_name = buf_create_from_str("_ref");
|
||||
AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
|
||||
@@ -1476,7 +1483,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
|
||||
// const _ref = &lhs;
|
||||
AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue);
|
||||
if (lhs == nullptr) return nullptr;
|
||||
AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
|
||||
AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);
|
||||
// TODO: avoid name collisions with generated variable names
|
||||
Buf* tmp_var_name = buf_create_from_str("_ref");
|
||||
AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
|
||||
@@ -1813,7 +1820,7 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
|
||||
// const _ref = &expr;
|
||||
AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue);
|
||||
if (expr == nullptr) return nullptr;
|
||||
AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr);
|
||||
AstNode *addr_of_expr = trans_create_node_addr_of(c, expr);
|
||||
// TODO: avoid name collisions with generated variable names
|
||||
Buf* ref_var_name = buf_create_from_str("_ref");
|
||||
AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr);
|
||||
@@ -1868,7 +1875,7 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
|
||||
// const _ref = &expr;
|
||||
AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue);
|
||||
if (expr == nullptr) return nullptr;
|
||||
AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr);
|
||||
AstNode *addr_of_expr = trans_create_node_addr_of(c, expr);
|
||||
// TODO: avoid name collisions with generated variable names
|
||||
Buf* ref_var_name = buf_create_from_str("_ref");
|
||||
AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr);
|
||||
@@ -1917,7 +1924,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
|
||||
AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
|
||||
if (value_node == nullptr)
|
||||
return value_node;
|
||||
return trans_create_node_addr_of(c, false, false, value_node);
|
||||
return trans_create_node_addr_of(c, value_node);
|
||||
}
|
||||
case UO_Deref:
|
||||
{
|
||||
@@ -4441,7 +4448,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
|
||||
} else if (first_tok->id == CTokIdAsterisk) {
|
||||
*tok_i += 1;
|
||||
|
||||
node = trans_create_node_addr_of(c, false, false, node);
|
||||
node = trans_create_node_ptr_type(c, false, false, node);
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user