Permalink
Browse files

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)
  • Loading branch information...
andrewrk committed May 21, 2017
1 parent 051ee8e commit 29b488245daa9210ed9b5e1ffb7290024677f0db
Showing with 328 additions and 24 deletions.
  1. +0 −1 CMakeLists.txt
  2. +18 −0 src/all_types.hpp
  3. +55 −11 src/codegen.cpp
  4. +136 −6 src/ir.cpp
  5. +11 −0 src/ir_print.cpp
  6. +79 −5 std/math.zig
  7. +11 −1 test/cases/eval.zig
  8. +18 −0 test/compile_errors.zig
View
@@ -232,7 +232,6 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_x86_64.zig" DESTINATION "${ZIG_S
install(FILES "${CMAKE_SOURCE_DIR}/std/os/path.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")
install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_file_template.zig" DESTINATION "${ZIG_STD_DEST}/special")
View
@@ -1193,6 +1193,7 @@ enum BuiltinFnId {
BuiltinFnIdTruncate,
BuiltinFnIdIntType,
BuiltinFnIdSetDebugSafety,
BuiltinFnIdSetFloatMode,
BuiltinFnIdTypeName,
BuiltinFnIdCanImplicitCast,
BuiltinFnIdSetGlobalAlign,
@@ -1580,6 +1581,8 @@ struct ScopeDecls {
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> decl_table;
bool safety_off;
AstNode *safety_set_node;
bool fast_math_off;
AstNode *fast_math_set_node;
ImportTableEntry *import;
// If this is a scope from a container, this is the type entry, otherwise null
TypeTableEntry *container_type;
@@ -1593,6 +1596,8 @@ struct ScopeBlock {
HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
bool safety_off;
AstNode *safety_set_node;
bool fast_math_off;
AstNode *fast_math_set_node;
};
// This scope is created from every defer expression.
@@ -1720,6 +1725,7 @@ enum IrInstructionId {
IrInstructionIdToPtrType,
IrInstructionIdPtrTypeChild,
IrInstructionIdSetDebugSafety,
IrInstructionIdSetFloatMode,
IrInstructionIdArrayType,
IrInstructionIdSliceType,
IrInstructionIdAsm,
@@ -2078,6 +2084,13 @@ struct IrInstructionSetDebugSafety {
IrInstruction *debug_safety_on;
};
struct IrInstructionSetFloatMode {
IrInstruction base;
IrInstruction *scope_value;
IrInstruction *mode_value;
};
struct IrInstructionArrayType {
IrInstruction base;
@@ -2550,4 +2563,9 @@ static const size_t enum_gen_union_index = 1;
static const size_t err_union_err_index = 0;
static const size_t err_union_payload_index = 1;
enum FloatMode {
FloatModeStrict,
FloatModeOptimized,
};
#endif
View
@@ -581,6 +581,24 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntr
}
}
static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) {
// TODO memoize
Scope *scope = instruction->scope;
while (scope) {
if (scope->id == ScopeIdBlock) {
ScopeBlock *block_scope = (ScopeBlock *)scope;
if (block_scope->fast_math_set_node)
return !block_scope->fast_math_off;
} else if (scope->id == ScopeIdDecls) {
ScopeDecls *decls_scope = (ScopeDecls *)scope;
if (decls_scope->fast_math_set_node)
return !decls_scope->fast_math_off;
}
scope = scope->parent;
}
return true;
}
static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) {
if (g->build_mode == BuildModeFastRelease)
return false;
@@ -1151,9 +1169,12 @@ enum DivKind {
DivKindExact,
};
static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, LLVMValueRef val1, LLVMValueRef val2,
static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_math,
LLVMValueRef val1, LLVMValueRef val2,
TypeTableEntry *type_entry, DivKind div_kind)
{
ZigLLVMSetFastMath(g->builder, want_fast_math);
LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
if (want_debug_safety) {
LLVMValueRef is_zero_bit;
@@ -1287,9 +1308,12 @@ enum RemKind {
RemKindMod,
};
static LLVMValueRef gen_rem(CodeGen *g, bool want_debug_safety, LLVMValueRef val1, LLVMValueRef val2,
static LLVMValueRef gen_rem(CodeGen *g, bool want_debug_safety, bool want_fast_math,
LLVMValueRef val1, LLVMValueRef val2,
TypeTableEntry *type_entry, RemKind rem_kind)
{
ZigLLVMSetFastMath(g->builder, want_fast_math);
LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
if (want_debug_safety) {
LLVMValueRef is_zero_bit;
@@ -1372,6 +1396,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpCmpLessOrEq:
case IrBinOpCmpGreaterOrEq:
if (type_entry->id == TypeTableEntryIdFloat) {
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");
} else if (type_entry->id == TypeTableEntryIdInt) {
@@ -1396,6 +1421,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpAdd:
case IrBinOpAddWrap:
if (type_entry->id == TypeTableEntryIdFloat) {
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
} else if (type_entry->id == TypeTableEntryIdInt) {
bool is_wrapping = (op_id == IrBinOpAddWrap);
@@ -1442,6 +1468,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpSub:
case IrBinOpSubWrap:
if (type_entry->id == TypeTableEntryIdFloat) {
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
return LLVMBuildFSub(g->builder, op1_value, op2_value, "");
} else if (type_entry->id == TypeTableEntryIdInt) {
bool is_wrapping = (op_id == IrBinOpSubWrap);
@@ -1460,6 +1487,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpMult:
case IrBinOpMultWrap:
if (type_entry->id == TypeTableEntryIdFloat) {
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
return LLVMBuildFMul(g->builder, op1_value, op2_value, "");
} else if (type_entry->id == TypeTableEntryIdInt) {
bool is_wrapping = (op_id == IrBinOpMultWrap);
@@ -1476,17 +1504,23 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
zig_unreachable();
}
case IrBinOpDivUnspecified:
return gen_div(g, want_debug_safety, op1_value, op2_value, type_entry, DivKindFloat);
return gen_div(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base),
op1_value, op2_value, type_entry, DivKindFloat);
case IrBinOpDivExact:
return gen_div(g, want_debug_safety, op1_value, op2_value, type_entry, DivKindExact);
return gen_div(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base),
op1_value, op2_value, type_entry, DivKindExact);
case IrBinOpDivTrunc:
return gen_div(g, want_debug_safety, op1_value, op2_value, type_entry, DivKindTrunc);
return gen_div(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base),
op1_value, op2_value, type_entry, DivKindTrunc);
case IrBinOpDivFloor:
return gen_div(g, want_debug_safety, op1_value, op2_value, type_entry, DivKindFloor);
return gen_div(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base),
op1_value, op2_value, type_entry, DivKindFloor);
case IrBinOpRemRem:
return gen_rem(g, want_debug_safety, op1_value, op2_value, type_entry, RemKindRem);
return gen_rem(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base),
op1_value, op2_value, type_entry, RemKindRem);
case IrBinOpRemMod:
return gen_rem(g, want_debug_safety, op1_value, op2_value, type_entry, RemKindMod);
return gen_rem(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base),
op1_value, op2_value, type_entry, RemKindMod);
}
zig_unreachable();
}
@@ -1602,6 +1636,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
}
case CastOpFloatToInt:
assert(wanted_type->id == TypeTableEntryIdInt);
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &cast_instruction->base));
if (wanted_type->data.integral.is_signed) {
return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, "");
} else {
@@ -1774,6 +1809,7 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
case IrUnOpNegationWrap:
{
if (expr_type->id == TypeTableEntryIdFloat) {
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &un_op_instruction->base));
return LLVMBuildFNeg(g->builder, expr, "");
} else if (expr_type->id == TypeTableEntryIdInt) {
if (op_id == IrUnOpNegationWrap) {
@@ -2986,6 +3022,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdPtrTypeChild:
case IrInstructionIdFieldPtr:
case IrInstructionIdSetDebugSafety:
case IrInstructionIdSetFloatMode:
case IrInstructionIdArrayType:
case IrInstructionIdSliceType:
case IrInstructionIdSizeOf:
@@ -4432,6 +4469,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2);
create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2);
create_builtin_fn(g, BuiltinFnIdSetGlobalAlign, "setGlobalAlign", 2);
create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);
create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2);
@@ -4588,6 +4626,15 @@ static void define_builtin_compile_vars(CodeGen *g) {
}
buf_appendf(contents, "};\n\n");
}
{
buf_appendf(contents,
"pub const FloatMode = enum {\n"
" Strict,\n"
" Optimized,\n"
"};\n\n");
assert(FloatModeStrict == 0);
assert(FloatModeOptimized == 1);
}
buf_appendf(contents, "pub const is_big_endian = %s;\n", bool_to_str(g->is_big_endian));
buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
@@ -4674,9 +4721,6 @@ static void init(CodeGen *g) {
g->builder = LLVMCreateBuilder();
g->dbuilder = ZigLLVMCreateDIBuilder(g->module, true);
ZigLLVMSetFastMath(g->builder, true);
Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING);
const char *flags = "";
unsigned runtime_version = 0;
Oops, something went wrong.

0 comments on commit 29b4882

Please sign in to comment.