Skip to content

Commit

Permalink
limit integer types to maximum bit width of 65535
Browse files Browse the repository at this point in the history
closes #1541
  • Loading branch information
andrewrk committed Nov 6, 2018
1 parent a08b657 commit 63f636e
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 145 deletions.
11 changes: 7 additions & 4 deletions doc/langref.html.in
Expand Up @@ -8,6 +8,7 @@
body{
background-color:#111;
color: #bbb;
font-family: sans-serif;
}
a {
color: #88f;
Expand Down Expand Up @@ -467,9 +468,10 @@ pub fn main() void {
<p>
In addition to the integer types above, arbitrary bit-width integers can be referenced by using
an identifier of <code>i</code> or </code>u</code> followed by digits. For example, the identifier
{#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer.
{#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
integer type is {#syntax#}65535{#endsyntax#}.
</p>
{#see_also|Integers|Floats|void|Errors#}
{#see_also|Integers|Floats|void|Errors|@IntType#}
{#header_close#}
{#header_open|Primitive Values#}
<div class="table-wrapper">
Expand Down Expand Up @@ -5814,9 +5816,10 @@ fn add(a: i32, b: i32) i32 { return a + b; }
{#header_close#}

{#header_open|@IntType#}
<pre>{#syntax#}@IntType(comptime is_signed: bool, comptime bit_count: u32) type{#endsyntax#}</pre>
<pre>{#syntax#}@IntType(comptime is_signed: bool, comptime bit_count: u16) type{#endsyntax#}</pre>
<p>
This function returns an integer type with the given signness and bit count.
This function returns an integer type with the given signness and bit count. The maximum
bit count for an integer type is {#syntax#}65535{#endsyntax#}.
</p>
{#header_close#}
{#header_open|@memberCount#}
Expand Down
1 change: 0 additions & 1 deletion src/all_types.hpp
Expand Up @@ -1222,7 +1222,6 @@ struct ZigType {
ZigLLVMDIType *di_type;

bool zero_bits; // this is denormalized data
bool is_copyable;
bool gen_h_loop_flag;

union {
Expand Down
68 changes: 24 additions & 44 deletions src/analyze.cpp
Expand Up @@ -367,23 +367,6 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
return LLVMSizeOfTypeInBits(g->target_data_ref, type_entry->type_ref);
}

Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry) {
Error err;
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return err;

if (!type_has_bits(type_entry))
return true;

if (!handle_is_ptr(type_entry))
return true;

if ((err = ensure_complete_type(g, type_entry)))
return err;

return type_entry->is_copyable;
}

static bool is_slice(ZigType *type) {
return type->id == ZigTypeIdStruct && type->data.structure.is_slice;
}
Expand Down Expand Up @@ -465,7 +448,6 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
assert(type_is_resolved(child_type, ResolveStatusZeroBitsKnown));

ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
entry->is_copyable = true;

const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";
const char *const_str = is_const ? "const " : "";
Expand Down Expand Up @@ -581,7 +563,6 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {

ZigType *entry = new_type_table_entry(ZigTypeIdOptional);
assert(child_type->type_ref || child_type->zero_bits);
entry->is_copyable = type_is_copyable(g, child_type).unwrap();

buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
Expand Down Expand Up @@ -671,7 +652,6 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
}

ZigType *entry = new_type_table_entry(ZigTypeIdErrorUnion);
entry->is_copyable = true;
assert(payload_type->di_type);
assert(type_is_complete(payload_type));

Expand Down Expand Up @@ -766,7 +746,6 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {

ZigType *entry = new_type_table_entry(ZigTypeIdArray);
entry->zero_bits = (array_size == 0) || child_type->zero_bits;
entry->is_copyable = false;

buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name));
Expand Down Expand Up @@ -831,7 +810,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
}

ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
entry->is_copyable = true;

// replace the & with [] to go from a ptr type name to a slice type name
buf_resize(&entry->name, 0);
Expand Down Expand Up @@ -986,7 +964,6 @@ ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const c
ImportTableEntry *import = scope ? get_scope_import(scope) : nullptr;
unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0;

entry->is_copyable = false;
entry->type_ref = LLVMInt8Type();
entry->di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder,
ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name),
Expand All @@ -1005,7 +982,6 @@ ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry) {
return fn_type->data.fn.bound_fn_parent;

ZigType *bound_fn_type = new_type_table_entry(ZigTypeIdBoundFn);
bound_fn_type->is_copyable = false;
bound_fn_type->data.bound_fn.fn_type = fn_type;
bound_fn_type->zero_bits = true;

Expand Down Expand Up @@ -1105,7 +1081,6 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
}

ZigType *fn_type = new_type_table_entry(ZigTypeIdFn);
fn_type->is_copyable = true;
fn_type->data.fn.fn_type_id = *fn_type_id;

bool skip_debug_info = false;
Expand Down Expand Up @@ -1318,7 +1293,6 @@ ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {

ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
ZigType *fn_type = new_type_table_entry(ZigTypeIdFn);
fn_type->is_copyable = false;
buf_resize(&fn_type->name, 0);
if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
const char *async_allocator_type_str = (fn_type->data.fn.fn_type_id.async_allocator_type == nullptr) ?
Expand Down Expand Up @@ -1526,7 +1500,6 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) {
ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
buf_resize(&err_set_type->name, 0);
buf_appendf(&err_set_type->name, "@typeOf(%s).ReturnType.ErrorSet", buf_ptr(&fn_entry->symbol_name));
err_set_type->is_copyable = true;
err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref;
err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type;
err_set_type->data.error_set.err_count = 0;
Expand Down Expand Up @@ -2846,7 +2819,6 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
tag_type = new_type_table_entry(ZigTypeIdEnum);
buf_resize(&tag_type->name, 0);
buf_appendf(&tag_type->name, "@TagType(%s)", buf_ptr(&union_type->name));
tag_type->is_copyable = true;
tag_type->type_ref = tag_int_type->type_ref;
tag_type->zero_bits = tag_int_type->zero_bits;

Expand Down Expand Up @@ -3366,10 +3338,10 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
}

{
ZigType *type = get_primitive_type(g, tld->name);
if (type != nullptr) {
ZigType *type;
if (get_primitive_type(g, tld->name, &type) != ErrorPrimitiveTypeNotFound) {
add_node_error(g, tld->source_node,
buf_sprintf("declaration shadows type '%s'", buf_ptr(&type->name)));
buf_sprintf("declaration shadows primitive type '%s'", buf_ptr(tld->name)));
}
}
}
Expand Down Expand Up @@ -3613,10 +3585,10 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
variable_entry->value->type = g->builtin_types.entry_invalid;
} else {
ZigType *type = get_primitive_type(g, name);
if (type != nullptr) {
ZigType *type;
if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
add_node_error(g, source_node,
buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
variable_entry->value->type = g->builtin_types.entry_invalid;
} else {
Scope *search_scope = nullptr;
Expand Down Expand Up @@ -4435,6 +4407,7 @@ void semantic_analyze(CodeGen *g) {
}

ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
assert(size_in_bits <= 65535);
TypeId type_id = {};
type_id.id = ZigTypeIdInt;
type_id.data.integer.is_signed = is_signed;
Expand Down Expand Up @@ -4523,7 +4496,7 @@ Buf *get_linux_libc_lib_path(const char *o_file) {
Termination term;
Buf *out_stderr = buf_alloc();
Buf *out_stdout = buf_alloc();
int err;
Error err;
if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
zig_panic("unable to determine libc lib path: executing C compiler: %s", err_str(err));
}
Expand Down Expand Up @@ -4552,7 +4525,7 @@ Buf *get_linux_libc_include_path(void) {
Termination term;
Buf *out_stderr = buf_alloc();
Buf *out_stdout = buf_alloc();
int err;
Error err;
if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
zig_panic("unable to determine libc include path: executing C compiler: %s", err_str(err));
}
Expand Down Expand Up @@ -5977,8 +5950,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
}

ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
assert(size_in_bits <= 65535);
ZigType *entry = new_type_table_entry(ZigTypeIdInt);
entry->is_copyable = true;
entry->type_ref = (size_in_bits == 0) ? LLVMVoidType() : LLVMIntType(size_in_bits);
entry->zero_bits = (size_in_bits == 0);

Expand Down Expand Up @@ -6455,7 +6428,10 @@ bool fn_type_can_fail(FnTypeId *fn_type_id) {
return type_can_fail(fn_type_id->return_type) || fn_type_id->cc == CallingConventionAsync;
}

ZigType *get_primitive_type(CodeGen *g, Buf *name) {
// ErrorNone - result pointer has the type
// ErrorOverflow - an integer primitive type has too large a bit width
// ErrorPrimitiveTypeNotFound - result pointer unchanged
Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result) {
if (buf_len(name) >= 2) {
uint8_t first_c = buf_ptr(name)[0];
if (first_c == 'i' || first_c == 'u') {
Expand All @@ -6466,18 +6442,22 @@ ZigType *get_primitive_type(CodeGen *g, Buf *name) {
}
}
bool is_signed = (first_c == 'i');
uint32_t bit_count = atoi(buf_ptr(name) + 1);
return get_int_type(g, is_signed, bit_count);
unsigned long int bit_count = strtoul(buf_ptr(name) + 1, nullptr, 10);
// strtoul returns ULONG_MAX on errors, so this comparison catches that as well.
if (bit_count >= 65536) return ErrorOverflow;
*result = get_int_type(g, is_signed, bit_count);
return ErrorNone;
}
}

not_integer:

auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
if (primitive_table_entry != nullptr) {
return primitive_table_entry->value;
}
return nullptr;
if (primitive_table_entry == nullptr)
return ErrorPrimitiveTypeNotFound;

*result = primitive_table_entry->value;
return ErrorNone;
}

Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents) {
Expand Down
4 changes: 1 addition & 3 deletions src/analyze.hpp
Expand Up @@ -9,7 +9,6 @@
#define ZIG_ANALYZE_HPP

#include "all_types.hpp"
#include "result.hpp"

void semantic_analyze(CodeGen *g);
ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
Expand Down Expand Up @@ -180,7 +179,6 @@ ZigTypeId type_id_at_index(size_t index);
size_t type_id_len();
size_t type_id_index(ZigType *entry);
ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry);
LinkLib *create_link_lib(Buf *name);
LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);

Expand All @@ -204,7 +202,7 @@ bool type_can_fail(ZigType *type_entry);
bool fn_eval_cacheable(Scope *scope, ZigType *return_type);
AstNode *type_decl_node(ZigType *type_entry);

ZigType *get_primitive_type(CodeGen *g, Buf *name);
Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result);

bool calling_convention_allows_zig_types(CallingConvention cc);
const char *calling_convention_name(CallingConvention cc);
Expand Down
6 changes: 3 additions & 3 deletions src/codegen.cpp
Expand Up @@ -7326,7 +7326,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));

ZigList<ErrorMsg *> errors = {0};
int err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr);
Error err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr);

if (err == ErrorCCompileErrors && errors.length > 0) {
for (size_t i = 0; i < errors.length; i += 1) {
Expand Down Expand Up @@ -7446,7 +7446,7 @@ static void gen_root_source(CodeGen *g) {
return;

Buf *source_code = buf_alloc();
int err;
Error err;
// No need for using the caching system for this file fetch because it is handled
// separately.
if ((err = os_fetch_file_path(resolved_path, source_code, true))) {
Expand Down Expand Up @@ -7514,7 +7514,7 @@ void codegen_add_assembly(CodeGen *g, Buf *path) {

static void gen_global_asm(CodeGen *g) {
Buf contents = BUF_INIT;
int err;
Error err;
for (size_t i = 0; i < g->assembly_files.length; i += 1) {
Buf *asm_file = g->assembly_files.at(i);
// No need to use the caching system for these fetches because they
Expand Down
5 changes: 3 additions & 2 deletions src/error.cpp
Expand Up @@ -7,8 +7,8 @@

#include "error.hpp"

const char *err_str(int err) {
switch ((enum Error)err) {
const char *err_str(Error err) {
switch (err) {
case ErrorNone: return "(no error)";
case ErrorNoMem: return "out of memory";
case ErrorInvalidFormat: return "invalid format";
Expand All @@ -32,6 +32,7 @@ const char *err_str(int err) {
case ErrorUnsupportedOperatingSystem: return "unsupported operating system";
case ErrorSharingViolation: return "sharing violation";
case ErrorPipeBusy: return "pipe busy";
case ErrorPrimitiveTypeNotFound: return "primitive type not found";
}
return "(invalid error)";
}
9 changes: 8 additions & 1 deletion src/error.hpp
Expand Up @@ -8,6 +8,8 @@
#ifndef ERROR_HPP
#define ERROR_HPP

#include <assert.h>

enum Error {
ErrorNone,
ErrorNoMem,
Expand All @@ -32,8 +34,13 @@ enum Error {
ErrorUnsupportedOperatingSystem,
ErrorSharingViolation,
ErrorPipeBusy,
ErrorPrimitiveTypeNotFound,
};

const char *err_str(int err);
const char *err_str(Error err);

static inline void assertNoError(Error err) {
assert(err == ErrorNone);
}

#endif

0 comments on commit 63f636e

Please sign in to comment.