add setEvalBranchQuota builtin function

This commit is contained in:
Andrew Kelley 2017-08-19 17:10:29 -04:00
parent eb26aeb1e5
commit caaeab9882
6 changed files with 84 additions and 1 deletions

View File

@ -137,4 +137,4 @@ produced .gcov files.
* Runtime crashes are better than bugs.
* Compile errors are better than runtime crashes.
* Minimize energy spent on coding style.
* Together we serve the users.
* Together we serve the end users.

View File

@ -1232,6 +1232,7 @@ enum BuiltinFnId {
BuiltinFnIdTypeId,
BuiltinFnIdShlExact,
BuiltinFnIdShrExact,
BuiltinFnIdSetEvalBranchQuota,
};
struct BuiltinFnEntry {
@ -1834,6 +1835,7 @@ enum IrInstructionId {
IrInstructionIdFieldParentPtr,
IrInstructionIdOffsetOf,
IrInstructionIdTypeId,
IrInstructionIdSetEvalBranchQuota,
};
struct IrInstruction {
@ -2603,6 +2605,12 @@ struct IrInstructionTypeId {
IrInstruction *type_value;
};
struct IrInstructionSetEvalBranchQuota {
IrInstruction base;
IrInstruction *new_quota;
};
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;

View File

@ -3173,6 +3173,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdSwitchVar:
case IrInstructionIdOffsetOf:
case IrInstructionIdTypeId:
case IrInstructionIdSetEvalBranchQuota:
zig_unreachable();
case IrInstructionIdReturn:
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
@ -4635,6 +4636,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);
create_builtin_fn(g, BuiltinFnIdShlExact, "shlExact", 2);
create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2);
create_builtin_fn(g, BuiltinFnIdSetEvalBranchQuota, "setEvalBranchQuota", 1);
}
static const char *bool_to_str(bool b) {

View File

@ -549,6 +549,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeId *) {
return IrInstructionIdTypeId;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionSetEvalBranchQuota *) {
return IrInstructionIdSetEvalBranchQuota;
}
template<typename T>
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@ -2192,6 +2196,17 @@ static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *so
return &instruction->base;
}
static IrInstruction *ir_build_set_eval_branch_quota(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *new_quota)
{
IrInstructionSetEvalBranchQuota *instruction = ir_build_instruction<IrInstructionSetEvalBranchQuota>(irb, scope, source_node);
instruction->new_quota = new_quota;
ir_ref_instruction(new_quota, irb->current_basic_block);
return &instruction->base;
}
static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
return nullptr;
}
@ -2881,6 +2896,13 @@ static IrInstruction *ir_instruction_typeid_get_dep(IrInstructionTypeId *instruc
}
}
static IrInstruction *ir_instruction_setevalbranchquota_get_dep(IrInstructionSetEvalBranchQuota *instruction, size_t index) {
switch (index) {
case 0: return instruction->new_quota;
default: return nullptr;
}
}
static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@ -3075,6 +3097,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
return ir_instruction_offsetof_get_dep((IrInstructionOffsetOf *) instruction, index);
case IrInstructionIdTypeId:
return ir_instruction_typeid_get_dep((IrInstructionTypeId *) instruction, index);
case IrInstructionIdSetEvalBranchQuota:
return ir_instruction_setevalbranchquota_get_dep((IrInstructionSetEvalBranchQuota *) instruction, index);
}
zig_unreachable();
}
@ -4481,6 +4505,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true);
}
case BuiltinFnIdSetEvalBranchQuota:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
if (arg0_value == irb->codegen->invalid_instruction)
return arg0_value;
return ir_build_set_eval_branch_quota(irb, scope, node, arg0_value);
}
}
zig_unreachable();
}
@ -12432,6 +12465,21 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira,
return result_type;
}
static TypeTableEntry *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
IrInstructionSetEvalBranchQuota *instruction)
{
uint64_t new_quota;
if (!ir_resolve_usize(ira, instruction->new_quota->other, &new_quota))
return ira->codegen->builtin_types.entry_invalid;
if (new_quota > ira->new_irb.exec->backward_branch_quota) {
ira->new_irb.exec->backward_branch_quota = new_quota;
}
ir_build_const_from(ira, &instruction->base);
return ira->codegen->builtin_types.entry_void;
}
static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) {
IrInstruction *type_value = instruction->type_value->other;
TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
@ -14249,6 +14297,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_offset_of(ira, (IrInstructionOffsetOf *)instruction);
case IrInstructionIdTypeId:
return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction);
case IrInstructionIdSetEvalBranchQuota:
return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstructionSetEvalBranchQuota *)instruction);
case IrInstructionIdMaybeWrap:
case IrInstructionIdErrWrapCode:
case IrInstructionIdErrWrapPayload:
@ -14365,6 +14415,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdSetGlobalSection:
case IrInstructionIdSetGlobalLinkage:
case IrInstructionIdPanic:
case IrInstructionIdSetEvalBranchQuota:
return true;
case IrInstructionIdPhi:
case IrInstructionIdUnOp:

View File

@ -910,6 +910,12 @@ static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) {
fprintf(irp->f, ")");
}
static void ir_print_set_eval_branch_quota(IrPrint *irp, IrInstructionSetEvalBranchQuota *instruction) {
fprintf(irp->f, "@setEvalBranchQuota(");
ir_print_other_instruction(irp, instruction->new_quota);
fprintf(irp->f, ")");
}
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@ -1200,6 +1206,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdTypeId:
ir_print_type_id(irp, (IrInstructionTypeId *)instruction);
break;
case IrInstructionIdSetEvalBranchQuota:
ir_print_set_eval_branch_quota(irp, (IrInstructionSetEvalBranchQuota *)instruction);
break;
}
fprintf(irp->f, "\n");
}

View File

@ -342,3 +342,16 @@ test "const global shares pointer with other same one" {
fn assertEqualPtrs(ptr1: &const u8, ptr2: &const u8) {
assert(ptr1 == ptr2);
}
test "@setEvalBranchQuota" {
comptime {
// 1001 for the loop and then 1 more for the assert fn call
@setEvalBranchQuota(1002);
var i = 0;
var sum = 0;
while (i < 1001) : (i += 1) {
sum += i;
}
assert(sum == 500500);
}
}