aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp9
-rw-r--r--src/analyze.cpp24
-rw-r--r--src/codegen.cpp2
-rw-r--r--src/ir.cpp131
-rw-r--r--src/ir_print.cpp14
5 files changed, 173 insertions, 7 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index bbd8df4b70..1e2ff3aaa4 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1096,6 +1096,7 @@ enum BuiltinFnId {
BuiltinFnIdCUndef,
BuiltinFnIdCompileVar,
BuiltinFnIdCompileErr,
+ BuiltinFnIdCompileLog,
BuiltinFnIdGeneratedCode,
BuiltinFnIdCtz,
BuiltinFnIdClz,
@@ -1541,6 +1542,7 @@ enum IrInstructionId {
IrInstructionIdMinValue,
IrInstructionIdMaxValue,
IrInstructionIdCompileErr,
+ IrInstructionIdCompileLog,
IrInstructionIdErrName,
IrInstructionIdEmbedFile,
IrInstructionIdCmpxchg,
@@ -1993,6 +1995,13 @@ struct IrInstructionCompileErr {
IrInstruction *msg;
};
+struct IrInstructionCompileLog {
+ IrInstruction base;
+
+ size_t msg_count;
+ IrInstruction **msg_list;
+};
+
struct IrInstructionErrName {
IrInstruction base;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 7fd1fee675..984fa32a83 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -3439,7 +3439,8 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
void render_const_value(Buf *buf, ConstExprValue *const_val) {
switch (const_val->special) {
case ConstValSpecialRuntime:
- zig_unreachable();
+ buf_appendf(buf, "(runtime value)");
+ return;
case ConstValSpecialUndef:
buf_appendf(buf, "undefined");
return;
@@ -3522,7 +3523,28 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
}
case TypeTableEntryIdArray:
{
+ TypeTableEntry *child_type = canon_type->data.array.child_type;
uint64_t len = canon_type->data.array.len;
+
+ // if it's []u8, assume UTF-8 and output a string
+ if (child_type->id == TypeTableEntryIdInt &&
+ child_type->data.integral.bit_count == 8 &&
+ !child_type->data.integral.is_signed)
+ {
+ buf_append_char(buf, '"');
+ for (uint64_t i = 0; i < len; i += 1) {
+ ConstExprValue *child_value = &const_val->data.x_array.elements[i];
+ uint64_t x = child_value->data.x_bignum.data.x_uint;
+ if (x == '"') {
+ buf_append_str(buf, "\\\"");
+ } else {
+ buf_append_char(buf, x);
+ }
+ }
+ buf_append_char(buf, '"');
+ return;
+ }
+
buf_appendf(buf, "%s{", buf_ptr(&canon_type->name));
for (uint64_t i = 0; i < len; i += 1) {
if (i != 0)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index a7ed6cd704..5849bf8e6d 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2377,6 +2377,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdMinValue:
case IrInstructionIdMaxValue:
case IrInstructionIdCompileErr:
+ case IrInstructionIdCompileLog:
case IrInstructionIdArrayLen:
case IrInstructionIdImport:
case IrInstructionIdCImport:
@@ -3791,6 +3792,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdDivExact, "divExact", 2);
create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2);
create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
+ create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdIntType, "intType", 2);
create_builtin_fn(g, BuiltinFnIdUnreachable, "unreachable", 0);
create_builtin_fn(g, BuiltinFnIdSetFnTest, "setFnTest", 1);
diff --git a/src/ir.cpp b/src/ir.cpp
index e89f89f89c..7af27ec765 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -375,6 +375,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileErr *) {
return IrInstructionIdCompileErr;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileLog *) {
+ return IrInstructionIdCompileLog;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionErrName *) {
return IrInstructionIdErrName;
}
@@ -1510,6 +1514,20 @@ static IrInstruction *ir_build_compile_err(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
+static IrInstruction *ir_build_compile_log(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ size_t msg_count, IrInstruction **msg_list)
+{
+ IrInstructionCompileLog *instruction = ir_build_instruction<IrInstructionCompileLog>(irb, scope, source_node);
+ instruction->msg_count = msg_count;
+ instruction->msg_list = msg_list;
+
+ for (size_t i = 0; i < msg_count; i += 1) {
+ ir_ref_instruction(msg_list[i], irb->current_basic_block);
+ }
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_err_name(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
IrInstructionErrName *instruction = ir_build_instruction<IrInstructionErrName>(irb, scope, source_node);
instruction->value = value;
@@ -2461,6 +2479,12 @@ static IrInstruction *ir_instruction_compileerr_get_dep(IrInstructionCompileErr
}
}
+static IrInstruction *ir_instruction_compilelog_get_dep(IrInstructionCompileLog *instruction, size_t index) {
+ if (index < instruction->msg_count)
+ return instruction->msg_list[index];
+ return nullptr;
+}
+
static IrInstruction *ir_instruction_errname_get_dep(IrInstructionErrName *instruction, size_t index) {
switch (index) {
case 0: return instruction->value;
@@ -2848,6 +2872,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
return ir_instruction_maxvalue_get_dep((IrInstructionMaxValue *) instruction, index);
case IrInstructionIdCompileErr:
return ir_instruction_compileerr_get_dep((IrInstructionCompileErr *) instruction, index);
+ case IrInstructionIdCompileLog:
+ return ir_instruction_compilelog_get_dep((IrInstructionCompileLog *) instruction, index);
case IrInstructionIdErrName:
return ir_instruction_errname_get_dep((IrInstructionErrName *) instruction, index);
case IrInstructionIdEmbedFile:
@@ -3767,7 +3793,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
BuiltinFnEntry *builtin_fn = entry->value;
size_t actual_param_count = node->data.fn_call_expr.params.length;
- if (builtin_fn->param_count != actual_param_count) {
+ if (builtin_fn->param_count != SIZE_MAX && builtin_fn->param_count != actual_param_count) {
add_node_error(irb->codegen, node,
buf_sprintf("expected %zu arguments, found %zu",
builtin_fn->param_count, actual_param_count));
@@ -3958,6 +3984,19 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_build_compile_err(irb, scope, node, arg0_value);
}
+ case BuiltinFnIdCompileLog:
+ {
+ IrInstruction **args = allocate<IrInstruction*>(actual_param_count);
+
+ for (size_t i = 0; i < actual_param_count; i += 1) {
+ AstNode *arg_node = node->data.fn_call_expr.params.at(i);
+ args[i] = ir_gen_node(irb, arg_node, scope);
+ if (args[i] == irb->codegen->invalid_instruction)
+ return irb->codegen->invalid_instruction;
+ }
+
+ return ir_build_compile_log(irb, scope, node, actual_param_count, args);
+ }
case BuiltinFnIdErrName:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -5254,7 +5293,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
return irb->codegen->invalid_instruction;
IrInstruction *start_value = ir_gen_node(irb, start_node, scope);
- if (ptr_value == irb->codegen->invalid_instruction)
+ if (start_value == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
IrInstruction *end_value;
@@ -5800,6 +5839,16 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
}
}
+ // implicit typed number to integer or float literal.
+ // works when the number is known
+ if (value->value.special == ConstValSpecialStatic) {
+ if (actual_type->id == TypeTableEntryIdInt && expected_type->id == TypeTableEntryIdNumLitInt) {
+ return ImplicitCastMatchResultYes;
+ } else if (actual_type->id == TypeTableEntryIdFloat && expected_type->id == TypeTableEntryIdNumLitFloat) {
+ return ImplicitCastMatchResultYes;
+ }
+ }
+
// implicit undefined literal to anything
if (actual_type->id == TypeTableEntryIdUndefLit) {
return ImplicitCastMatchResultYes;
@@ -6654,6 +6703,19 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
return result;
}
+static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *target, TypeTableEntry *wanted_type)
+{
+ ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, wanted_type, true);
+ bignum_init_bignum(&result->value.data.x_bignum, &val->data.x_bignum);
+ return result;
+}
+
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
TypeTableEntry *wanted_type, IrInstruction *value)
{
@@ -6858,6 +6920,15 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
+ // explicit cast from typed number to integer or float literal.
+ // works when the number is known at compile time
+ if (instr_is_comptime(value) &&
+ ((actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdNumLitInt) ||
+ (actual_type->id == TypeTableEntryIdFloat && wanted_type->id == TypeTableEntryIdNumLitFloat)))
+ {
+ return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);
+ }
+
// explicit cast from %void to integer type which can fit it
bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion &&
!type_has_bits(actual_type->data.error.child_type);
@@ -7552,6 +7623,13 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
op1_array_val = op1_val->data.x_ptr.base_ptr;
op1_array_index = op1_val->data.x_ptr.index;
op1_array_end = op1_array_val->data.x_array.size - 1;
+ } else if (is_slice(op1_canon_type)) {
+ TypeTableEntry *ptr_type = op1_canon_type->data.structure.fields[slice_ptr_index].type_entry;
+ child_type = ptr_type->data.pointer.child_type;
+ ConstExprValue *ptr_val = &op1_val->data.x_struct.fields[slice_ptr_index];
+ op1_array_val = ptr_val->data.x_ptr.base_ptr;
+ op1_array_index = ptr_val->data.x_ptr.index;
+ op1_array_end = op1_array_val->data.x_array.size;
} else {
ir_add_error(ira, op1,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
@@ -7585,6 +7663,18 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
op2_array_val = op2_val->data.x_ptr.base_ptr;
op2_array_index = op2_val->data.x_ptr.index;
op2_array_end = op2_array_val->data.x_array.size - 1;
+ } else if (is_slice(op2_canon_type)) {
+ TypeTableEntry *ptr_type = op2_canon_type->data.structure.fields[slice_ptr_index].type_entry;
+ if (ptr_type->data.pointer.child_type != child_type) {
+ ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
+ buf_ptr(&child_type->name),
+ buf_ptr(&op2->value.type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];
+ op2_array_val = ptr_val->data.x_ptr.base_ptr;
+ op2_array_index = ptr_val->data.x_ptr.index;
+ op2_array_end = op2_array_val->data.x_array.size;
} else {
ir_add_error(ira, op2,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
@@ -9177,7 +9267,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
}
} else {
ir_add_error(ira, &field_ptr_instruction->base,
- buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name)));
+ buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name)));
return ira->codegen->builtin_types.entry_invalid;
}
} else if (container_type->id == TypeTableEntryIdNamespace) {
@@ -9528,6 +9618,12 @@ static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,
if (!target_val)
return ira->codegen->builtin_types.entry_invalid;
+ if (ira->new_irb.exec->is_inline) {
+ // ignore setDebugSafety when running functions at compile time
+ ir_build_const_from(ira, &set_debug_safety_instruction->base, false);
+ return ira->codegen->builtin_types.entry_void;
+ }
+
bool *safety_off_ptr;
AstNode **safety_set_node_ptr;
if (target_type->id == TypeTableEntryIdBlock) {
@@ -10703,6 +10799,26 @@ static TypeTableEntry *ir_analyze_instruction_compile_err(IrAnalyze *ira,
return ira->codegen->builtin_types.entry_invalid;
}
+static TypeTableEntry *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstructionCompileLog *instruction) {
+ Buf buf = BUF_INIT;
+ fprintf(stderr, "| ");
+ for (size_t i = 0; i < instruction->msg_count; i += 1) {
+ IrInstruction *msg = instruction->msg_list[i]->other;
+ if (msg->value.type->id == TypeTableEntryIdInvalid)
+ return ira->codegen->builtin_types.entry_invalid;
+ buf_resize(&buf, 0);
+ render_const_value(&buf, &msg->value);
+ const char *comma_str = (i != 0) ? ", " : "";
+ fprintf(stderr, "%s%s", comma_str, buf_ptr(&buf));
+ }
+ fprintf(stderr, "\n");
+
+ ir_add_error(ira, &instruction->base, buf_sprintf("found compile log statement"));
+
+ ir_build_const_from(ira, &instruction->base, false);
+ return ira->codegen->builtin_types.entry_void;
+}
+
static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErrName *instruction) {
IrInstruction *value = instruction->value->other;
if (value->value.type->id == TypeTableEntryIdInvalid)
@@ -11602,13 +11718,13 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst
out_val->data.x_bool = bignum_add(dest_bignum, op1_bignum, op2_bignum);
break;
case IrOverflowOpSub:
- out_val->data.x_bool = bignum_add(dest_bignum, op1_bignum, op2_bignum);
+ out_val->data.x_bool = bignum_sub(dest_bignum, op1_bignum, op2_bignum);
break;
case IrOverflowOpMul:
- out_val->data.x_bool = bignum_add(dest_bignum, op1_bignum, op2_bignum);
+ out_val->data.x_bool = bignum_mul(dest_bignum, op1_bignum, op2_bignum);
break;
case IrOverflowOpShl:
- out_val->data.x_bool = bignum_add(dest_bignum, op1_bignum, op2_bignum);
+ out_val->data.x_bool = bignum_shl(dest_bignum, op1_bignum, op2_bignum);
break;
}
if (!bignum_fits_in_bits(dest_bignum, canon_type->data.integral.bit_count,
@@ -12007,6 +12123,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_max_value(ira, (IrInstructionMaxValue *)instruction);
case IrInstructionIdCompileErr:
return ir_analyze_instruction_compile_err(ira, (IrInstructionCompileErr *)instruction);
+ case IrInstructionIdCompileLog:
+ return ir_analyze_instruction_compile_log(ira, (IrInstructionCompileLog *)instruction);
case IrInstructionIdErrName:
return ir_analyze_instruction_err_name(ira, (IrInstructionErrName *)instruction);
case IrInstructionIdTypeName:
@@ -12164,6 +12282,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdSetDebugSafety:
case IrInstructionIdImport:
case IrInstructionIdCompileErr:
+ case IrInstructionIdCompileLog:
case IrInstructionIdCImport:
case IrInstructionIdCInclude:
case IrInstructionIdCDefine:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index a378df04b5..3c9e53662e 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -532,6 +532,17 @@ static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruct
fprintf(irp->f, ")");
}
+static void ir_print_compile_log(IrPrint *irp, IrInstructionCompileLog *instruction) {
+ fprintf(irp->f, "@compileLog(");
+ for (size_t i = 0; i < instruction->msg_count; i += 1) {
+ if (i != 0)
+ fprintf(irp->f, ",");
+ IrInstruction *msg = instruction->msg_list[i];
+ ir_print_other_instruction(irp, msg);
+ }
+ fprintf(irp->f, ")");
+}
+
static void ir_print_err_name(IrPrint *irp, IrInstructionErrName *instruction) {
fprintf(irp->f, "@errorName(");
ir_print_other_instruction(irp, instruction->value);
@@ -990,6 +1001,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdCompileErr:
ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction);
break;
+ case IrInstructionIdCompileLog:
+ ir_print_compile_log(irp, (IrInstructionCompileLog *)instruction);
+ break;
case IrInstructionIdErrName:
ir_print_err_name(irp, (IrInstructionErrName *)instruction);
break;