authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-18 20:57:27-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-18 20:57:27-05:00
logbf7cde62c52b370f953db2cd6167a156771d8343
tree4f11799818dc793db8431332537b010620aad55f
parented31ae8867fd2d7b5274c6b127d42360b48fc49c

IR: support setDebugSafety builtin function


6 files changed, 167 insertions(+), 76 deletions(-)

src/all_types.hpp+8
...@@ -1449,6 +1449,7 @@ enum IrInstructionId {...@@ -1449,6 +1449,7 @@ enum IrInstructionId {
1449 IrInstructionIdToPtrType,1449 IrInstructionIdToPtrType,
1450 IrInstructionIdPtrTypeChild,1450 IrInstructionIdPtrTypeChild,
1451 IrInstructionIdSetFnTest,1451 IrInstructionIdSetFnTest,
1452 IrInstructionIdSetDebugSafety,
1452 IrInstructionIdArrayType,1453 IrInstructionIdArrayType,
1453 IrInstructionIdSliceType,1454 IrInstructionIdSliceType,
1454 IrInstructionIdAsm,1455 IrInstructionIdAsm,
...@@ -1705,6 +1706,13 @@ struct IrInstructionSetFnTest {...@@ -1705,6 +1706,13 @@ struct IrInstructionSetFnTest {
1705 IrInstruction *is_test;1706 IrInstruction *is_test;
1706};1707};
17071708
1709struct IrInstructionSetDebugSafety {
1710 IrInstruction base;
1711
1712 IrInstruction *scope_value;
1713 IrInstruction *debug_safety_on;
1714};
1715
1708struct IrInstructionArrayType {1716struct IrInstructionArrayType {
1709 IrInstruction base;1717 IrInstruction base;
17101718
src/ast_render.cpp+11-2
...@@ -669,6 +669,17 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -669,6 +669,17 @@ static void render_node(AstRender *ar, AstNode *node) {
669 render_node(ar, node->data.while_expr.body);669 render_node(ar, node->data.while_expr.body);
670 break;670 break;
671 }671 }
672 case NodeTypeThisLiteral:
673 {
674 fprintf(ar->f, "this");
675 break;
676 }
677 case NodeTypeBoolLiteral:
678 {
679 const char *bool_str = node->data.bool_literal.value ? "true" : "false";
680 fprintf(ar->f, "%s", bool_str);
681 break;
682 }
672 case NodeTypeFnDecl:683 case NodeTypeFnDecl:
673 case NodeTypeParamDecl:684 case NodeTypeParamDecl:
674 case NodeTypeErrorValueDecl:685 case NodeTypeErrorValueDecl:
...@@ -677,10 +688,8 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -677,10 +688,8 @@ static void render_node(AstRender *ar, AstNode *node) {
677 case NodeTypeStructField:688 case NodeTypeStructField:
678 case NodeTypeStructValueField:689 case NodeTypeStructValueField:
679 case NodeTypeUse:690 case NodeTypeUse:
680 case NodeTypeBoolLiteral:
681 case NodeTypeNullLiteral:691 case NodeTypeNullLiteral:
682 case NodeTypeZeroesLiteral:692 case NodeTypeZeroesLiteral:
683 case NodeTypeThisLiteral:
684 case NodeTypeIfBoolExpr:693 case NodeTypeIfBoolExpr:
685 case NodeTypeIfVarExpr:694 case NodeTypeIfVarExpr:
686 case NodeTypeForExpr:695 case NodeTypeForExpr:
src/codegen.cpp+1
...@@ -1681,6 +1681,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1681,6 +1681,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1681 case IrInstructionIdPtrTypeChild:1681 case IrInstructionIdPtrTypeChild:
1682 case IrInstructionIdFieldPtr:1682 case IrInstructionIdFieldPtr:
1683 case IrInstructionIdSetFnTest:1683 case IrInstructionIdSetFnTest:
1684 case IrInstructionIdSetDebugSafety:
1684 case IrInstructionIdArrayType:1685 case IrInstructionIdArrayType:
1685 case IrInstructionIdSliceType:1686 case IrInstructionIdSliceType:
1686 zig_unreachable();1687 zig_unreachable();
src/ir.cpp+101-67
...@@ -201,6 +201,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) {...@@ -201,6 +201,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) {
201 return IrInstructionIdSetFnTest;201 return IrInstructionIdSetFnTest;
202}202}
203203
204static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) {
205 return IrInstructionIdSetDebugSafety;
206}
207
204static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {208static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
205 return IrInstructionIdArrayType;209 return IrInstructionIdArrayType;
206}210}
...@@ -786,6 +790,19 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node,...@@ -786,6 +790,19 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node,
786 return &instruction->base;790 return &instruction->base;
787}791}
788792
793static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, AstNode *source_node,
794 IrInstruction *scope_value, IrInstruction *debug_safety_on)
795{
796 IrInstructionSetDebugSafety *instruction = ir_build_instruction<IrInstructionSetDebugSafety>(irb, source_node);
797 instruction->scope_value = scope_value;
798 instruction->debug_safety_on = debug_safety_on;
799
800 ir_ref_instruction(scope_value);
801 ir_ref_instruction(debug_safety_on);
802
803 return &instruction->base;
804}
805
789static IrInstruction *ir_build_array_type(IrBuilder *irb, AstNode *source_node, IrInstruction *size,806static IrInstruction *ir_build_array_type(IrBuilder *irb, AstNode *source_node, IrInstruction *size,
790 IrInstruction *child_type)807 IrInstruction *child_type)
791{808{
...@@ -1291,6 +1308,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {...@@ -1291,6 +1308,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
12911308
1292 return ir_build_set_fn_test(irb, node, arg0_value, arg1_value);1309 return ir_build_set_fn_test(irb, node, arg0_value, arg1_value);
1293 }1310 }
1311 case BuiltinFnIdSetDebugSafety:
1312 {
1313 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
1314 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context);
1315 if (arg0_value == irb->codegen->invalid_instruction)
1316 return arg0_value;
1317
1318 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
1319 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, node->block_context);
1320 if (arg1_value == irb->codegen->invalid_instruction)
1321 return arg1_value;
1322
1323 return ir_build_set_debug_safety(irb, node, arg0_value, arg1_value);
1324 }
1294 case BuiltinFnIdMemcpy:1325 case BuiltinFnIdMemcpy:
1295 case BuiltinFnIdMemset:1326 case BuiltinFnIdMemset:
1296 case BuiltinFnIdSizeof:1327 case BuiltinFnIdSizeof:
...@@ -1325,7 +1356,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {...@@ -1325,7 +1356,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
1325 case BuiltinFnIdSetFnVisible:1356 case BuiltinFnIdSetFnVisible:
1326 case BuiltinFnIdSetFnStaticEval:1357 case BuiltinFnIdSetFnStaticEval:
1327 case BuiltinFnIdSetFnNoInline:1358 case BuiltinFnIdSetFnNoInline:
1328 case BuiltinFnIdSetDebugSafety:
1329 zig_panic("TODO IR gen more builtin functions");1359 zig_panic("TODO IR gen more builtin functions");
1330 }1360 }
1331 zig_unreachable();1361 zig_unreachable();
...@@ -2260,6 +2290,15 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value...@@ -2260,6 +2290,15 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value
2260 return const_val->data.x_type;2290 return const_val->data.x_type;
2261}2291}
22622292
2293static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) {
2294 if (value->static_value.special != ConstValSpecialStatic) {
2295 add_node_error(ira->codegen, value->source_node,
2296 buf_sprintf("unable to evaluate constant expression"));
2297 return nullptr;
2298 }
2299 return &value->static_value;
2300}
2301
2263static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out) {2302static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out) {
2264 if (bool_value == ira->codegen->invalid_instruction)2303 if (bool_value == ira->codegen->invalid_instruction)
2265 return false;2304 return false;
...@@ -2273,12 +2312,9 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out...@@ -2273,12 +2312,9 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out
2273 return false;2312 return false;
2274 }2313 }
22752314
2276 ConstExprValue *const_val = &bool_value->static_value;2315 ConstExprValue *const_val = ir_resolve_const(ira, bool_value);
2277 if (const_val->special == ConstValSpecialRuntime) {2316 if (!const_val)
2278 add_node_error(ira->codegen, bool_value->source_node,
2279 buf_sprintf("unable to evaluate constant expression"));
2280 return false;2317 return false;
2281 }
22822318
2283 *out = const_val->data.x_bool;2319 *out = const_val->data.x_bool;
2284 return true;2320 return true;
...@@ -4027,12 +4063,67 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira,...@@ -4027,12 +4063,67 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira,
4027 }4063 }
4028 fn_entry->fn_test_set_node = source_node;4064 fn_entry->fn_test_set_node = source_node;
40294065
4030 ira->codegen->test_fn_count += 1;4066 if (fn_entry->is_test)
4067 ira->codegen->test_fn_count += 1;
40314068
4032 ir_build_const_from(ira, &set_fn_test_instruction->base, false);4069 ir_build_const_from(ira, &set_fn_test_instruction->base, false);
4033 return ira->codegen->builtin_types.entry_void;4070 return ira->codegen->builtin_types.entry_void;
4034}4071}
40354072
4073static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,
4074 IrInstructionSetDebugSafety *set_debug_safety_instruction)
4075{
4076 IrInstruction *target_instruction = set_debug_safety_instruction->scope_value->other;
4077 TypeTableEntry *target_type = target_instruction->type_entry;
4078 if (target_type->id == TypeTableEntryIdInvalid)
4079 return ira->codegen->builtin_types.entry_invalid;
4080 ConstExprValue *target_val = ir_resolve_const(ira, target_instruction);
4081 if (!target_val)
4082 return ira->codegen->builtin_types.entry_invalid;
4083
4084 BlockContext *target_context;
4085 if (target_type->id == TypeTableEntryIdBlock) {
4086 target_context = target_val->data.x_block;
4087 } else if (target_type->id == TypeTableEntryIdFn) {
4088 target_context = target_val->data.x_fn->fn_def_node->data.fn_def.block_context;
4089 } else if (target_type->id == TypeTableEntryIdMetaType) {
4090 TypeTableEntry *type_arg = target_val->data.x_type;
4091 if (type_arg->id == TypeTableEntryIdStruct) {
4092 target_context = type_arg->data.structure.block_context;
4093 } else if (type_arg->id == TypeTableEntryIdEnum) {
4094 target_context = type_arg->data.enumeration.block_context;
4095 } else if (type_arg->id == TypeTableEntryIdUnion) {
4096 target_context = type_arg->data.unionation.block_context;
4097 } else {
4098 add_node_error(ira->codegen, target_instruction->source_node,
4099 buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
4100 return ira->codegen->builtin_types.entry_invalid;
4101 }
4102 } else {
4103 add_node_error(ira->codegen, target_instruction->source_node,
4104 buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
4105 return ira->codegen->builtin_types.entry_invalid;
4106 }
4107
4108 IrInstruction *debug_safety_on_value = set_debug_safety_instruction->debug_safety_on->other;
4109 bool want_debug_safety;
4110 if (!ir_resolve_bool(ira, debug_safety_on_value, &want_debug_safety))
4111 return ira->codegen->builtin_types.entry_invalid;
4112
4113 AstNode *source_node = set_debug_safety_instruction->base.source_node;
4114 if (target_context->safety_set_node) {
4115 ErrorMsg *msg = add_node_error(ira->codegen, source_node,
4116 buf_sprintf("function test attribute set twice"));
4117 add_error_note(ira->codegen, msg, target_context->safety_set_node, buf_sprintf("first set here"));
4118 return ira->codegen->builtin_types.entry_invalid;
4119 }
4120 target_context->safety_set_node = source_node;
4121 target_context->safety_off = !want_debug_safety;
4122
4123 ir_build_const_from(ira, &set_debug_safety_instruction->base, false);
4124 return ira->codegen->builtin_types.entry_void;
4125}
4126
4036static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,4127static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
4037 IrInstructionSliceType *slice_type_instruction)4128 IrInstructionSliceType *slice_type_instruction)
4038{4129{
...@@ -4164,6 +4255,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -4164,6 +4255,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
4164 return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);4255 return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
4165 case IrInstructionIdSetFnTest:4256 case IrInstructionIdSetFnTest:
4166 return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);4257 return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
4258 case IrInstructionIdSetDebugSafety:
4259 return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction);
4167 case IrInstructionIdSliceType:4260 case IrInstructionIdSliceType:
4168 return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction);4261 return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction);
4169 case IrInstructionIdAsm:4262 case IrInstructionIdAsm:
...@@ -4257,6 +4350,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -4257,6 +4350,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
4257 case IrInstructionIdReturn:4350 case IrInstructionIdReturn:
4258 case IrInstructionIdUnreachable:4351 case IrInstructionIdUnreachable:
4259 case IrInstructionIdSetFnTest:4352 case IrInstructionIdSetFnTest:
4353 case IrInstructionIdSetDebugSafety:
4260 return true;4354 return true;
4261 case IrInstructionIdPhi:4355 case IrInstructionIdPhi:
4262 case IrInstructionIdUnOp:4356 case IrInstructionIdUnOp:
...@@ -4854,64 +4948,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -4854,64 +4948,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
4854// return g->builtin_types.entry_void;4948// return g->builtin_types.entry_void;
4855//}4949//}
4856//4950//
4857//static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import,
4858// BlockContext *parent_context, AstNode *node)
4859//{
4860// AstNode **target_node = &node->data.fn_call_expr.params.at(0);
4861// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
4862//
4863// TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node);
4864// BlockContext *target_context;
4865// ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val;
4866// if (target_type->id == TypeTableEntryIdInvalid) {
4867// return g->builtin_types.entry_invalid;
4868// }
4869// if (!const_val->ok) {
4870// add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression"));
4871// return g->builtin_types.entry_invalid;
4872// }
4873// if (target_type->id == TypeTableEntryIdBlock) {
4874// target_context = const_val->data.x_block;
4875// } else if (target_type->id == TypeTableEntryIdFn) {
4876// target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context;
4877// } else if (target_type->id == TypeTableEntryIdMetaType) {
4878// TypeTableEntry *type_arg = const_val->data.x_type;
4879// if (type_arg->id == TypeTableEntryIdStruct) {
4880// target_context = type_arg->data.structure.block_context;
4881// } else if (type_arg->id == TypeTableEntryIdEnum) {
4882// target_context = type_arg->data.enumeration.block_context;
4883// } else if (type_arg->id == TypeTableEntryIdUnion) {
4884// target_context = type_arg->data.unionation.block_context;
4885// } else {
4886// add_node_error(g, *target_node,
4887// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
4888// return g->builtin_types.entry_invalid;
4889// }
4890// } else {
4891// add_node_error(g, *target_node,
4892// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
4893// return g->builtin_types.entry_invalid;
4894// }
4895//
4896// bool want_debug_safety;
4897// bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety);
4898// if (!ok) {
4899// return g->builtin_types.entry_invalid;
4900// }
4901//
4902// if (target_context->safety_set_node) {
4903// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice"));
4904// add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here"));
4905// return g->builtin_types.entry_invalid;
4906// }
4907// target_context->safety_set_node = node;
4908//
4909// target_context->safety_off = !want_debug_safety;
4910//
4911// return g->builtin_types.entry_void;
4912//}
4913
4914
4915//static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4951//static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4916// TypeTableEntry *expected_type, AstNode *node)4952// TypeTableEntry *expected_type, AstNode *node)
4917//{4953//{
...@@ -5215,8 +5251,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -5215,8 +5251,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
5215// return analyze_set_fn_static_eval(g, import, context, node);5251// return analyze_set_fn_static_eval(g, import, context, node);
5216// case BuiltinFnIdSetFnVisible:5252// case BuiltinFnIdSetFnVisible:
5217// return analyze_set_fn_visible(g, import, context, node);5253// return analyze_set_fn_visible(g, import, context, node);
5218// case BuiltinFnIdSetDebugSafety:
5219// return analyze_set_debug_safety(g, import, context, node);
5220// }5254// }
5221// zig_unreachable();5255// zig_unreachable();
5222//}5256//}
src/ir_print.cpp+11
...@@ -409,6 +409,14 @@ static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instructi...@@ -409,6 +409,14 @@ static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instructi
409 fprintf(irp->f, ")");409 fprintf(irp->f, ")");
410}410}
411411
412static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) {
413 fprintf(irp->f, "@setDebugSafety(");
414 ir_print_other_instruction(irp, instruction->scope_value);
415 fprintf(irp->f, ", ");
416 ir_print_other_instruction(irp, instruction->debug_safety_on);
417 fprintf(irp->f, ")");
418}
419
412static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instruction) {420static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instruction) {
413 fprintf(irp->f, "[");421 fprintf(irp->f, "[");
414 ir_print_other_instruction(irp, instruction->size);422 ir_print_other_instruction(irp, instruction->size);
...@@ -541,6 +549,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -541,6 +549,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
541 case IrInstructionIdSetFnTest:549 case IrInstructionIdSetFnTest:
542 ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);550 ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
543 break;551 break;
552 case IrInstructionIdSetDebugSafety:
553 ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction);
554 break;
544 case IrInstructionIdArrayType:555 case IrInstructionIdArrayType:
545 ir_print_array_type(irp, (IrInstructionArrayType *)instruction);556 ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
546 break;557 break;
test/self_hosted2.zig+35-7
...@@ -1,13 +1,41 @@...@@ -1,13 +1,41 @@
1fn add(a: i32, b: i32) -> i32 {1pub const SYS_write = 1;
2 a + b2pub const SYS_exit = 60;
3pub const stdout_fileno = 1;
4const text = "hello\n";
5
6export nakedcc fn _start() -> unreachable {
7 myMain();
8}
9
10fn myMain() -> unreachable {
11 write(stdout_fileno, &text[0], text.len);
12 exit(0);
3}13}
414
5fn assert(ok: bool) {15pub inline fn syscall1(number: usize, arg1: usize) -> usize {
6 if (!ok) @unreachable();16 asm volatile ("syscall"
17 : [ret] "={rax}" (-> usize)
18 : [number] "{rax}" (number),
19 [arg1] "{rdi}" (arg1)
20 : "rcx", "r11")
7}21}
822
9fn testAdd() {23pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize {
10 @setFnTest(this, true);24 asm volatile ("syscall"
25 : [ret] "={rax}" (-> usize)
26 : [number] "{rax}" (number),
27 [arg1] "{rdi}" (arg1),
28 [arg2] "{rsi}" (arg2),
29 [arg3] "{rdx}" (arg3)
30 : "rcx", "r11")
31}
1132
12 assert(add(2, 3) == 5);33pub fn write(fd: i32, buf: &const u8, count: usize) -> usize {
34 syscall3(SYS_write, usize(fd), usize(buf), count)
13}35}
36
37pub fn exit(status: i32) -> unreachable {
38 syscall1(SYS_exit, usize(status));
39 @unreachable()
40}
41