IR: support setDebugSafety builtin function
parent
ed31ae8867
commit
bf7cde62c5
|
@ -1449,6 +1449,7 @@ enum IrInstructionId {
|
||||||
IrInstructionIdToPtrType,
|
IrInstructionIdToPtrType,
|
||||||
IrInstructionIdPtrTypeChild,
|
IrInstructionIdPtrTypeChild,
|
||||||
IrInstructionIdSetFnTest,
|
IrInstructionIdSetFnTest,
|
||||||
|
IrInstructionIdSetDebugSafety,
|
||||||
IrInstructionIdArrayType,
|
IrInstructionIdArrayType,
|
||||||
IrInstructionIdSliceType,
|
IrInstructionIdSliceType,
|
||||||
IrInstructionIdAsm,
|
IrInstructionIdAsm,
|
||||||
|
@ -1705,6 +1706,13 @@ struct IrInstructionSetFnTest {
|
||||||
IrInstruction *is_test;
|
IrInstruction *is_test;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IrInstructionSetDebugSafety {
|
||||||
|
IrInstruction base;
|
||||||
|
|
||||||
|
IrInstruction *scope_value;
|
||||||
|
IrInstruction *debug_safety_on;
|
||||||
|
};
|
||||||
|
|
||||||
struct IrInstructionArrayType {
|
struct IrInstructionArrayType {
|
||||||
IrInstruction base;
|
IrInstruction base;
|
||||||
|
|
||||||
|
|
|
@ -669,6 +669,17 @@ static void render_node(AstRender *ar, AstNode *node) {
|
||||||
render_node(ar, node->data.while_expr.body);
|
render_node(ar, node->data.while_expr.body);
|
||||||
break;
|
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 NodeTypeFnDecl:
|
||||||
case NodeTypeParamDecl:
|
case NodeTypeParamDecl:
|
||||||
case NodeTypeErrorValueDecl:
|
case NodeTypeErrorValueDecl:
|
||||||
|
@ -677,10 +688,8 @@ static void render_node(AstRender *ar, AstNode *node) {
|
||||||
case NodeTypeStructField:
|
case NodeTypeStructField:
|
||||||
case NodeTypeStructValueField:
|
case NodeTypeStructValueField:
|
||||||
case NodeTypeUse:
|
case NodeTypeUse:
|
||||||
case NodeTypeBoolLiteral:
|
|
||||||
case NodeTypeNullLiteral:
|
case NodeTypeNullLiteral:
|
||||||
case NodeTypeZeroesLiteral:
|
case NodeTypeZeroesLiteral:
|
||||||
case NodeTypeThisLiteral:
|
|
||||||
case NodeTypeIfBoolExpr:
|
case NodeTypeIfBoolExpr:
|
||||||
case NodeTypeIfVarExpr:
|
case NodeTypeIfVarExpr:
|
||||||
case NodeTypeForExpr:
|
case NodeTypeForExpr:
|
||||||
|
|
|
@ -1681,6 +1681,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||||
case IrInstructionIdPtrTypeChild:
|
case IrInstructionIdPtrTypeChild:
|
||||||
case IrInstructionIdFieldPtr:
|
case IrInstructionIdFieldPtr:
|
||||||
case IrInstructionIdSetFnTest:
|
case IrInstructionIdSetFnTest:
|
||||||
|
case IrInstructionIdSetDebugSafety:
|
||||||
case IrInstructionIdArrayType:
|
case IrInstructionIdArrayType:
|
||||||
case IrInstructionIdSliceType:
|
case IrInstructionIdSliceType:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
|
166
src/ir.cpp
166
src/ir.cpp
|
@ -201,6 +201,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) {
|
||||||
return IrInstructionIdSetFnTest;
|
return IrInstructionIdSetFnTest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) {
|
||||||
|
return IrInstructionIdSetDebugSafety;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
|
static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
|
||||||
return IrInstructionIdArrayType;
|
return IrInstructionIdArrayType;
|
||||||
}
|
}
|
||||||
|
@ -786,6 +790,19 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node,
|
||||||
return &instruction->base;
|
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,
|
static IrInstruction *ir_build_array_type(IrBuilder *irb, AstNode *source_node, IrInstruction *size,
|
||||||
IrInstruction *child_type)
|
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);
|
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 BuiltinFnIdMemcpy:
|
||||||
case BuiltinFnIdMemset:
|
case BuiltinFnIdMemset:
|
||||||
case BuiltinFnIdSizeof:
|
case BuiltinFnIdSizeof:
|
||||||
|
@ -1325,7 +1356,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
|
||||||
case BuiltinFnIdSetFnVisible:
|
case BuiltinFnIdSetFnVisible:
|
||||||
case BuiltinFnIdSetFnStaticEval:
|
case BuiltinFnIdSetFnStaticEval:
|
||||||
case BuiltinFnIdSetFnNoInline:
|
case BuiltinFnIdSetFnNoInline:
|
||||||
case BuiltinFnIdSetDebugSafety:
|
|
||||||
zig_panic("TODO IR gen more builtin functions");
|
zig_panic("TODO IR gen more builtin functions");
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
@ -2260,6 +2290,15 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value
|
||||||
return const_val->data.x_type;
|
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) {
|
static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out) {
|
||||||
if (bool_value == ira->codegen->invalid_instruction)
|
if (bool_value == ira->codegen->invalid_instruction)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2273,12 +2312,9 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstExprValue *const_val = &bool_value->static_value;
|
ConstExprValue *const_val = ir_resolve_const(ira, bool_value);
|
||||||
if (const_val->special == ConstValSpecialRuntime) {
|
if (!const_val)
|
||||||
add_node_error(ira->codegen, bool_value->source_node,
|
|
||||||
buf_sprintf("unable to evaluate constant expression"));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
*out = const_val->data.x_bool;
|
*out = const_val->data.x_bool;
|
||||||
return true;
|
return true;
|
||||||
|
@ -4027,12 +4063,67 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira,
|
||||||
}
|
}
|
||||||
fn_entry->fn_test_set_node = source_node;
|
fn_entry->fn_test_set_node = source_node;
|
||||||
|
|
||||||
|
if (fn_entry->is_test)
|
||||||
ira->codegen->test_fn_count += 1;
|
ira->codegen->test_fn_count += 1;
|
||||||
|
|
||||||
ir_build_const_from(ira, &set_fn_test_instruction->base, false);
|
ir_build_const_from(ira, &set_fn_test_instruction->base, false);
|
||||||
return ira->codegen->builtin_types.entry_void;
|
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,
|
static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
|
||||||
IrInstructionSliceType *slice_type_instruction)
|
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);
|
return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
|
||||||
case IrInstructionIdSetFnTest:
|
case IrInstructionIdSetFnTest:
|
||||||
return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
|
return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
|
||||||
|
case IrInstructionIdSetDebugSafety:
|
||||||
|
return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction);
|
||||||
case IrInstructionIdSliceType:
|
case IrInstructionIdSliceType:
|
||||||
return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction);
|
return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction);
|
||||||
case IrInstructionIdAsm:
|
case IrInstructionIdAsm:
|
||||||
|
@ -4257,6 +4350,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||||
case IrInstructionIdReturn:
|
case IrInstructionIdReturn:
|
||||||
case IrInstructionIdUnreachable:
|
case IrInstructionIdUnreachable:
|
||||||
case IrInstructionIdSetFnTest:
|
case IrInstructionIdSetFnTest:
|
||||||
|
case IrInstructionIdSetDebugSafety:
|
||||||
return true;
|
return true;
|
||||||
case IrInstructionIdPhi:
|
case IrInstructionIdPhi:
|
||||||
case IrInstructionIdUnOp:
|
case IrInstructionIdUnOp:
|
||||||
|
@ -4854,64 +4948,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
|
||||||
// return g->builtin_types.entry_void;
|
// 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,
|
//static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
// TypeTableEntry *expected_type, AstNode *node)
|
// 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);
|
// return analyze_set_fn_static_eval(g, import, context, node);
|
||||||
// case BuiltinFnIdSetFnVisible:
|
// case BuiltinFnIdSetFnVisible:
|
||||||
// return analyze_set_fn_visible(g, import, context, node);
|
// return analyze_set_fn_visible(g, import, context, node);
|
||||||
// case BuiltinFnIdSetDebugSafety:
|
|
||||||
// return analyze_set_debug_safety(g, import, context, node);
|
|
||||||
// }
|
// }
|
||||||
// zig_unreachable();
|
// zig_unreachable();
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -409,6 +409,14 @@ static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instructi
|
||||||
fprintf(irp->f, ")");
|
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) {
|
static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instruction) {
|
||||||
fprintf(irp->f, "[");
|
fprintf(irp->f, "[");
|
||||||
ir_print_other_instruction(irp, instruction->size);
|
ir_print_other_instruction(irp, instruction->size);
|
||||||
|
@ -541,6 +549,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||||
case IrInstructionIdSetFnTest:
|
case IrInstructionIdSetFnTest:
|
||||||
ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
|
ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
|
||||||
break;
|
break;
|
||||||
|
case IrInstructionIdSetDebugSafety:
|
||||||
|
ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction);
|
||||||
|
break;
|
||||||
case IrInstructionIdArrayType:
|
case IrInstructionIdArrayType:
|
||||||
ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
|
ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,13 +1,41 @@
|
||||||
fn add(a: i32, b: i32) -> i32 {
|
pub const SYS_write = 1;
|
||||||
a + b
|
pub const SYS_exit = 60;
|
||||||
|
pub const stdout_fileno = 1;
|
||||||
|
const text = "hello\n";
|
||||||
|
|
||||||
|
export nakedcc fn _start() -> unreachable {
|
||||||
|
myMain();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert(ok: bool) {
|
fn myMain() -> unreachable {
|
||||||
if (!ok) @unreachable();
|
write(stdout_fileno, &text[0], text.len);
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testAdd() {
|
pub inline fn syscall1(number: usize, arg1: usize) -> usize {
|
||||||
@setFnTest(this, true);
|
asm volatile ("syscall"
|
||||||
|
: [ret] "={rax}" (-> usize)
|
||||||
assert(add(2, 3) == 5);
|
: [number] "{rax}" (number),
|
||||||
|
[arg1] "{rdi}" (arg1)
|
||||||
|
: "rcx", "r11")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue