aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-01-05 06:30:49 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-01-05 06:30:49 -0700
commit3327b0488d869710940bbd834a3d1e41758a61b5 (patch)
tree7b50f83acf3de1ca558d92fbf3cfea681b36d312 /src
parenta11d0aaf62e3ebf2f46307d1546b8105792c8dd0 (diff)
downloadzig-3327b0488d869710940bbd834a3d1e41758a61b5.tar.gz
zig-3327b0488d869710940bbd834a3d1e41758a61b5.zip
add #min_value() and #max_value()
Diffstat (limited to 'src')
-rw-r--r--src/analyze.cpp66
-rw-r--r--src/codegen.cpp56
2 files changed, 102 insertions, 20 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 27772f6ef1..2bffcee8c8 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1482,7 +1482,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
}
if (implicit_type == nullptr && variable_declaration->is_const) {
- add_node_error(g, source_node, buf_sprintf("variables must have initial values or be declared 'mut'."));
+ add_node_error(g, source_node, buf_sprintf("const variable missing initialization"));
implicit_type = g->builtin_types.entry_invalid;
}
@@ -1684,23 +1684,44 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
node->data.if_var_expr.then_block, node->data.if_var_expr.else_node, node);
}
+static TypeTableEntry *analyze_min_max_value(CodeGen *g, AstNode *node, TypeTableEntry *type_entry,
+ const char *err_format)
+{
+ if (type_entry->id == TypeTableEntryIdInt ||
+ type_entry->id == TypeTableEntryIdFloat ||
+ type_entry->id == TypeTableEntryIdBool)
+ {
+ return type_entry;
+ } else {
+ add_node_error(g, node,
+ buf_sprintf(err_format, buf_ptr(&type_entry->name)));
+ return g->builtin_types.entry_invalid;
+ }
+}
+
static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node)
{
assert(node->type == NodeTypeCompilerFnType);
Buf *name = &node->data.compiler_fn_type.name;
+ TypeTableEntry *type_entry = resolve_type(g, node->data.compiler_fn_type.type, import, context);
+
if (buf_eql_str(name, "sizeof")) {
- TypeTableEntry *type_entry = resolve_type(g, node->data.compiler_fn_type.type, import, context);
uint64_t size_in_bytes = type_entry->size_in_bits / 8;
TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, size_in_bytes);
NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node;
assert(!codegen_num_lit->resolved_type);
- codegen_num_lit->resolved_type = resolve_type_compatibility(g, context, node, expected_type, num_lit_type);
+ codegen_num_lit->resolved_type = resolve_type_compatibility(g, context, node,
+ expected_type, num_lit_type);
return num_lit_type;
+ } else if (buf_eql_str(name, "min_value")) {
+ return analyze_min_max_value(g, node, type_entry, "no min value available for type '%s'");
+ } else if (buf_eql_str(name, "max_value")) {
+ return analyze_min_max_value(g, node, type_entry, "no max value available for type '%s'");
} else {
add_node_error(g, node,
buf_sprintf("invalid compiler function: '%s'", buf_ptr(name)));
@@ -1966,16 +1987,43 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
break;
case PrefixOpBinNot:
{
- // TODO: don't require i32
- analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.prefix_op_expr.primary_expr);
- return_type = g->builtin_types.entry_i32;
+ AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
+ TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
+ operand_node);
+ if (expr_type->id == TypeTableEntryIdInvalid) {
+ return_type = expr_type;
+ } else if (expr_type->id == TypeTableEntryIdInt ||
+ (expr_type->id == TypeTableEntryIdNumberLiteral &&
+ !is_num_lit_float(expr_type->data.num_lit.kind)))
+ {
+ return_type = expr_type;
+ } else {
+ add_node_error(g, operand_node, buf_sprintf("invalid binary not type: '%s'",
+ buf_ptr(&expr_type->name)));
+ return_type = g->builtin_types.entry_invalid;
+ }
break;
}
case PrefixOpNegation:
{
- // TODO: don't require i32
- analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.prefix_op_expr.primary_expr);
- return_type = g->builtin_types.entry_i32;
+ AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
+ TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
+ operand_node);
+ if (expr_type->id == TypeTableEntryIdInvalid) {
+ return_type = expr_type;
+ } else if (expr_type->id == TypeTableEntryIdInt &&
+ expr_type->data.integral.is_signed)
+ {
+ return_type = expr_type;
+ } else if (expr_type->id == TypeTableEntryIdFloat) {
+ return_type = expr_type;
+ } else if (expr_type->id == TypeTableEntryIdNumberLiteral) {
+ return_type = expr_type;
+ } else {
+ add_node_error(g, operand_node, buf_sprintf("invalid negation type: '%s'",
+ buf_ptr(&expr_type->name)));
+ return_type = g->builtin_types.entry_invalid;
+ }
break;
}
case PrefixOpAddressOf:
diff --git a/src/codegen.cpp b/src/codegen.cpp
index bc9462ae99..9c2cf3c88f 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -859,28 +859,38 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
if (else_node) {
LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then");
LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Else");
- LLVMBasicBlockRef endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
+
+ LLVMBasicBlockRef endif_block;
+ bool then_endif_reachable = get_expr_type(then_node)->id != TypeTableEntryIdUnreachable;
+ bool else_endif_reachable = get_expr_type(else_node)->id != TypeTableEntryIdUnreachable;
+ if (then_endif_reachable || else_endif_reachable) {
+ endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
+ }
LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
LLVMPositionBuilderAtEnd(g->builder, then_block);
LLVMValueRef then_expr_result = gen_expr(g, then_node);
- if (get_expr_type(then_node)->id != TypeTableEntryIdUnreachable)
+ if (then_endif_reachable) {
LLVMBuildBr(g->builder, endif_block);
+ }
LLVMPositionBuilderAtEnd(g->builder, else_block);
LLVMValueRef else_expr_result = gen_expr(g, else_node);
- if (get_expr_type(else_node)->id != TypeTableEntryIdUnreachable)
+ if (else_endif_reachable) {
LLVMBuildBr(g->builder, endif_block);
+ }
- LLVMPositionBuilderAtEnd(g->builder, endif_block);
- if (use_expr_value) {
- LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
- LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
- LLVMBasicBlockRef incoming_blocks[2] = {then_block, else_block};
- LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
+ if (then_endif_reachable || else_endif_reachable) {
+ LLVMPositionBuilderAtEnd(g->builder, endif_block);
+ if (use_expr_value) {
+ LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
+ LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
+ LLVMBasicBlockRef incoming_blocks[2] = {then_block, else_block};
+ LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
- return phi;
+ return phi;
+ }
}
return nullptr;
@@ -1245,14 +1255,38 @@ static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeCompilerFnType);
Buf *name = &node->data.compiler_fn_type.name;
+ TypeTableEntry *type_entry = get_type_for_type_node(g, node->data.compiler_fn_type.type);
if (buf_eql_str(name, "sizeof")) {
- TypeTableEntry *type_entry = get_type_for_type_node(g, node->data.compiler_fn_type.type);
NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node;
AstNodeNumberLiteral num_lit_node;
num_lit_node.kind = type_entry->data.num_lit.kind;
num_lit_node.overflow = false;
num_lit_node.data.x_uint = type_entry->size_in_bits / 8;
return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node);
+ } else if (buf_eql_str(name, "min_value")) {
+ if (type_entry->id == TypeTableEntryIdInt) {
+ if (type_entry->data.integral.is_signed) {
+ return LLVMConstInt(type_entry->type_ref, 1ULL << (type_entry->size_in_bits - 1), false);
+ } else {
+ return LLVMConstNull(type_entry->type_ref);
+ }
+ } else if (type_entry->id == TypeTableEntryIdFloat) {
+ zig_panic("TODO codegen min_value float");
+ } else {
+ zig_unreachable();
+ }
+ } else if (buf_eql_str(name, "max_value")) {
+ if (type_entry->id == TypeTableEntryIdInt) {
+ if (type_entry->data.integral.is_signed) {
+ return LLVMConstInt(type_entry->type_ref, (1ULL << (type_entry->size_in_bits - 1)) - 1, false);
+ } else {
+ return LLVMConstAllOnes(type_entry->type_ref);
+ }
+ } else if (type_entry->id == TypeTableEntryIdFloat) {
+ zig_panic("TODO codegen max_value float");
+ } else {
+ zig_unreachable();
+ }
} else {
zig_unreachable();
}