Commit bf7cde62c5
Changed files (6)
src/all_types.hpp
@@ -1449,6 +1449,7 @@ enum IrInstructionId {
IrInstructionIdToPtrType,
IrInstructionIdPtrTypeChild,
IrInstructionIdSetFnTest,
+ IrInstructionIdSetDebugSafety,
IrInstructionIdArrayType,
IrInstructionIdSliceType,
IrInstructionIdAsm,
@@ -1705,6 +1706,13 @@ struct IrInstructionSetFnTest {
IrInstruction *is_test;
};
+struct IrInstructionSetDebugSafety {
+ IrInstruction base;
+
+ IrInstruction *scope_value;
+ IrInstruction *debug_safety_on;
+};
+
struct IrInstructionArrayType {
IrInstruction base;
src/ast_render.cpp
@@ -669,6 +669,17 @@ static void render_node(AstRender *ar, AstNode *node) {
render_node(ar, node->data.while_expr.body);
break;
}
+ case NodeTypeThisLiteral:
+ {
+ fprintf(ar->f, "this");
+ break;
+ }
+ case NodeTypeBoolLiteral:
+ {
+ const char *bool_str = node->data.bool_literal.value ? "true" : "false";
+ fprintf(ar->f, "%s", bool_str);
+ break;
+ }
case NodeTypeFnDecl:
case NodeTypeParamDecl:
case NodeTypeErrorValueDecl:
@@ -677,10 +688,8 @@ static void render_node(AstRender *ar, AstNode *node) {
case NodeTypeStructField:
case NodeTypeStructValueField:
case NodeTypeUse:
- case NodeTypeBoolLiteral:
case NodeTypeNullLiteral:
case NodeTypeZeroesLiteral:
- case NodeTypeThisLiteral:
case NodeTypeIfBoolExpr:
case NodeTypeIfVarExpr:
case NodeTypeForExpr:
src/codegen.cpp
@@ -1681,6 +1681,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdPtrTypeChild:
case IrInstructionIdFieldPtr:
case IrInstructionIdSetFnTest:
+ case IrInstructionIdSetDebugSafety:
case IrInstructionIdArrayType:
case IrInstructionIdSliceType:
zig_unreachable();
src/ir.cpp
@@ -201,6 +201,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) {
return IrInstructionIdSetFnTest;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) {
+ return IrInstructionIdSetDebugSafety;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
return IrInstructionIdArrayType;
}
@@ -786,6 +790,19 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node,
return &instruction->base;
}
+static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, AstNode *source_node,
+ IrInstruction *scope_value, IrInstruction *debug_safety_on)
+{
+ IrInstructionSetDebugSafety *instruction = ir_build_instruction<IrInstructionSetDebugSafety>(irb, source_node);
+ instruction->scope_value = scope_value;
+ instruction->debug_safety_on = debug_safety_on;
+
+ ir_ref_instruction(scope_value);
+ ir_ref_instruction(debug_safety_on);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_array_type(IrBuilder *irb, AstNode *source_node, IrInstruction *size,
IrInstruction *child_type)
{
@@ -1291,6 +1308,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
return ir_build_set_fn_test(irb, node, arg0_value, arg1_value);
}
+ case BuiltinFnIdSetDebugSafety:
+ {
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context);
+ if (arg0_value == irb->codegen->invalid_instruction)
+ return arg0_value;
+
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
+ IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, node->block_context);
+ if (arg1_value == irb->codegen->invalid_instruction)
+ return arg1_value;
+
+ return ir_build_set_debug_safety(irb, node, arg0_value, arg1_value);
+ }
case BuiltinFnIdMemcpy:
case BuiltinFnIdMemset:
case BuiltinFnIdSizeof:
@@ -1325,7 +1356,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
case BuiltinFnIdSetFnVisible:
case BuiltinFnIdSetFnStaticEval:
case BuiltinFnIdSetFnNoInline:
- case BuiltinFnIdSetDebugSafety:
zig_panic("TODO IR gen more builtin functions");
}
zig_unreachable();
@@ -2260,6 +2290,15 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value
return const_val->data.x_type;
}
+static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) {
+ if (value->static_value.special != ConstValSpecialStatic) {
+ add_node_error(ira->codegen, value->source_node,
+ buf_sprintf("unable to evaluate constant expression"));
+ return nullptr;
+ }
+ return &value->static_value;
+}
+
static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out) {
if (bool_value == ira->codegen->invalid_instruction)
return false;
@@ -2273,12 +2312,9 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out
return false;
}
- ConstExprValue *const_val = &bool_value->static_value;
- if (const_val->special == ConstValSpecialRuntime) {
- add_node_error(ira->codegen, bool_value->source_node,
- buf_sprintf("unable to evaluate constant expression"));
+ ConstExprValue *const_val = ir_resolve_const(ira, bool_value);
+ if (!const_val)
return false;
- }
*out = const_val->data.x_bool;
return true;
@@ -4027,12 +4063,67 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira,
}
fn_entry->fn_test_set_node = source_node;
- ira->codegen->test_fn_count += 1;
+ if (fn_entry->is_test)
+ ira->codegen->test_fn_count += 1;
ir_build_const_from(ira, &set_fn_test_instruction->base, false);
return ira->codegen->builtin_types.entry_void;
}
+static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,
+ IrInstructionSetDebugSafety *set_debug_safety_instruction)
+{
+ IrInstruction *target_instruction = set_debug_safety_instruction->scope_value->other;
+ TypeTableEntry *target_type = target_instruction->type_entry;
+ if (target_type->id == TypeTableEntryIdInvalid)
+ return ira->codegen->builtin_types.entry_invalid;
+ ConstExprValue *target_val = ir_resolve_const(ira, target_instruction);
+ if (!target_val)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ BlockContext *target_context;
+ if (target_type->id == TypeTableEntryIdBlock) {
+ target_context = target_val->data.x_block;
+ } else if (target_type->id == TypeTableEntryIdFn) {
+ target_context = target_val->data.x_fn->fn_def_node->data.fn_def.block_context;
+ } else if (target_type->id == TypeTableEntryIdMetaType) {
+ TypeTableEntry *type_arg = target_val->data.x_type;
+ if (type_arg->id == TypeTableEntryIdStruct) {
+ target_context = type_arg->data.structure.block_context;
+ } else if (type_arg->id == TypeTableEntryIdEnum) {
+ target_context = type_arg->data.enumeration.block_context;
+ } else if (type_arg->id == TypeTableEntryIdUnion) {
+ target_context = type_arg->data.unionation.block_context;
+ } else {
+ add_node_error(ira->codegen, target_instruction->source_node,
+ buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ } else {
+ add_node_error(ira->codegen, target_instruction->source_node,
+ buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ IrInstruction *debug_safety_on_value = set_debug_safety_instruction->debug_safety_on->other;
+ bool want_debug_safety;
+ if (!ir_resolve_bool(ira, debug_safety_on_value, &want_debug_safety))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ AstNode *source_node = set_debug_safety_instruction->base.source_node;
+ if (target_context->safety_set_node) {
+ ErrorMsg *msg = add_node_error(ira->codegen, source_node,
+ buf_sprintf("function test attribute set twice"));
+ add_error_note(ira->codegen, msg, target_context->safety_set_node, buf_sprintf("first set here"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ target_context->safety_set_node = source_node;
+ target_context->safety_off = !want_debug_safety;
+
+ ir_build_const_from(ira, &set_debug_safety_instruction->base, false);
+ return ira->codegen->builtin_types.entry_void;
+}
+
static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
IrInstructionSliceType *slice_type_instruction)
{
@@ -4164,6 +4255,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
case IrInstructionIdSetFnTest:
return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
+ case IrInstructionIdSetDebugSafety:
+ return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction);
case IrInstructionIdSliceType:
return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction);
case IrInstructionIdAsm:
@@ -4257,6 +4350,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdReturn:
case IrInstructionIdUnreachable:
case IrInstructionIdSetFnTest:
+ case IrInstructionIdSetDebugSafety:
return true;
case IrInstructionIdPhi:
case IrInstructionIdUnOp:
@@ -4854,64 +4948,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
// return g->builtin_types.entry_void;
//}
//
-//static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import,
-// BlockContext *parent_context, AstNode *node)
-//{
-// AstNode **target_node = &node->data.fn_call_expr.params.at(0);
-// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
-//
-// TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node);
-// BlockContext *target_context;
-// ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val;
-// if (target_type->id == TypeTableEntryIdInvalid) {
-// return g->builtin_types.entry_invalid;
-// }
-// if (!const_val->ok) {
-// add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression"));
-// return g->builtin_types.entry_invalid;
-// }
-// if (target_type->id == TypeTableEntryIdBlock) {
-// target_context = const_val->data.x_block;
-// } else if (target_type->id == TypeTableEntryIdFn) {
-// target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context;
-// } else if (target_type->id == TypeTableEntryIdMetaType) {
-// TypeTableEntry *type_arg = const_val->data.x_type;
-// if (type_arg->id == TypeTableEntryIdStruct) {
-// target_context = type_arg->data.structure.block_context;
-// } else if (type_arg->id == TypeTableEntryIdEnum) {
-// target_context = type_arg->data.enumeration.block_context;
-// } else if (type_arg->id == TypeTableEntryIdUnion) {
-// target_context = type_arg->data.unionation.block_context;
-// } else {
-// add_node_error(g, *target_node,
-// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
-// return g->builtin_types.entry_invalid;
-// }
-// } else {
-// add_node_error(g, *target_node,
-// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
-// return g->builtin_types.entry_invalid;
-// }
-//
-// bool want_debug_safety;
-// bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety);
-// if (!ok) {
-// return g->builtin_types.entry_invalid;
-// }
-//
-// if (target_context->safety_set_node) {
-// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice"));
-// add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here"));
-// return g->builtin_types.entry_invalid;
-// }
-// target_context->safety_set_node = node;
-//
-// target_context->safety_off = !want_debug_safety;
-//
-// return g->builtin_types.entry_void;
-//}
-
-
//static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
// TypeTableEntry *expected_type, AstNode *node)
//{
@@ -5215,8 +5251,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
// return analyze_set_fn_static_eval(g, import, context, node);
// case BuiltinFnIdSetFnVisible:
// return analyze_set_fn_visible(g, import, context, node);
-// case BuiltinFnIdSetDebugSafety:
-// return analyze_set_debug_safety(g, import, context, node);
// }
// zig_unreachable();
//}
src/ir_print.cpp
@@ -409,6 +409,14 @@ static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instructi
fprintf(irp->f, ")");
}
+static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) {
+ fprintf(irp->f, "@setDebugSafety(");
+ ir_print_other_instruction(irp, instruction->scope_value);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->debug_safety_on);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instruction) {
fprintf(irp->f, "[");
ir_print_other_instruction(irp, instruction->size);
@@ -541,6 +549,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdSetFnTest:
ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
break;
+ case IrInstructionIdSetDebugSafety:
+ ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction);
+ break;
case IrInstructionIdArrayType:
ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
break;
test/self_hosted2.zig
@@ -1,13 +1,41 @@
-fn add(a: i32, b: i32) -> i32 {
- a + b
+pub const SYS_write = 1;
+pub const SYS_exit = 60;
+pub const stdout_fileno = 1;
+const text = "hello\n";
+
+export nakedcc fn _start() -> unreachable {
+ myMain();
+}
+
+fn myMain() -> unreachable {
+ write(stdout_fileno, &text[0], text.len);
+ exit(0);
}
-fn assert(ok: bool) {
- if (!ok) @unreachable();
+pub inline fn syscall1(number: usize, arg1: usize) -> usize {
+ asm volatile ("syscall"
+ : [ret] "={rax}" (-> usize)
+ : [number] "{rax}" (number),
+ [arg1] "{rdi}" (arg1)
+ : "rcx", "r11")
}
-fn testAdd() {
- @setFnTest(this, true);
+pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize {
+ asm volatile ("syscall"
+ : [ret] "={rax}" (-> usize)
+ : [number] "{rax}" (number),
+ [arg1] "{rdi}" (arg1),
+ [arg2] "{rsi}" (arg2),
+ [arg3] "{rdx}" (arg3)
+ : "rcx", "r11")
+}
- assert(add(2, 3) == 5);
+pub fn write(fd: i32, buf: &const u8, count: usize) -> usize {
+ syscall3(SYS_write, usize(fd), usize(buf), count)
}
+
+pub fn exit(status: i32) -> unreachable {
+ syscall1(SYS_exit, usize(status));
+ @unreachable()
+}
+