aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp149
1 files changed, 120 insertions, 29 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index f516da8c15..e3ab55b72e 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -4347,8 +4347,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
IrInstruction *array_val = ir_build_load_ptr(irb, parent_scope, array_node, array_val_ptr);
- IrInstruction *array_type = ir_build_typeof(irb, parent_scope, array_node, array_val);
- IrInstruction *pointer_type = ir_build_to_ptr_type(irb, parent_scope, array_node, array_type);
+ IrInstruction *pointer_type = ir_build_to_ptr_type(irb, parent_scope, array_node, array_val);
IrInstruction *elem_var_type;
if (node->data.for_expr.elem_is_ptr) {
elem_var_type = pointer_type;
@@ -6887,6 +6886,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
+ case TypeTableEntryIdArgTuple:
if (!is_equality_cmp) {
ir_add_error_node(ira, source_node,
buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
@@ -7449,6 +7449,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
case TypeTableEntryIdFn:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdEnumTag:
+ case TypeTableEntryIdArgTuple:
// OK
break;
}
@@ -7520,21 +7521,35 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
{
AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i);
assert(param_decl_node->type == NodeTypeParamDecl);
- AstNode *param_type_node = param_decl_node->data.param_decl.type;
- TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node);
- if (param_type->id == TypeTableEntryIdInvalid)
- return false;
+ bool is_var_args = param_decl_node->data.param_decl.is_var_args;
+ bool arg_part_of_generic_id = false;
+ IrInstruction *casted_arg;
+ if (is_var_args) {
+ arg_part_of_generic_id = true;
+ casted_arg = arg;
+ } else {
+ AstNode *param_type_node = param_decl_node->data.param_decl.type;
+ TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node);
+ if (param_type->id == TypeTableEntryIdInvalid)
+ return false;
- IrInstruction *casted_arg = ir_implicit_cast(ira, arg, param_type);
- if (casted_arg->value.type->id == TypeTableEntryIdInvalid)
- return false;
+ bool is_var_type = (param_type->id == TypeTableEntryIdVar);
+ if (is_var_type) {
+ arg_part_of_generic_id = true;
+ casted_arg = arg;
+ } else {
+ casted_arg = ir_implicit_cast(ira, arg, param_type);
+ if (casted_arg->value.type->id == TypeTableEntryIdInvalid)
+ return false;
+ }
+ }
- bool inline_arg = param_decl_node->data.param_decl.is_inline;
- bool is_var_type = (param_type->id == TypeTableEntryIdVar);
+ bool comptime_arg = param_decl_node->data.param_decl.is_inline;
ConstExprValue *arg_val;
- if (inline_arg) {
+ if (comptime_arg) {
+ arg_part_of_generic_id = true;
arg_val = ir_resolve_const(ira, casted_arg, UndefBad);
if (!arg_val)
return false;
@@ -7544,26 +7559,41 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
} else {
arg_val = create_const_runtime(casted_arg->value.type);
}
+ if (arg_part_of_generic_id) {
+ generic_id->params[generic_id->param_count] = *arg_val;
+ generic_id->param_count += 1;
+ }
Buf *param_name = param_decl_node->data.param_decl.name;
- VariableTableEntry *var = add_variable(ira->codegen, param_decl_node,
- *child_scope, param_name, true, arg_val);
- var->value.depends_on_compile_var = true;
- *child_scope = var->child_scope;
+ if (is_var_args) {
+ if (!impl_fn->var_args_var) {
+ ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,
+ fn_type_id->param_count, fn_type_id->param_count + 1);
+ VariableTableEntry *var = add_variable(ira->codegen, param_decl_node,
+ *child_scope, param_name, true, var_args_val);
+ var->value.depends_on_compile_var = true;
+ *child_scope = var->child_scope;
+ impl_fn->var_args_var = var;
+ }
+ impl_fn->var_args_var->value.data.x_arg_tuple.end_index = fn_type_id->param_count + 1;
- if (inline_arg || is_var_type) {
- generic_id->params[generic_id->param_count] = *arg_val;
- generic_id->param_count += 1;
+ } else {
+ VariableTableEntry *var = add_variable(ira->codegen, param_decl_node,
+ *child_scope, param_name, true, arg_val);
+ var->value.depends_on_compile_var = true;
+ *child_scope = var->child_scope;
+ var->shadowable = !comptime_arg;
+
+ *next_proto_i += 1;
}
- if (!inline_arg) {
- if (type_requires_comptime(var->value.type)) {
- ir_add_error(ira, arg,
- buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&var->value.type->name)));
+
+ if (!comptime_arg) {
+ if (type_requires_comptime(casted_arg->value.type)) {
+ ir_add_error(ira, casted_arg,
+ buf_sprintf("parameter of type '%s' requires comptime", buf_ptr(&casted_arg->value.type->name)));
return false;
}
- var->shadowable = true;
-
casted_args[fn_type_id->param_count] = casted_arg;
FnTypeParamInfo *param_info = &fn_type_id->param_info[fn_type_id->param_count];
param_info->type = casted_arg->value.type;
@@ -7571,7 +7601,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
impl_fn->param_source_nodes[fn_type_id->param_count] = param_decl_node;
fn_type_id->param_count += 1;
}
- *next_proto_i += 1;
+
return true;
}
@@ -7682,6 +7712,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
FnTypeId inst_fn_type_id = {0};
init_fn_type_id(&inst_fn_type_id, fn_proto_node);
inst_fn_type_id.param_count = 0;
+ inst_fn_type_id.is_var_args = false;
// TODO maybe GenericFnTypeId can be replaced with using the child_scope directly
// as the key in generic_table
@@ -7918,6 +7949,7 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
case TypeTableEntryIdBlock:
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdVar:
+ case TypeTableEntryIdArgTuple:
ir_add_error_node(ira, un_op_instruction->base.source_node,
buf_sprintf("unable to wrap type '%s' in error type", buf_ptr(&meta_type->name)));
// TODO if meta_type is type decl, add note pointing to type decl declaration
@@ -7990,6 +8022,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdEnumTag:
+ case TypeTableEntryIdArgTuple:
{
ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
value->value.depends_on_compile_var);
@@ -8327,6 +8360,30 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
return_type = array_type;
} else if (is_slice(array_type)) {
return_type = array_type->data.structure.fields[0].type_entry;
+ } else if (array_type->id == TypeTableEntryIdArgTuple) {
+ ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
+ if (!ptr_val)
+ return ira->codegen->builtin_types.entry_invalid;
+ ConstExprValue *args_val = const_ptr_pointee(ptr_val);
+ size_t start = args_val->data.x_arg_tuple.start_index;
+ size_t end = args_val->data.x_arg_tuple.end_index;
+ ConstExprValue *elem_index_val = ir_resolve_const(ira, elem_index, UndefBad);
+ if (!elem_index_val)
+ return ira->codegen->builtin_types.entry_invalid;
+ size_t index = bignum_to_twos_complement(&elem_index_val->data.x_bignum);
+ size_t len = end - start;
+ if (index >= len) {
+ ir_add_error(ira, &elem_ptr_instruction->base,
+ buf_sprintf("index %zu outside argument list of size %zu", index, len));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ size_t abs_index = start + index;
+ FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
+ assert(fn_entry);
+ VariableTableEntry *var = fn_entry->variable_list.at(abs_index);
+ bool depends_on_compile_var = array_ptr->value.depends_on_compile_var ||
+ elem_index->value.depends_on_compile_var;
+ return ir_analyze_var_ptr(ira, &elem_ptr_instruction->base, var, true, depends_on_compile_var);
} else {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
@@ -8582,6 +8639,29 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
buf_ptr(&container_type->name)));
return ira->codegen->builtin_types.entry_invalid;
}
+ } else if (container_type->id == TypeTableEntryIdArgTuple) {
+ ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
+ if (!container_ptr_val)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ assert(container_ptr->value.type->id == TypeTableEntryIdPointer);
+ ConstExprValue *child_val = const_ptr_pointee(container_ptr_val);
+
+ if (buf_eql_str(field_name, "len")) {
+ ConstExprValue *len_val = allocate<ConstExprValue>(1);
+ size_t len = child_val->data.x_arg_tuple.end_index - child_val->data.x_arg_tuple.start_index;
+ init_const_usize(ira->codegen, len_val, len);
+
+ TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize;
+ bool ptr_is_const = true;
+ return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,
+ usize, false, ConstPtrSpecialNone, ptr_is_const);
+ } else {
+ ir_add_error_node(ira, source_node,
+ buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
+ buf_ptr(&container_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
} else if (container_type->id == TypeTableEntryIdMetaType) {
ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
if (!container_ptr_val)
@@ -8830,6 +8910,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
case TypeTableEntryIdFn:
case TypeTableEntryIdTypeDecl:
case TypeTableEntryIdEnumTag:
+ case TypeTableEntryIdArgTuple:
{
ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base, false);
// TODO depends_on_compile_var should be set based on whether the type of the expression
@@ -8847,8 +8928,8 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
static TypeTableEntry *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
IrInstructionToPtrType *to_ptr_type_instruction)
{
- IrInstruction *type_value = to_ptr_type_instruction->value->other;
- TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
+ IrInstruction *value = to_ptr_type_instruction->value->other;
+ TypeTableEntry *type_entry = value->value.type;
if (type_entry->id == TypeTableEntryIdInvalid)
return type_entry;
@@ -8857,6 +8938,11 @@ static TypeTableEntry *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
ptr_type = get_pointer_to_type(ira->codegen, type_entry->data.array.child_type, false);
} else if (is_slice(type_entry)) {
ptr_type = type_entry->data.structure.fields[0].type_entry;
+ } else if (type_entry->id == TypeTableEntryIdArgTuple) {
+ ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);
+ if (!arg_tuple_val)
+ return ira->codegen->builtin_types.entry_invalid;
+ zig_panic("TODO for loop on var args");
} else {
ir_add_error_node(ira, to_ptr_type_instruction->base.source_node,
buf_sprintf("expected array type, found '%s'", buf_ptr(&type_entry->name)));
@@ -8864,7 +8950,7 @@ static TypeTableEntry *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
}
ConstExprValue *out_val = ir_build_const_from(ira, &to_ptr_type_instruction->base,
- type_value->value.depends_on_compile_var);
+ value->value.depends_on_compile_var);
out_val->data.x_type = ptr_type;
return ira->codegen->builtin_types.entry_type;
}
@@ -9027,6 +9113,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
case TypeTableEntryIdBlock:
+ case TypeTableEntryIdArgTuple:
ir_add_error_node(ira, slice_type_instruction->base.source_node,
buf_sprintf("slice of type '%s' not allowed", buf_ptr(&resolved_child_type->name)));
// TODO if this is a typedecl, add error note showing the declaration of the type decl
@@ -9118,6 +9205,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
case TypeTableEntryIdBlock:
+ case TypeTableEntryIdArgTuple:
ir_add_error_node(ira, array_type_instruction->base.source_node,
buf_sprintf("array of type '%s' not allowed", buf_ptr(&child_type->name)));
// TODO if this is a typedecl, add error note showing the declaration of the type decl
@@ -9214,6 +9302,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
case TypeTableEntryIdMetaType:
case TypeTableEntryIdFn:
case TypeTableEntryIdNamespace:
+ case TypeTableEntryIdArgTuple:
ir_add_error_node(ira, size_of_instruction->base.source_node,
buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
// TODO if this is a typedecl, add error note showing the declaration of the type decl
@@ -9559,6 +9648,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
case TypeTableEntryIdUnion:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
+ case TypeTableEntryIdArgTuple:
ir_add_error(ira, &switch_target_instruction->base,
buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
// TODO if this is a typedecl, add error note showing the declaration of the type decl
@@ -10075,6 +10165,7 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
+ case TypeTableEntryIdArgTuple:
{
const char *err_format = is_max ?
"no max value available for type '%s'" :