diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-05-20 23:06:32 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-05-20 23:06:32 -0400 |
| commit | 29b488245daa9210ed9b5e1ffb7290024677f0db (patch) | |
| tree | 7bcee7504f7caa5f72c8d83bbf066aa494306a70 /src/ir.cpp | |
| parent | 051ee8e626111445c27d6c868cb0cdec6df7409e (diff) | |
| download | zig-29b488245daa9210ed9b5e1ffb7290024677f0db.tar.gz zig-29b488245daa9210ed9b5e1ffb7290024677f0db.zip | |
add setFloatMode builtin and std.math.floor
* skip installing std/rand_test.zig as it's not needed beyond running
the std lib tests
* add std.math.floor function
* add setFloatMode builtin function to choose between
builtin.FloatMode.Optimized (default) and builtin.FloatMode.Strict
(Optimized is equivalent to -ffast-math in gcc)
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 142 |
1 files changed, 136 insertions, 6 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 3c14d808db..cc0e364487 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -297,6 +297,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety * return IrInstructionIdSetDebugSafety; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFloatMode *) { + return IrInstructionIdSetFloatMode; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) { return IrInstructionIdArrayType; } @@ -1190,6 +1194,19 @@ static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, Scope *scope, As return &instruction->base; } +static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *scope_value, IrInstruction *mode_value) +{ + IrInstructionSetFloatMode *instruction = ir_build_instruction<IrInstructionSetFloatMode>(irb, scope, source_node); + instruction->scope_value = scope_value; + instruction->mode_value = mode_value; + + ir_ref_instruction(scope_value, irb->current_basic_block); + ir_ref_instruction(mode_value, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size, IrInstruction *child_type) { @@ -2361,6 +2378,14 @@ static IrInstruction *ir_instruction_setdebugsafety_get_dep(IrInstructionSetDebu } } +static IrInstruction *ir_instruction_setfloatmode_get_dep(IrInstructionSetFloatMode *instruction, size_t index) { + switch (index) { + case 0: return instruction->scope_value; + case 1: return instruction->mode_value; + default: return nullptr; + } +} + static IrInstruction *ir_instruction_arraytype_get_dep(IrInstructionArrayType *instruction, size_t index) { switch (index) { case 0: return instruction->size; @@ -2897,6 +2922,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t return ir_instruction_ptrtypechild_get_dep((IrInstructionPtrTypeChild *) instruction, index); case IrInstructionIdSetDebugSafety: return ir_instruction_setdebugsafety_get_dep((IrInstructionSetDebugSafety *) instruction, index); + case IrInstructionIdSetFloatMode: + return ir_instruction_setfloatmode_get_dep((IrInstructionSetFloatMode *) instruction, index); case IrInstructionIdArrayType: return ir_instruction_arraytype_get_dep((IrInstructionArrayType *) instruction, index); case IrInstructionIdSliceType: @@ -3841,6 +3868,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_set_debug_safety(irb, scope, node, arg0_value, arg1_value); } + case BuiltinFnIdSetFloatMode: + { + 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; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + return ir_build_set_float_mode(irb, scope, node, arg0_value, arg1_value); + } case BuiltinFnIdSizeof: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -7740,6 +7781,16 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { return result; } +static ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { + Tld *tld = codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str(name)); + resolve_top_level_decl(codegen, tld, false); + assert(tld->id == TldIdVar); + TldVar *tld_var = (TldVar *)tld; + ConstExprValue *var_value = tld_var->var->value; + assert(var_value != nullptr); + return var_value; +} + static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *return_instruction) { @@ -10556,7 +10607,7 @@ static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, AstNode *source_node = set_debug_safety_instruction->base.source_node; if (*safety_set_node_ptr) { ErrorMsg *msg = ir_add_error_node(ira, source_node, - buf_sprintf("function test attribute set twice")); + buf_sprintf("debug safety set twice for same scope")); add_error_note(ira->codegen, msg, *safety_set_node_ptr, buf_sprintf("first set here")); return ira->codegen->builtin_types.entry_invalid; } @@ -10567,6 +10618,86 @@ static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, return ira->codegen->builtin_types.entry_void; } +static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, + IrInstructionSetFloatMode *instruction) +{ + IrInstruction *target_instruction = instruction->scope_value->other; + TypeTableEntry *target_type = target_instruction->value.type; + if (type_is_invalid(target_type)) + return ira->codegen->builtin_types.entry_invalid; + ConstExprValue *target_val = ir_resolve_const(ira, target_instruction, UndefBad); + if (!target_val) + return ira->codegen->builtin_types.entry_invalid; + + if (ira->new_irb.exec->is_inline) { + // ignore setFloatMode when running functions at compile time + ir_build_const_from(ira, &instruction->base); + return ira->codegen->builtin_types.entry_void; + } + + bool *fast_math_off_ptr; + AstNode **fast_math_set_node_ptr; + if (target_type->id == TypeTableEntryIdBlock) { + ScopeBlock *block_scope = (ScopeBlock *)target_val->data.x_block; + fast_math_off_ptr = &block_scope->fast_math_off; + fast_math_set_node_ptr = &block_scope->fast_math_set_node; + } else if (target_type->id == TypeTableEntryIdFn) { + FnTableEntry *target_fn = target_val->data.x_fn.fn_entry; + assert(target_fn->def_scope); + fast_math_off_ptr = &target_fn->def_scope->fast_math_off; + fast_math_set_node_ptr = &target_fn->def_scope->fast_math_set_node; + } else if (target_type->id == TypeTableEntryIdMetaType) { + ScopeDecls *decls_scope; + TypeTableEntry *type_arg = target_val->data.x_type; + if (type_arg->id == TypeTableEntryIdStruct) { + decls_scope = type_arg->data.structure.decls_scope; + } else if (type_arg->id == TypeTableEntryIdEnum) { + decls_scope = type_arg->data.enumeration.decls_scope; + } else if (type_arg->id == TypeTableEntryIdUnion) { + decls_scope = type_arg->data.unionation.decls_scope; + } else { + ir_add_error_node(ira, target_instruction->source_node, + buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&type_arg->name))); + return ira->codegen->builtin_types.entry_invalid; + } + fast_math_off_ptr = &decls_scope->fast_math_off; + fast_math_set_node_ptr = &decls_scope->fast_math_set_node; + } else { + ir_add_error_node(ira, target_instruction->source_node, + buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&target_type->name))); + return ira->codegen->builtin_types.entry_invalid; + } + + ConstExprValue *float_mode_val = get_builtin_value(ira->codegen, "FloatMode"); + assert(float_mode_val->type->id == TypeTableEntryIdMetaType); + TypeTableEntry *float_mode_enum_type = float_mode_val->data.x_type; + + IrInstruction *float_mode_value = instruction->mode_value->other; + if (type_is_invalid(float_mode_value->value.type)) + return ira->codegen->builtin_types.entry_invalid; + IrInstruction *casted_value = ir_implicit_cast(ira, float_mode_value, float_mode_enum_type); + if (type_is_invalid(casted_value->value.type)) + return ira->codegen->builtin_types.entry_invalid; + ConstExprValue *mode_val = ir_resolve_const(ira, casted_value, UndefBad); + if (!mode_val) + return ira->codegen->builtin_types.entry_invalid; + + bool want_fast_math = (mode_val->data.x_enum.tag == FloatModeOptimized); + + AstNode *source_node = instruction->base.source_node; + if (*fast_math_set_node_ptr) { + ErrorMsg *msg = ir_add_error_node(ira, source_node, + buf_sprintf("float mode set twice for same scope")); + add_error_note(ira->codegen, msg, *fast_math_set_node_ptr, buf_sprintf("first set here")); + return ira->codegen->builtin_types.entry_invalid; + } + *fast_math_set_node_ptr = source_node; + *fast_math_off_ptr = !want_fast_math; + + ir_build_const_from(ira, &instruction->base); + return ira->codegen->builtin_types.entry_void; +} + static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstructionSliceType *slice_type_instruction) { @@ -11864,11 +11995,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira, if (type_is_invalid(type_entry)) return ira->codegen->builtin_types.entry_invalid; - Tld *tld = ira->codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str("TypeId")); - resolve_top_level_decl(ira->codegen, tld, false); - assert(tld->id == TldIdVar); - TldVar *tld_var = (TldVar *)tld; - ConstExprValue *var_value = tld_var->var->value; + ConstExprValue *var_value = get_builtin_value(ira->codegen, "TypeId"); assert(var_value->type->id == TypeTableEntryIdMetaType); TypeTableEntry *result_type = var_value->data.x_type; @@ -13271,6 +13398,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_set_global_linkage(ira, (IrInstructionSetGlobalLinkage *)instruction); case IrInstructionIdSetDebugSafety: return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction); + case IrInstructionIdSetFloatMode: + return ir_analyze_instruction_set_float_mode(ira, (IrInstructionSetFloatMode *)instruction); case IrInstructionIdSliceType: return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction); case IrInstructionIdAsm: @@ -13482,6 +13611,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdReturn: case IrInstructionIdUnreachable: case IrInstructionIdSetDebugSafety: + case IrInstructionIdSetFloatMode: case IrInstructionIdImport: case IrInstructionIdCompileErr: case IrInstructionIdCompileLog: |
