diff --git a/doc/langref.html.in b/doc/langref.html.in
index 32481ade50..4359cadb58 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -1565,7 +1565,7 @@ var foo: u8 align(4) = 100;
test "global variable alignment" {
assert(@typeOf(&foo).alignment == 4);
assert(@typeOf(&foo) == *align(4) u8);
- const slice = (&foo)[0..1];
+ const slice = (*[1]u8)(&foo)[0..];
assert(@typeOf(slice) == []align(4) u8);
}
@@ -1671,7 +1671,7 @@ test "using slices for strings" {
test "slice pointer" {
var array: [10]u8 = undefined;
- const ptr = &array[0];
+ const ptr = &array;
// You can use slicing syntax to convert a pointer into a slice:
const slice = ptr[0..5];
@@ -4893,10 +4893,10 @@ pub const TypeId = enum {
Pointer,
Array,
Struct,
- FloatLiteral,
- IntLiteral,
- UndefinedLiteral,
- NullLiteral,
+ ComptimeFloat,
+ ComptimeInt,
+ Undefined,
+ Null,
Nullable,
ErrorUnion,
Error,
@@ -4927,10 +4927,10 @@ pub const TypeInfo = union(TypeId) {
Pointer: Pointer,
Array: Array,
Struct: Struct,
- FloatLiteral: void,
- IntLiteral: void,
- UndefinedLiteral: void,
- NullLiteral: void,
+ ComptimeFloat: void,
+ ComptimeInt: void,
+ Undefined: void,
+ Null: void,
Nullable: Nullable,
ErrorUnion: ErrorUnion,
ErrorSet: ErrorSet,
@@ -5685,10 +5685,10 @@ pub const TypeId = enum {
Pointer,
Array,
Struct,
- FloatLiteral,
- IntLiteral,
- UndefinedLiteral,
- NullLiteral,
+ ComptimeFloat,
+ ComptimeInt,
+ Undefined,
+ Null,
Nullable,
ErrorUnion,
ErrorSet,
@@ -5713,10 +5713,10 @@ pub const TypeInfo = union(TypeId) {
Pointer: Pointer,
Array: Array,
Struct: Struct,
- FloatLiteral: void,
- IntLiteral: void,
- UndefinedLiteral: void,
- NullLiteral: void,
+ ComptimeFloat: void,
+ ComptimeInt: void,
+ Undefined: void,
+ Null: void,
Nullable: Nullable,
ErrorUnion: ErrorUnion,
ErrorSet: ErrorSet,
@@ -6004,9 +6004,12 @@ const c = @cImport({
{#code_begin|syntax#}
const base64 = @import("std").base64;
-export fn decode_base_64(dest_ptr: *u8, dest_len: usize,
- source_ptr: *const u8, source_len: usize) usize
-{
+export fn decode_base_64(
+ dest_ptr: [*]u8,
+ dest_len: usize,
+ source_ptr: [*]const u8,
+ source_len: usize,
+) usize {
const src = source_ptr[0..source_len];
const dest = dest_ptr[0..dest_len];
const base64_decoder = base64.standard_decoder_unsafe;
diff --git a/example/mix_o_files/base64.zig b/example/mix_o_files/base64.zig
index 35b090825b..7ded9824a0 100644
--- a/example/mix_o_files/base64.zig
+++ b/example/mix_o_files/base64.zig
@@ -1,6 +1,6 @@
const base64 = @import("std").base64;
-export fn decode_base_64(dest_ptr: *u8, dest_len: usize, source_ptr: *const u8, source_len: usize) usize {
+export fn decode_base_64(dest_ptr: [*]u8, dest_len: usize, source_ptr: [*]const u8, source_len: usize) usize {
const src = source_ptr[0..source_len];
const dest = dest_ptr[0..dest_len];
const base64_decoder = base64.standard_decoder_unsafe;
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 5db1e7ea79..f05a44ad2d 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -83,6 +83,7 @@ enum ConstParentId {
ConstParentIdStruct,
ConstParentIdArray,
ConstParentIdUnion,
+ ConstParentIdScalar,
};
struct ConstParent {
@@ -100,6 +101,9 @@ struct ConstParent {
struct {
ConstExprValue *union_val;
} p_union;
+ struct {
+ ConstExprValue *scalar_val;
+ } p_scalar;
} data;
};
@@ -578,6 +582,7 @@ enum CastOp {
CastOpBytesToSlice,
CastOpNumLitToConcrete,
CastOpErrSet,
+ CastOpBitCast,
};
struct AstNodeFnCallExpr {
@@ -1154,10 +1159,10 @@ enum TypeTableEntryId {
TypeTableEntryIdPointer,
TypeTableEntryIdArray,
TypeTableEntryIdStruct,
- TypeTableEntryIdNumLitFloat,
- TypeTableEntryIdNumLitInt,
- TypeTableEntryIdUndefLit,
- TypeTableEntryIdNullLit,
+ TypeTableEntryIdComptimeFloat,
+ TypeTableEntryIdComptimeInt,
+ TypeTableEntryIdUndefined,
+ TypeTableEntryIdNull,
TypeTableEntryIdMaybe,
TypeTableEntryIdErrorUnion,
TypeTableEntryIdErrorSet,
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 2b9d776e78..8008bea68d 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -232,10 +232,10 @@ bool type_is_complete(TypeTableEntry *type_entry) {
case TypeTableEntryIdFloat:
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -268,10 +268,10 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
case TypeTableEntryIdFloat:
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -1333,10 +1333,10 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
zig_unreachable();
case TypeTableEntryIdMetaType:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
case TypeTableEntryIdNamespace:
@@ -1374,10 +1374,10 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
case TypeTableEntryIdInvalid:
zig_unreachable();
case TypeTableEntryIdMetaType:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
case TypeTableEntryIdNamespace:
@@ -1511,15 +1511,15 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
case TypeTableEntryIdInvalid:
return g->builtin_types.entry_invalid;
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdArgTuple:
case TypeTableEntryIdOpaque:
add_node_error(g, param_node->data.param_decl.type,
buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name)));
return g->builtin_types.entry_invalid;
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
@@ -1599,16 +1599,16 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
case TypeTableEntryIdInvalid:
zig_unreachable();
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdArgTuple:
case TypeTableEntryIdOpaque:
add_node_error(g, fn_proto->return_type,
buf_sprintf("return type '%s' not allowed", buf_ptr(&fn_type_id.return_type->name)));
return g->builtin_types.entry_invalid;
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
@@ -1860,7 +1860,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
}
assert(!struct_type->data.structure.zero_bits_loop_flag);
- assert(struct_type->data.structure.fields);
+ assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
assert(decl_node->type == NodeTypeContainerDecl);
size_t field_count = struct_type->data.structure.src_field_count;
@@ -2677,8 +2677,8 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
return;
}
tag_type = enum_type;
+ abi_alignment_so_far = get_abi_alignment(g, enum_type); // this populates src_field_count
covered_enum_fields = allocate(enum_type->data.enumeration.src_field_count);
- abi_alignment_so_far = get_abi_alignment(g, enum_type);
} else {
tag_type = nullptr;
abi_alignment_so_far = 0;
@@ -3337,16 +3337,16 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
case TypeTableEntryIdInvalid:
return g->builtin_types.entry_invalid;
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdBlock:
case TypeTableEntryIdArgTuple:
case TypeTableEntryIdOpaque:
add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed",
buf_ptr(&type_entry->name)));
return g->builtin_types.entry_invalid;
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdMetaType:
case TypeTableEntryIdVoid:
@@ -3480,12 +3480,12 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
implicit_type = g->builtin_types.entry_invalid;
} else if ((!is_const || linkage == VarLinkageExternal) &&
- (implicit_type->id == TypeTableEntryIdNumLitFloat ||
- implicit_type->id == TypeTableEntryIdNumLitInt))
+ (implicit_type->id == TypeTableEntryIdComptimeFloat ||
+ implicit_type->id == TypeTableEntryIdComptimeInt))
{
add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
implicit_type = g->builtin_types.entry_invalid;
- } else if (implicit_type->id == TypeTableEntryIdNullLit) {
+ } else if (implicit_type->id == TypeTableEntryIdNull) {
add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
implicit_type = g->builtin_types.entry_invalid;
} else if (implicit_type->id == TypeTableEntryIdMetaType && !is_const) {
@@ -3730,10 +3730,10 @@ static bool is_container(TypeTableEntry *type_entry) {
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
case TypeTableEntryIdArray:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -3779,10 +3779,10 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
case TypeTableEntryIdArray:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -4283,10 +4283,10 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
switch (type_entry->id) {
case TypeTableEntryIdInvalid:
case TypeTableEntryIdMetaType:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
@@ -4568,7 +4568,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
case TypeTableEntryIdVoid:
return (uint32_t)4149439618;
case TypeTableEntryIdInt:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeInt:
{
uint32_t result = 1331471175;
for (size_t i = 0; i < const_val->data.x_bigint.digit_count; i += 1) {
@@ -4609,7 +4609,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
default:
zig_unreachable();
}
- case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdComptimeFloat:
{
float128_t f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);
uint32_t ints[4];
@@ -4672,9 +4672,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
case TypeTableEntryIdPromise:
// TODO better hashing algorithm
return 223048345;
- case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdUndefined:
return 162837799;
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdNull:
return 844854567;
case TypeTableEntryIdArray:
// TODO better hashing algorithm
@@ -4754,10 +4754,10 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdFn:
@@ -4819,10 +4819,10 @@ static bool return_type_is_cacheable(TypeTableEntry *return_type) {
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdFn:
@@ -4930,10 +4930,10 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
case TypeTableEntryIdInvalid:
case TypeTableEntryIdOpaque:
zig_unreachable();
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMetaType:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
@@ -5070,7 +5070,7 @@ ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {
void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value) {
const_val->special = ConstValSpecialStatic;
const_val->type = type;
- if (type->id == TypeTableEntryIdNumLitFloat) {
+ if (type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_init_64(&const_val->data.x_bigfloat, value);
} else if (type->id == TypeTableEntryIdFloat) {
switch (type->data.floating.bit_count) {
@@ -5158,7 +5158,8 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
const_val->type = get_slice_type(g, ptr_type);
const_val->data.x_struct.fields = create_const_vals(2);
- init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const);
+ init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const,
+ PtrLenUnknown);
init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len);
}
@@ -5169,21 +5170,24 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
}
void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
- size_t elem_index, bool is_const)
+ size_t elem_index, bool is_const, PtrLen ptr_len)
{
assert(array_val->type->id == TypeTableEntryIdArray);
TypeTableEntry *child_type = array_val->type->data.array.child_type;
const_val->special = ConstValSpecialStatic;
- const_val->type = get_pointer_to_type(g, child_type, is_const);
+ const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,
+ ptr_len, get_abi_alignment(g, child_type), 0, 0);
const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
const_val->data.x_ptr.data.base_array.array_val = array_val;
const_val->data.x_ptr.data.base_array.elem_index = elem_index;
}
-ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const) {
+ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const,
+ PtrLen ptr_len)
+{
ConstExprValue *const_val = create_const_vals(1);
- init_const_ptr_array(g, const_val, array_val, elem_index, is_const);
+ init_const_ptr_array(g, const_val, array_val, elem_index, is_const, ptr_len);
return const_val;
}
@@ -5346,10 +5350,10 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
default:
zig_unreachable();
}
- case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdComptimeFloat:
return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ;
case TypeTableEntryIdInt:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeInt:
return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ;
case TypeTableEntryIdPointer:
case TypeTableEntryIdFn:
@@ -5406,9 +5410,9 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
return false;
}
return true;
- case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdUndefined:
zig_panic("TODO");
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdNull:
zig_panic("TODO");
case TypeTableEntryIdMaybe:
if (a->data.x_maybe == nullptr || b->data.x_maybe == nullptr) {
@@ -5510,7 +5514,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
case TypeTableEntryIdVoid:
buf_appendf(buf, "{}");
return;
- case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdComptimeFloat:
bigfloat_append_buf(buf, &const_val->data.x_bigfloat);
return;
case TypeTableEntryIdFloat:
@@ -5538,7 +5542,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
default:
zig_unreachable();
}
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdInt:
bigint_append_buf(buf, &const_val->data.x_bigint, 10);
return;
@@ -5642,12 +5646,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
buf_appendf(buf, "}");
return;
}
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdNull:
{
buf_appendf(buf, "null");
return;
}
- case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdUndefined:
{
buf_appendf(buf, "undefined");
return;
@@ -5757,10 +5761,10 @@ uint32_t type_id_hash(TypeId x) {
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdFloat:
case TypeTableEntryIdStruct:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorSet:
case TypeTableEntryIdEnum:
@@ -5803,10 +5807,10 @@ bool type_id_eql(TypeId a, TypeId b) {
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdFloat:
case TypeTableEntryIdStruct:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdPromise:
case TypeTableEntryIdErrorSet:
@@ -5925,10 +5929,10 @@ static const TypeTableEntryId all_type_ids[] = {
TypeTableEntryIdPointer,
TypeTableEntryIdArray,
TypeTableEntryIdStruct,
- TypeTableEntryIdNumLitFloat,
- TypeTableEntryIdNumLitInt,
- TypeTableEntryIdUndefLit,
- TypeTableEntryIdNullLit,
+ TypeTableEntryIdComptimeFloat,
+ TypeTableEntryIdComptimeInt,
+ TypeTableEntryIdUndefined,
+ TypeTableEntryIdNull,
TypeTableEntryIdMaybe,
TypeTableEntryIdErrorUnion,
TypeTableEntryIdErrorSet,
@@ -5976,13 +5980,13 @@ size_t type_id_index(TypeTableEntry *entry) {
if (entry->data.structure.is_slice)
return 25;
return 8;
- case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdComptimeFloat:
return 9;
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeInt:
return 10;
- case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdUndefined:
return 11;
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdNull:
return 12;
case TypeTableEntryIdMaybe:
return 13;
@@ -6034,14 +6038,14 @@ const char *type_id_name(TypeTableEntryId id) {
return "Array";
case TypeTableEntryIdStruct:
return "Struct";
- case TypeTableEntryIdNumLitFloat:
- return "FloatLiteral";
- case TypeTableEntryIdNumLitInt:
- return "IntLiteral";
- case TypeTableEntryIdUndefLit:
- return "UndefinedLiteral";
- case TypeTableEntryIdNullLit:
- return "NullLiteral";
+ case TypeTableEntryIdComptimeFloat:
+ return "ComptimeFloat";
+ case TypeTableEntryIdComptimeInt:
+ return "ComptimeInt";
+ case TypeTableEntryIdUndefined:
+ return "Undefined";
+ case TypeTableEntryIdNull:
+ return "Null";
case TypeTableEntryIdMaybe:
return "Nullable";
case TypeTableEntryIdErrorUnion:
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 905bfa86dd..25bda198d6 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -152,8 +152,9 @@ ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *poi
size_t addr, bool is_const);
void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
- size_t elem_index, bool is_const);
-ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const);
+ size_t elem_index, bool is_const, PtrLen ptr_len);
+ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index,
+ bool is_const, PtrLen ptr_len);
void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
size_t start, size_t len, bool is_const);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 01108de534..ac73db7b26 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2541,6 +2541,8 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
add_error_range_check(g, wanted_type, g->err_tag_type, expr_val);
}
return expr_val;
+ case CastOpBitCast:
+ return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
}
zig_unreachable();
}
@@ -2823,7 +2825,13 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on;
- if (array_type->id == TypeTableEntryIdArray) {
+ if (array_type->id == TypeTableEntryIdArray ||
+ (array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
+ {
+ if (array_type->id == TypeTableEntryIdPointer) {
+ assert(array_type->data.pointer.child_type->id == TypeTableEntryIdArray);
+ array_type = array_type->data.pointer.child_type;
+ }
if (safety_check_on) {
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
array_type->data.array.len, false);
@@ -3709,7 +3717,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
- if (array_type->id == TypeTableEntryIdArray) {
+ if (array_type->id == TypeTableEntryIdArray ||
+ (array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
+ {
+ if (array_type->id == TypeTableEntryIdPointer) {
+ array_type = array_type->data.pointer.child_type;
+ }
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
LLVMValueRef end_val;
if (instruction->end) {
@@ -3750,6 +3763,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
return tmp_struct_ptr;
} else if (array_type->id == TypeTableEntryIdPointer) {
+ assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
LLVMValueRef end_val = ir_llvm_value(g, instruction->end);
@@ -4727,7 +4741,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
-static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *array_const_val);
+static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
switch (parent->id) {
@@ -4743,6 +4757,10 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
parent->data.p_array.elem_index);
case ConstParentIdUnion:
return gen_const_ptr_union_recursive(g, parent->data.p_union.union_val);
+ case ConstParentIdScalar:
+ render_const_val(g, parent->data.p_scalar.scalar_val, "");
+ render_const_val_global(g, parent->data.p_scalar.scalar_val, "");
+ return parent->data.p_scalar.scalar_val->global_refs->llvm_global;
}
zig_unreachable();
}
@@ -4768,7 +4786,8 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
};
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
} else {
- zig_unreachable();
+ assert(parent->id == ConstParentIdScalar);
+ return base_ptr;
}
}
@@ -4812,10 +4831,10 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
case TypeTableEntryIdInvalid:
case TypeTableEntryIdMetaType:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
case TypeTableEntryIdNamespace:
@@ -5258,10 +5277,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
case TypeTableEntryIdInvalid:
case TypeTableEntryIdMetaType:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
@@ -5500,7 +5519,7 @@ static void do_code_gen(CodeGen *g) {
TldVar *tld_var = g->global_vars.at(i);
VariableTableEntry *var = tld_var->var;
- if (var->value->type->id == TypeTableEntryIdNumLitFloat) {
+ if (var->value->type->id == TypeTableEntryIdComptimeFloat) {
// Generate debug info for it but that's it.
ConstExprValue *const_val = var->value;
assert(const_val->special != ConstValSpecialRuntime);
@@ -5514,7 +5533,7 @@ static void do_code_gen(CodeGen *g) {
continue;
}
- if (var->value->type->id == TypeTableEntryIdNumLitInt) {
+ if (var->value->type->id == TypeTableEntryIdComptimeInt) {
// Generate debug info for it but that's it.
ConstExprValue *const_val = var->value;
assert(const_val->special != ConstValSpecialRuntime);
@@ -5908,25 +5927,27 @@ static void define_builtin_types(CodeGen *g) {
g->builtin_types.entry_block = entry;
}
{
- TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
- buf_init_from_str(&entry->name, "(float literal)");
+ TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdComptimeFloat);
+ buf_init_from_str(&entry->name, "comptime_float");
entry->zero_bits = true;
g->builtin_types.entry_num_lit_float = entry;
+ g->primitive_type_table.put(&entry->name, entry);
}
{
- TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitInt);
- buf_init_from_str(&entry->name, "(integer literal)");
+ TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdComptimeInt);
+ buf_init_from_str(&entry->name, "comptime_int");
entry->zero_bits = true;
g->builtin_types.entry_num_lit_int = entry;
+ g->primitive_type_table.put(&entry->name, entry);
}
{
- TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefLit);
+ TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefined);
buf_init_from_str(&entry->name, "(undefined)");
entry->zero_bits = true;
g->builtin_types.entry_undef = entry;
}
{
- TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNullLit);
+ TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNull);
buf_init_from_str(&entry->name, "(null)");
entry->zero_bits = true;
g->builtin_types.entry_null = entry;
@@ -6391,10 +6412,10 @@ static void define_builtin_compile_vars(CodeGen *g) {
" Slice: Slice,\n"
" Array: Array,\n"
" Struct: Struct,\n"
- " FloatLiteral: void,\n"
- " IntLiteral: void,\n"
- " UndefinedLiteral: void,\n"
- " NullLiteral: void,\n"
+ " ComptimeFloat: void,\n"
+ " ComptimeInt: void,\n"
+ " Undefined: void,\n"
+ " Null: void,\n"
" Nullable: Nullable,\n"
" ErrorUnion: ErrorUnion,\n"
" ErrorSet: ErrorSet,\n"
@@ -6966,10 +6987,10 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry
switch (type_entry->id) {
case TypeTableEntryIdInvalid:
case TypeTableEntryIdMetaType:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
@@ -7151,10 +7172,10 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdArgTuple:
case TypeTableEntryIdPromise:
zig_unreachable();
@@ -7303,11 +7324,11 @@ static void gen_h_file(CodeGen *g) {
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
case TypeTableEntryIdPointer:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdArray:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
case TypeTableEntryIdNamespace:
diff --git a/src/ir.cpp b/src/ir.cpp
index a230c60456..9578795fcc 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -107,6 +107,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, VariableTableEntry *var);
static TypeTableEntry *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op);
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
+static TypeTableEntry *adjust_ptr_align(CodeGen *g, TypeTableEntry *ptr_type, uint32_t new_align);
ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
assert(const_val->type->id == TypeTableEntryIdPointer);
@@ -6849,7 +6850,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
- IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_mem_ptr_maybe);
+ IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
+ get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
+ false, false, PtrLenUnknown, get_abi_alignment(irb->codegen, irb->codegen->builtin_types.entry_u8),
+ 0, 0));
+ IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
@@ -6940,14 +6945,14 @@ static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *so
}
static bool const_val_fits_in_num_lit(ConstExprValue *const_val, TypeTableEntry *num_lit_type) {
- return ((num_lit_type->id == TypeTableEntryIdNumLitFloat &&
- (const_val->type->id == TypeTableEntryIdFloat || const_val->type->id == TypeTableEntryIdNumLitFloat)) ||
- (num_lit_type->id == TypeTableEntryIdNumLitInt &&
- (const_val->type->id == TypeTableEntryIdInt || const_val->type->id == TypeTableEntryIdNumLitInt)));
+ return ((num_lit_type->id == TypeTableEntryIdComptimeFloat &&
+ (const_val->type->id == TypeTableEntryIdFloat || const_val->type->id == TypeTableEntryIdComptimeFloat)) ||
+ (num_lit_type->id == TypeTableEntryIdComptimeInt &&
+ (const_val->type->id == TypeTableEntryIdInt || const_val->type->id == TypeTableEntryIdComptimeInt)));
}
static bool float_has_fraction(ConstExprValue *const_val) {
- if (const_val->type->id == TypeTableEntryIdNumLitFloat) {
+ if (const_val->type->id == TypeTableEntryIdComptimeFloat) {
return bigfloat_has_fraction(&const_val->data.x_bigfloat);
} else if (const_val->type->id == TypeTableEntryIdFloat) {
switch (const_val->type->data.floating.bit_count) {
@@ -6970,7 +6975,7 @@ static bool float_has_fraction(ConstExprValue *const_val) {
}
static void float_append_buf(Buf *buf, ConstExprValue *const_val) {
- if (const_val->type->id == TypeTableEntryIdNumLitFloat) {
+ if (const_val->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_append_buf(buf, &const_val->data.x_bigfloat);
} else if (const_val->type->id == TypeTableEntryIdFloat) {
switch (const_val->type->data.floating.bit_count) {
@@ -7005,7 +7010,7 @@ static void float_append_buf(Buf *buf, ConstExprValue *const_val) {
}
static void float_init_bigint(BigInt *bigint, ConstExprValue *const_val) {
- if (const_val->type->id == TypeTableEntryIdNumLitFloat) {
+ if (const_val->type->id == TypeTableEntryIdComptimeFloat) {
bigint_init_bigfloat(bigint, &const_val->data.x_bigfloat);
} else if (const_val->type->id == TypeTableEntryIdFloat) {
switch (const_val->type->data.floating.bit_count) {
@@ -7041,7 +7046,7 @@ static void float_init_bigint(BigInt *bigint, ConstExprValue *const_val) {
}
static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) {
- if (dest_val->type->id == TypeTableEntryIdNumLitFloat) {
+ if (dest_val->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_init_bigfloat(&dest_val->data.x_bigfloat, bigfloat);
} else if (dest_val->type->id == TypeTableEntryIdFloat) {
switch (dest_val->type->data.floating.bit_count) {
@@ -7063,7 +7068,7 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) {
}
static void float_init_f32(ConstExprValue *dest_val, float x) {
- if (dest_val->type->id == TypeTableEntryIdNumLitFloat) {
+ if (dest_val->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_init_32(&dest_val->data.x_bigfloat, x);
} else if (dest_val->type->id == TypeTableEntryIdFloat) {
switch (dest_val->type->data.floating.bit_count) {
@@ -7089,7 +7094,7 @@ static void float_init_f32(ConstExprValue *dest_val, float x) {
}
static void float_init_f64(ConstExprValue *dest_val, double x) {
- if (dest_val->type->id == TypeTableEntryIdNumLitFloat) {
+ if (dest_val->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_init_64(&dest_val->data.x_bigfloat, x);
} else if (dest_val->type->id == TypeTableEntryIdFloat) {
switch (dest_val->type->data.floating.bit_count) {
@@ -7115,7 +7120,7 @@ static void float_init_f64(ConstExprValue *dest_val, double x) {
}
static void float_init_f128(ConstExprValue *dest_val, float128_t x) {
- if (dest_val->type->id == TypeTableEntryIdNumLitFloat) {
+ if (dest_val->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_init_128(&dest_val->data.x_bigfloat, x);
} else if (dest_val->type->id == TypeTableEntryIdFloat) {
switch (dest_val->type->data.floating.bit_count) {
@@ -7145,7 +7150,7 @@ static void float_init_f128(ConstExprValue *dest_val, float128_t x) {
}
static void float_init_float(ConstExprValue *dest_val, ConstExprValue *src_val) {
- if (src_val->type->id == TypeTableEntryIdNumLitFloat) {
+ if (src_val->type->id == TypeTableEntryIdComptimeFloat) {
float_init_bigfloat(dest_val, &src_val->data.x_bigfloat);
} else if (src_val->type->id == TypeTableEntryIdFloat) {
switch (src_val->type->data.floating.bit_count) {
@@ -7168,7 +7173,7 @@ static void float_init_float(ConstExprValue *dest_val, ConstExprValue *src_val)
static Cmp float_cmp(ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
- if (op1->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op1->type->id == TypeTableEntryIdComptimeFloat) {
return bigfloat_cmp(&op1->data.x_bigfloat, &op2->data.x_bigfloat);
} else if (op1->type->id == TypeTableEntryIdFloat) {
switch (op1->type->data.floating.bit_count) {
@@ -7205,7 +7210,7 @@ static Cmp float_cmp(ConstExprValue *op1, ConstExprValue *op2) {
}
static Cmp float_cmp_zero(ConstExprValue *op) {
- if (op->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op->type->id == TypeTableEntryIdComptimeFloat) {
return bigfloat_cmp_zero(&op->data.x_bigfloat);
} else if (op->type->id == TypeTableEntryIdFloat) {
switch (op->type->data.floating.bit_count) {
@@ -7246,7 +7251,7 @@ static Cmp float_cmp_zero(ConstExprValue *op) {
static void float_add(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
out_val->type = op1->type;
- if (op1->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op1->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_add(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
} else if (op1->type->id == TypeTableEntryIdFloat) {
switch (op1->type->data.floating.bit_count) {
@@ -7270,7 +7275,7 @@ static void float_add(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal
static void float_sub(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
out_val->type = op1->type;
- if (op1->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op1->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_sub(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
} else if (op1->type->id == TypeTableEntryIdFloat) {
switch (op1->type->data.floating.bit_count) {
@@ -7294,7 +7299,7 @@ static void float_sub(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal
static void float_mul(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
out_val->type = op1->type;
- if (op1->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op1->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_mul(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
} else if (op1->type->id == TypeTableEntryIdFloat) {
switch (op1->type->data.floating.bit_count) {
@@ -7318,7 +7323,7 @@ static void float_mul(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal
static void float_div(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
out_val->type = op1->type;
- if (op1->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op1->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_div(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
} else if (op1->type->id == TypeTableEntryIdFloat) {
switch (op1->type->data.floating.bit_count) {
@@ -7342,7 +7347,7 @@ static void float_div(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal
static void float_div_trunc(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
out_val->type = op1->type;
- if (op1->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op1->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_div_trunc(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
} else if (op1->type->id == TypeTableEntryIdFloat) {
switch (op1->type->data.floating.bit_count) {
@@ -7377,7 +7382,7 @@ static void float_div_trunc(ConstExprValue *out_val, ConstExprValue *op1, ConstE
static void float_div_floor(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
out_val->type = op1->type;
- if (op1->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op1->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_div_floor(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
} else if (op1->type->id == TypeTableEntryIdFloat) {
switch (op1->type->data.floating.bit_count) {
@@ -7402,7 +7407,7 @@ static void float_div_floor(ConstExprValue *out_val, ConstExprValue *op1, ConstE
static void float_rem(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
out_val->type = op1->type;
- if (op1->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op1->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_rem(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
} else if (op1->type->id == TypeTableEntryIdFloat) {
switch (op1->type->data.floating.bit_count) {
@@ -7426,7 +7431,7 @@ static void float_rem(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal
static void float_mod(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
out_val->type = op1->type;
- if (op1->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op1->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_mod(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
} else if (op1->type->id == TypeTableEntryIdFloat) {
switch (op1->type->data.floating.bit_count) {
@@ -7451,7 +7456,7 @@ static void float_mod(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal
static void float_negate(ConstExprValue *out_val, ConstExprValue *op) {
out_val->type = op->type;
- if (op->type->id == TypeTableEntryIdNumLitFloat) {
+ if (op->type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_negate(&out_val->data.x_bigfloat, &op->data.x_bigfloat);
} else if (op->type->id == TypeTableEntryIdFloat) {
switch (op->type->data.floating.bit_count) {
@@ -7525,9 +7530,9 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
assert(const_val->special != ConstValSpecialRuntime);
bool const_val_is_int = (const_val->type->id == TypeTableEntryIdInt ||
- const_val->type->id == TypeTableEntryIdNumLitInt);
+ const_val->type->id == TypeTableEntryIdComptimeInt);
bool const_val_is_float = (const_val->type->id == TypeTableEntryIdFloat ||
- const_val->type->id == TypeTableEntryIdNumLitFloat);
+ const_val->type->id == TypeTableEntryIdComptimeFloat);
if (other_type->id == TypeTableEntryIdFloat) {
return true;
} else if (other_type->id == TypeTableEntryIdInt && const_val_is_int) {
@@ -7571,7 +7576,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
return true;
}
}
- if (explicit_cast && (other_type->id == TypeTableEntryIdInt || other_type->id == TypeTableEntryIdNumLitInt) &&
+ if (explicit_cast && (other_type->id == TypeTableEntryIdInt || other_type->id == TypeTableEntryIdComptimeInt) &&
const_val_is_float)
{
if (float_has_fraction(const_val)) {
@@ -7584,7 +7589,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
buf_ptr(&other_type->name)));
return false;
} else {
- if (other_type->id == TypeTableEntryIdNumLitInt) {
+ if (other_type->id == TypeTableEntryIdComptimeInt) {
return true;
} else {
BigInt bigint;
@@ -7955,7 +7960,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
// implicit conversion from null literal to maybe type
if (expected_type->id == TypeTableEntryIdMaybe &&
- actual_type->id == TypeTableEntryIdNullLit)
+ actual_type->id == TypeTableEntryIdNull)
{
return ImplicitCastMatchResultYes;
}
@@ -8073,8 +8078,8 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
// implicit number literal to typed number
// implicit number literal to &const integer
- if (actual_type->id == TypeTableEntryIdNumLitFloat ||
- actual_type->id == TypeTableEntryIdNumLitInt)
+ if (actual_type->id == TypeTableEntryIdComptimeFloat ||
+ actual_type->id == TypeTableEntryIdComptimeInt)
{
if (expected_type->id == TypeTableEntryIdPointer &&
expected_type->data.pointer.is_const)
@@ -8094,9 +8099,9 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
// implicit typed number to integer or float literal.
// works when the number is known
if (value->value.special == ConstValSpecialStatic) {
- if (actual_type->id == TypeTableEntryIdInt && expected_type->id == TypeTableEntryIdNumLitInt) {
+ if (actual_type->id == TypeTableEntryIdInt && expected_type->id == TypeTableEntryIdComptimeInt) {
return ImplicitCastMatchResultYes;
- } else if (actual_type->id == TypeTableEntryIdFloat && expected_type->id == TypeTableEntryIdNumLitFloat) {
+ } else if (actual_type->id == TypeTableEntryIdFloat && expected_type->id == TypeTableEntryIdComptimeFloat) {
return ImplicitCastMatchResultYes;
}
}
@@ -8137,7 +8142,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
}
// implicit undefined literal to anything
- if (actual_type->id == TypeTableEntryIdUndefLit) {
+ if (actual_type->id == TypeTableEntryIdUndefined) {
return ImplicitCastMatchResultYes;
}
@@ -8185,7 +8190,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
}
}
- bool any_are_null = (prev_inst->value.type->id == TypeTableEntryIdNullLit);
+ bool any_are_null = (prev_inst->value.type->id == TypeTableEntryIdNull);
bool convert_to_const_slice = false;
for (size_t i = 1; i < instruction_count; i += 1) {
IrInstruction *cur_inst = instructions[i];
@@ -8464,12 +8469,12 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
}
}
- if (prev_type->id == TypeTableEntryIdNullLit) {
+ if (prev_type->id == TypeTableEntryIdNull) {
prev_inst = cur_inst;
continue;
}
- if (cur_type->id == TypeTableEntryIdNullLit) {
+ if (cur_type->id == TypeTableEntryIdNull) {
any_are_null = true;
continue;
}
@@ -8541,17 +8546,17 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
continue;
}
- if (cur_type->id == TypeTableEntryIdUndefLit) {
+ if (cur_type->id == TypeTableEntryIdUndefined) {
continue;
}
- if (prev_type->id == TypeTableEntryIdUndefLit) {
+ if (prev_type->id == TypeTableEntryIdUndefined) {
prev_inst = cur_inst;
continue;
}
- if (prev_type->id == TypeTableEntryIdNumLitInt ||
- prev_type->id == TypeTableEntryIdNumLitFloat)
+ if (prev_type->id == TypeTableEntryIdComptimeInt ||
+ prev_type->id == TypeTableEntryIdComptimeFloat)
{
if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type, false)) {
prev_inst = cur_inst;
@@ -8561,8 +8566,8 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
}
}
- if (cur_type->id == TypeTableEntryIdNumLitInt ||
- cur_type->id == TypeTableEntryIdNumLitFloat)
+ if (cur_type->id == TypeTableEntryIdComptimeInt ||
+ cur_type->id == TypeTableEntryIdComptimeFloat)
{
if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type, false)) {
continue;
@@ -8666,13 +8671,13 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
} else if (expected_type != nullptr && expected_type->id == TypeTableEntryIdErrorUnion) {
return get_error_union_type(ira->codegen, err_set_type, expected_type->data.error_union.payload_type);
} else {
- if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt ||
- prev_inst->value.type->id == TypeTableEntryIdNumLitFloat)
+ if (prev_inst->value.type->id == TypeTableEntryIdComptimeInt ||
+ prev_inst->value.type->id == TypeTableEntryIdComptimeFloat)
{
ir_add_error_node(ira, source_node,
buf_sprintf("unable to make error union out of number literal"));
return ira->codegen->builtin_types.entry_invalid;
- } else if (prev_inst->value.type->id == TypeTableEntryIdNullLit) {
+ } else if (prev_inst->value.type->id == TypeTableEntryIdNull) {
ir_add_error_node(ira, source_node,
buf_sprintf("unable to make error union out of null literal"));
return ira->codegen->builtin_types.entry_invalid;
@@ -8680,9 +8685,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type);
}
}
- } else if (any_are_null && prev_inst->value.type->id != TypeTableEntryIdNullLit) {
- if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt ||
- prev_inst->value.type->id == TypeTableEntryIdNumLitFloat)
+ } else if (any_are_null && prev_inst->value.type->id != TypeTableEntryIdNull) {
+ if (prev_inst->value.type->id == TypeTableEntryIdComptimeInt ||
+ prev_inst->value.type->id == TypeTableEntryIdComptimeFloat)
{
ir_add_error_node(ira, source_node,
buf_sprintf("unable to make maybe out of number literal"));
@@ -8729,6 +8734,7 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
case CastOpNoCast:
zig_unreachable();
case CastOpErrSet:
+ case CastOpBitCast:
zig_panic("TODO");
case CastOpNoop:
{
@@ -8737,7 +8743,7 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
break;
}
case CastOpNumLitToConcrete:
- if (other_val->type->id == TypeTableEntryIdNumLitFloat) {
+ if (other_val->type->id == TypeTableEntryIdComptimeFloat) {
assert(new_type->id == TypeTableEntryIdFloat);
switch (new_type->data.floating.bit_count) {
case 32:
@@ -8752,7 +8758,7 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
default:
zig_unreachable();
}
- } else if (other_val->type->id == TypeTableEntryIdNumLitInt) {
+ } else if (other_val->type->id == TypeTableEntryIdComptimeInt) {
bigint_init_bigint(&const_val->data.x_bigint, &other_val->data.x_bigint);
} else {
zig_unreachable();
@@ -9595,9 +9601,9 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
source_instr->source_node, wanted_type);
- if (wanted_type->id == TypeTableEntryIdNumLitFloat) {
+ if (wanted_type->id == TypeTableEntryIdComptimeFloat) {
float_init_float(&result->value, val);
- } else if (wanted_type->id == TypeTableEntryIdNumLitInt) {
+ } else if (wanted_type->id == TypeTableEntryIdComptimeInt) {
bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);
} else {
zig_unreachable();
@@ -9750,6 +9756,49 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
return result;
}
+static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
+ TypeTableEntry *wanted_type)
+{
+ assert(wanted_type->id == TypeTableEntryIdPointer);
+ wanted_type = adjust_ptr_align(ira->codegen, wanted_type, target->value.type->data.pointer.alignment);
+ TypeTableEntry *array_type = wanted_type->data.pointer.child_type;
+ assert(array_type->id == TypeTableEntryIdArray);
+ assert(array_type->data.array.len == 1);
+
+ if (instr_is_comptime(target)) {
+ ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+
+ assert(val->type->id == TypeTableEntryIdPointer);
+ ConstExprValue *pointee = const_ptr_pointee(ira->codegen, val);
+ if (pointee->special != ConstValSpecialRuntime) {
+ ConstExprValue *array_val = create_const_vals(1);
+ array_val->special = ConstValSpecialStatic;
+ array_val->type = array_type;
+ array_val->data.x_array.special = ConstArraySpecialNone;
+ array_val->data.x_array.s_none.elements = pointee;
+ array_val->data.x_array.s_none.parent.id = ConstParentIdScalar;
+ array_val->data.x_array.s_none.parent.data.p_scalar.scalar_val = pointee;
+
+ IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
+ source_instr->scope, source_instr->source_node);
+ const_instruction->base.value.type = wanted_type;
+ const_instruction->base.value.special = ConstValSpecialStatic;
+ const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialRef;
+ const_instruction->base.value.data.x_ptr.data.ref.pointee = array_val;
+ const_instruction->base.value.data.x_ptr.mut = val->data.x_ptr.mut;
+ return &const_instruction->base;
+ }
+ }
+
+ // pointer to array and pointer to single item are represented the same way at runtime
+ IrInstruction *result = ir_build_cast(&ira->new_irb, target->scope, target->source_node,
+ wanted_type, target, CastOpBitCast);
+ result->value.type = wanted_type;
+ return result;
+}
+
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
TypeTableEntry *wanted_type, IrInstruction *value)
{
@@ -9929,8 +9978,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
TypeTableEntry *wanted_child_type = wanted_type->data.maybe.child_type;
if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node).id == ConstCastResultIdOk) {
return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
- } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
- actual_type->id == TypeTableEntryIdNumLitFloat)
+ } else if (actual_type->id == TypeTableEntryIdComptimeInt ||
+ actual_type->id == TypeTableEntryIdComptimeFloat)
{
if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
@@ -9955,7 +10004,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
// explicit cast from null literal to maybe type
if (wanted_type->id == TypeTableEntryIdMaybe &&
- actual_type->id == TypeTableEntryIdNullLit)
+ actual_type->id == TypeTableEntryIdNull)
{
return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
}
@@ -9964,8 +10013,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (wanted_type->id == TypeTableEntryIdErrorUnion) {
if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type, source_node).id == ConstCastResultIdOk) {
return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
- } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
- actual_type->id == TypeTableEntryIdNumLitFloat)
+ } else if (actual_type->id == TypeTableEntryIdComptimeInt ||
+ actual_type->id == TypeTableEntryIdComptimeFloat)
{
if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
@@ -10012,9 +10061,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
{
TypeTableEntry *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node).id == ConstCastResultIdOk ||
- actual_type->id == TypeTableEntryIdNullLit ||
- actual_type->id == TypeTableEntryIdNumLitInt ||
- actual_type->id == TypeTableEntryIdNumLitFloat)
+ actual_type->id == TypeTableEntryIdNull ||
+ actual_type->id == TypeTableEntryIdComptimeInt ||
+ actual_type->id == TypeTableEntryIdComptimeFloat)
{
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
if (type_is_invalid(cast1->value.type))
@@ -10030,8 +10079,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
// explicit cast from number literal to another type
// explicit cast from number literal to &const integer
- if (actual_type->id == TypeTableEntryIdNumLitFloat ||
- actual_type->id == TypeTableEntryIdNumLitInt)
+ if (actual_type->id == TypeTableEntryIdComptimeFloat ||
+ actual_type->id == TypeTableEntryIdComptimeInt)
{
ensure_complete_type(ira->codegen, wanted_type);
if (type_is_invalid(wanted_type))
@@ -10060,9 +10109,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return cast2;
} else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
CastOp op;
- if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
+ if ((actual_type->id == TypeTableEntryIdComptimeFloat &&
wanted_type->id == TypeTableEntryIdFloat) ||
- (actual_type->id == TypeTableEntryIdNumLitInt &&
+ (actual_type->id == TypeTableEntryIdComptimeInt &&
wanted_type->id == TypeTableEntryIdInt))
{
op = CastOpNumLitToConcrete;
@@ -10082,8 +10131,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
// explicit cast from typed number to integer or float literal.
// works when the number is known at compile time
if (instr_is_comptime(value) &&
- ((actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdNumLitInt) ||
- (actual_type->id == TypeTableEntryIdFloat && wanted_type->id == TypeTableEntryIdNumLitFloat)))
+ ((actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdComptimeInt) ||
+ (actual_type->id == TypeTableEntryIdFloat && wanted_type->id == TypeTableEntryIdComptimeFloat)))
{
return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);
}
@@ -10156,8 +10205,32 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
+ // explicit cast from *T to *[1]T
+ if (wanted_type->id == TypeTableEntryIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
+ actual_type->id == TypeTableEntryIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle)
+ {
+ TypeTableEntry *array_type = wanted_type->data.pointer.child_type;
+ if (array_type->id == TypeTableEntryIdArray && array_type->data.array.len == 1 &&
+ types_match_const_cast_only(ira, array_type->data.array.child_type,
+ actual_type->data.pointer.child_type, source_node).id == ConstCastResultIdOk)
+ {
+ if (wanted_type->data.pointer.alignment > actual_type->data.pointer.alignment) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
+ add_error_note(ira->codegen, msg, value->source_node,
+ buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name),
+ actual_type->data.pointer.alignment));
+ add_error_note(ira->codegen, msg, source_instr->source_node,
+ buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name),
+ wanted_type->data.pointer.alignment));
+ return ira->codegen->invalid_instruction;
+ }
+ return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type);
+ }
+ }
+
+
// explicit cast from undefined to anything
- if (actual_type->id == TypeTableEntryIdUndefLit) {
+ if (actual_type->id == TypeTableEntryIdUndefined) {
return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
}
@@ -10554,19 +10627,19 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
IrBinOp op_id = bin_op_instruction->op_id;
bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
if (is_equality_cmp &&
- ((op1->value.type->id == TypeTableEntryIdNullLit && op2->value.type->id == TypeTableEntryIdMaybe) ||
- (op2->value.type->id == TypeTableEntryIdNullLit && op1->value.type->id == TypeTableEntryIdMaybe) ||
- (op1->value.type->id == TypeTableEntryIdNullLit && op2->value.type->id == TypeTableEntryIdNullLit)))
+ ((op1->value.type->id == TypeTableEntryIdNull && op2->value.type->id == TypeTableEntryIdMaybe) ||
+ (op2->value.type->id == TypeTableEntryIdNull && op1->value.type->id == TypeTableEntryIdMaybe) ||
+ (op1->value.type->id == TypeTableEntryIdNull && op2->value.type->id == TypeTableEntryIdNull)))
{
- if (op1->value.type->id == TypeTableEntryIdNullLit && op2->value.type->id == TypeTableEntryIdNullLit) {
+ if (op1->value.type->id == TypeTableEntryIdNull && op2->value.type->id == TypeTableEntryIdNull) {
ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
out_val->data.x_bool = (op_id == IrBinOpCmpEq);
return ira->codegen->builtin_types.entry_bool;
}
IrInstruction *maybe_op;
- if (op1->value.type->id == TypeTableEntryIdNullLit) {
+ if (op1->value.type->id == TypeTableEntryIdNull) {
maybe_op = op2;
- } else if (op2->value.type->id == TypeTableEntryIdNullLit) {
+ } else if (op2->value.type->id == TypeTableEntryIdNull) {
maybe_op = op1;
} else {
zig_unreachable();
@@ -10686,8 +10759,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
case TypeTableEntryIdInvalid:
zig_unreachable(); // handled above
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
break;
@@ -10722,8 +10795,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdUnion:
@@ -10745,10 +10818,10 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type);
if (one_possible_value || (value_is_comptime(op1_val) && value_is_comptime(op2_val))) {
bool answer;
- if (resolved_type->id == TypeTableEntryIdNumLitFloat || resolved_type->id == TypeTableEntryIdFloat) {
+ if (resolved_type->id == TypeTableEntryIdComptimeFloat || resolved_type->id == TypeTableEntryIdFloat) {
Cmp cmp_result = float_cmp(op1_val, op2_val);
answer = resolve_cmp_op_id(op_id, cmp_result);
- } else if (resolved_type->id == TypeTableEntryIdNumLitInt || resolved_type->id == TypeTableEntryIdInt) {
+ } else if (resolved_type->id == TypeTableEntryIdComptimeInt || resolved_type->id == TypeTableEntryIdInt) {
Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
answer = resolve_cmp_op_id(op_id, cmp_result);
} else {
@@ -10812,12 +10885,12 @@ static int ir_eval_math_op(TypeTableEntry *type_entry, ConstExprValue *op1_val,
bool is_int;
bool is_float;
Cmp op2_zcmp;
- if (type_entry->id == TypeTableEntryIdInt || type_entry->id == TypeTableEntryIdNumLitInt) {
+ if (type_entry->id == TypeTableEntryIdInt || type_entry->id == TypeTableEntryIdComptimeInt) {
is_int = true;
is_float = false;
op2_zcmp = bigint_cmp_zero(&op2_val->data.x_bigint);
} else if (type_entry->id == TypeTableEntryIdFloat ||
- type_entry->id == TypeTableEntryIdNumLitFloat)
+ type_entry->id == TypeTableEntryIdComptimeFloat)
{
is_int = false;
is_float = true;
@@ -10991,7 +11064,7 @@ static TypeTableEntry *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *
if (type_is_invalid(op1->value.type))
return ira->codegen->builtin_types.entry_invalid;
- if (op1->value.type->id != TypeTableEntryIdInt && op1->value.type->id != TypeTableEntryIdNumLitInt) {
+ if (op1->value.type->id != TypeTableEntryIdInt && op1->value.type->id != TypeTableEntryIdComptimeInt) {
ir_add_error(ira, &bin_op_instruction->base,
buf_sprintf("bit shifting operation expected integer type, found '%s'",
buf_ptr(&op1->value.type->name)));
@@ -11004,7 +11077,7 @@ static TypeTableEntry *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *
IrInstruction *casted_op2;
IrBinOp op_id = bin_op_instruction->op_id;
- if (op1->value.type->id == TypeTableEntryIdNumLitInt) {
+ if (op1->value.type->id == TypeTableEntryIdComptimeInt) {
casted_op2 = op2;
if (op_id == IrBinOpBitShiftLeftLossy) {
@@ -11049,7 +11122,7 @@ static TypeTableEntry *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *
ir_num_lit_fits_in_other_type(ira, result_instruction, op1->value.type, false);
return op1->value.type;
- } else if (op1->value.type->id == TypeTableEntryIdNumLitInt) {
+ } else if (op1->value.type->id == TypeTableEntryIdComptimeInt) {
ir_add_error(ira, &bin_op_instruction->base,
buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
return ira->codegen->builtin_types.entry_invalid;
@@ -11085,15 +11158,15 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
if (type_is_invalid(resolved_type))
return resolved_type;
- bool is_int = resolved_type->id == TypeTableEntryIdInt || resolved_type->id == TypeTableEntryIdNumLitInt;
- bool is_float = resolved_type->id == TypeTableEntryIdFloat || resolved_type->id == TypeTableEntryIdNumLitFloat;
+ bool is_int = resolved_type->id == TypeTableEntryIdInt || resolved_type->id == TypeTableEntryIdComptimeInt;
+ bool is_float = resolved_type->id == TypeTableEntryIdFloat || resolved_type->id == TypeTableEntryIdComptimeFloat;
bool is_signed_div = (
(resolved_type->id == TypeTableEntryIdInt && resolved_type->data.integral.is_signed) ||
resolved_type->id == TypeTableEntryIdFloat ||
- (resolved_type->id == TypeTableEntryIdNumLitFloat &&
+ (resolved_type->id == TypeTableEntryIdComptimeFloat &&
((bigfloat_cmp_zero(&op1->value.data.x_bigfloat) != CmpGT) !=
(bigfloat_cmp_zero(&op2->value.data.x_bigfloat) != CmpGT))) ||
- (resolved_type->id == TypeTableEntryIdNumLitInt &&
+ (resolved_type->id == TypeTableEntryIdComptimeInt &&
((bigint_cmp_zero(&op1->value.data.x_bigint) != CmpGT) !=
(bigint_cmp_zero(&op2->value.data.x_bigint) != CmpGT)))
);
@@ -11194,7 +11267,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
return ira->codegen->builtin_types.entry_invalid;
}
- if (resolved_type->id == TypeTableEntryIdNumLitInt) {
+ if (resolved_type->id == TypeTableEntryIdComptimeInt) {
if (op_id == IrBinOpAddWrap) {
op_id = IrBinOpAdd;
} else if (op_id == IrBinOpSubWrap) {
@@ -11568,11 +11641,11 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {
case TypeTableEntryIdFn:
case TypeTableEntryIdPromise:
return VarClassRequiredAny;
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
case TypeTableEntryIdBlock:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdOpaque:
case TypeTableEntryIdMetaType:
case TypeTableEntryIdNamespace:
@@ -11837,10 +11910,10 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
case TypeTableEntryIdMetaType:
case TypeTableEntryIdVoid:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -11861,10 +11934,10 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
case TypeTableEntryIdFloat:
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -12076,7 +12149,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
}
bool comptime_arg = param_decl_node->data.param_decl.is_inline ||
- casted_arg->value.type->id == TypeTableEntryIdNumLitInt || casted_arg->value.type->id == TypeTableEntryIdNumLitFloat;
+ casted_arg->value.type->id == TypeTableEntryIdComptimeInt || casted_arg->value.type->id == TypeTableEntryIdComptimeFloat;
ConstExprValue *arg_val;
@@ -12101,8 +12174,8 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
var->shadowable = !comptime_arg;
*next_proto_i += 1;
- } else if (casted_arg->value.type->id == TypeTableEntryIdNumLitInt ||
- casted_arg->value.type->id == TypeTableEntryIdNumLitFloat)
+ } else if (casted_arg->value.type->id == TypeTableEntryIdComptimeInt ||
+ casted_arg->value.type->id == TypeTableEntryIdComptimeFloat)
{
ir_add_error(ira, casted_arg,
buf_sprintf("compiler bug: integer and float literals in var args function must be casted. https://github.com/ziglang/zig/issues/557"));
@@ -12825,10 +12898,10 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -12862,10 +12935,10 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un
bool is_wrap_op = (un_op_instruction->op_id == IrUnOpNegationWrap);
- bool is_float = (expr_type->id == TypeTableEntryIdFloat || expr_type->id == TypeTableEntryIdNumLitFloat);
+ bool is_float = (expr_type->id == TypeTableEntryIdFloat || expr_type->id == TypeTableEntryIdComptimeFloat);
if ((expr_type->id == TypeTableEntryIdInt && expr_type->data.integral.is_signed) ||
- expr_type->id == TypeTableEntryIdNumLitInt || (is_float && !is_wrap_op))
+ expr_type->id == TypeTableEntryIdComptimeInt || (is_float && !is_wrap_op))
{
if (instr_is_comptime(value)) {
ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
@@ -12881,7 +12954,7 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un
} else {
bigint_negate(&out_val->data.x_bigint, &target_const_val->data.x_bigint);
}
- if (is_wrap_op || is_float || expr_type->id == TypeTableEntryIdNumLitInt) {
+ if (is_wrap_op || is_float || expr_type->id == TypeTableEntryIdComptimeInt) {
return expr_type;
}
@@ -13077,10 +13150,10 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
if (type_is_invalid(resolved_type))
return resolved_type;
- if (resolved_type->id == TypeTableEntryIdNumLitFloat ||
- resolved_type->id == TypeTableEntryIdNumLitInt ||
- resolved_type->id == TypeTableEntryIdNullLit ||
- resolved_type->id == TypeTableEntryIdUndefLit)
+ if (resolved_type->id == TypeTableEntryIdComptimeFloat ||
+ resolved_type->id == TypeTableEntryIdComptimeInt ||
+ resolved_type->id == TypeTableEntryIdNull ||
+ resolved_type->id == TypeTableEntryIdUndefined)
{
ir_add_error_node(ira, phi_instruction->base.source_node,
buf_sprintf("unable to infer expression type"));
@@ -13162,11 +13235,13 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
if (type_is_invalid(array_ptr->value.type))
return ira->codegen->builtin_types.entry_invalid;
+ ConstExprValue *orig_array_ptr_val = &array_ptr->value;
+
IrInstruction *elem_index = elem_ptr_instruction->elem_index->other;
if (type_is_invalid(elem_index->value.type))
return ira->codegen->builtin_types.entry_invalid;
- TypeTableEntry *ptr_type = array_ptr->value.type;
+ TypeTableEntry *ptr_type = orig_array_ptr_val->type;
assert(ptr_type->id == TypeTableEntryIdPointer);
TypeTableEntry *array_type = ptr_type->data.pointer.child_type;
@@ -13177,7 +13252,18 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
if (type_is_invalid(array_type)) {
return array_type;
- } else if (array_type->id == TypeTableEntryIdArray) {
+ } else if (array_type->id == TypeTableEntryIdArray ||
+ (array_type->id == TypeTableEntryIdPointer &&
+ array_type->data.pointer.ptr_len == PtrLenSingle &&
+ array_type->data.pointer.child_type->id == TypeTableEntryIdArray))
+ {
+ if (array_type->id == TypeTableEntryIdPointer) {
+ array_type = array_type->data.pointer.child_type;
+ ptr_type = ptr_type->data.pointer.child_type;
+ if (orig_array_ptr_val->special != ConstValSpecialRuntime) {
+ orig_array_ptr_val = const_ptr_pointee(ira->codegen, orig_array_ptr_val);
+ }
+ }
if (array_type->data.array.len == 0) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index 0 outside array of size 0"));
@@ -13205,7 +13291,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
} else if (array_type->id == TypeTableEntryIdPointer) {
if (array_type->data.pointer.ptr_len == PtrLenSingle) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
- buf_sprintf("indexing not allowed on pointer to single item"));
+ buf_sprintf("index of single-item pointer"));
return ira->codegen->builtin_types.entry_invalid;
}
return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len);
@@ -13294,9 +13380,9 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
}
ConstExprValue *array_ptr_val;
- if (array_ptr->value.special != ConstValSpecialRuntime &&
- (array_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == TypeTableEntryIdArray) &&
- (array_ptr_val = const_ptr_pointee(ira->codegen, &array_ptr->value)) &&
+ if (orig_array_ptr_val->special != ConstValSpecialRuntime &&
+ (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == TypeTableEntryIdArray) &&
+ (array_ptr_val = const_ptr_pointee(ira->codegen, orig_array_ptr_val)) &&
array_ptr_val->special != ConstValSpecialRuntime &&
(array_type->id != TypeTableEntryIdPointer ||
array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
@@ -13401,7 +13487,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
} else if (array_type->id == TypeTableEntryIdArray) {
ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
- out_val->data.x_ptr.mut = array_ptr->value.data.x_ptr.mut;
+ out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;
out_val->data.x_ptr.data.base_array.array_val = array_ptr_val;
out_val->data.x_ptr.data.base_array.elem_index = index;
return return_type;
@@ -14127,10 +14213,10 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
switch (type_entry->id) {
case TypeTableEntryIdInvalid:
zig_unreachable(); // handled above
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
@@ -14393,8 +14479,8 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case TypeTableEntryIdInvalid: // handled above
zig_unreachable();
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdBlock:
case TypeTableEntryIdArgTuple:
case TypeTableEntryIdOpaque:
@@ -14409,8 +14495,8 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -14501,8 +14587,8 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
case TypeTableEntryIdInvalid: // handled above
zig_unreachable();
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdBlock:
case TypeTableEntryIdArgTuple:
case TypeTableEntryIdOpaque:
@@ -14517,8 +14603,8 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -14570,11 +14656,11 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
case TypeTableEntryIdInvalid: // handled above
zig_unreachable();
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdBlock:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdMetaType:
case TypeTableEntryIdNamespace:
@@ -14627,7 +14713,7 @@ static TypeTableEntry *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIn
ir_build_test_nonnull_from(&ira->new_irb, &instruction->base, value);
return ira->codegen->builtin_types.entry_bool;
- } else if (type_entry->id == TypeTableEntryIdNullLit) {
+ } else if (type_entry->id == TypeTableEntryIdNull) {
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
out_val->data.x_bool = false;
return ira->codegen->builtin_types.entry_bool;
@@ -14934,8 +15020,8 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
case TypeTableEntryIdBool:
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
case TypeTableEntryIdPointer:
case TypeTableEntryIdPromise:
case TypeTableEntryIdFn:
@@ -15013,8 +15099,8 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
@@ -15532,10 +15618,10 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
case TypeTableEntryIdPromise:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdErrorSet:
@@ -16194,10 +16280,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
case TypeTableEntryIdVoid:
case TypeTableEntryIdBool:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdArgTuple:
@@ -17057,7 +17143,7 @@ static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruc
return ira->codegen->builtin_types.entry_invalid;
if (dest_type->id != TypeTableEntryIdInt &&
- dest_type->id != TypeTableEntryIdNumLitInt)
+ dest_type->id != TypeTableEntryIdComptimeInt)
{
ir_add_error(ira, dest_type_value, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
return ira->codegen->builtin_types.entry_invalid;
@@ -17069,7 +17155,7 @@ static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruc
return ira->codegen->builtin_types.entry_invalid;
if (src_type->id != TypeTableEntryIdInt &&
- src_type->id != TypeTableEntryIdNumLitInt)
+ src_type->id != TypeTableEntryIdComptimeInt)
{
ir_add_error(ira, target, buf_sprintf("expected integer type, found '%s'", buf_ptr(&src_type->name)));
return ira->codegen->builtin_types.entry_invalid;
@@ -17406,14 +17492,29 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
byte_alignment, 0, 0);
return_type = get_slice_type(ira->codegen, slice_ptr_type);
} else if (array_type->id == TypeTableEntryIdPointer) {
- TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type,
- array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
- PtrLenUnknown,
- array_type->data.pointer.alignment, 0, 0);
- return_type = get_slice_type(ira->codegen, slice_ptr_type);
- if (!end) {
- ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value"));
- return ira->codegen->builtin_types.entry_invalid;
+ if (array_type->data.pointer.ptr_len == PtrLenSingle) {
+ TypeTableEntry *main_type = array_type->data.pointer.child_type;
+ if (main_type->id == TypeTableEntryIdArray) {
+ TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen,
+ main_type->data.pointer.child_type,
+ array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
+ PtrLenUnknown,
+ array_type->data.pointer.alignment, 0, 0);
+ return_type = get_slice_type(ira->codegen, slice_ptr_type);
+ } else {
+ ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ } else {
+ TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type,
+ array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
+ PtrLenUnknown,
+ array_type->data.pointer.alignment, 0, 0);
+ return_type = get_slice_type(ira->codegen, slice_ptr_type);
+ if (!end) {
+ ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
}
} else if (is_slice(array_type)) {
TypeTableEntry *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry;
@@ -17433,12 +17534,24 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
size_t abs_offset;
size_t rel_end;
bool ptr_is_undef = false;
- if (array_type->id == TypeTableEntryIdArray) {
- array_val = const_ptr_pointee(ira->codegen, &ptr_ptr->value);
- abs_offset = 0;
- rel_end = array_type->data.array.len;
- parent_ptr = nullptr;
+ if (array_type->id == TypeTableEntryIdArray ||
+ (array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
+ {
+ if (array_type->id == TypeTableEntryIdPointer) {
+ TypeTableEntry *child_array_type = array_type->data.pointer.child_type;
+ assert(child_array_type->id == TypeTableEntryIdArray);
+ parent_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value);
+ array_val = const_ptr_pointee(ira->codegen, parent_ptr);
+ rel_end = child_array_type->data.array.len;
+ abs_offset = 0;
+ } else {
+ array_val = const_ptr_pointee(ira->codegen, &ptr_ptr->value);
+ rel_end = array_type->data.array.len;
+ parent_ptr = nullptr;
+ abs_offset = 0;
+ }
} else if (array_type->id == TypeTableEntryIdPointer) {
+ assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
parent_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value);
if (parent_ptr->special == ConstValSpecialUndef) {
array_val = nullptr;
@@ -17537,7 +17650,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
if (array_val) {
size_t index = abs_offset + start_scalar;
bool is_const = slice_is_const(return_type);
- init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const);
+ init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const, PtrLenUnknown);
if (array_type->id == TypeTableEntryIdArray) {
ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut;
} else if (is_slice(array_type)) {
@@ -17763,10 +17876,10 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc
zig_unreachable();
case TypeTableEntryIdMetaType:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
@@ -18264,8 +18377,8 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
if (!end_val)
return ira->codegen->builtin_types.entry_invalid;
- assert(start_val->type->id == TypeTableEntryIdInt || start_val->type->id == TypeTableEntryIdNumLitInt);
- assert(end_val->type->id == TypeTableEntryIdInt || end_val->type->id == TypeTableEntryIdNumLitInt);
+ assert(start_val->type->id == TypeTableEntryIdInt || start_val->type->id == TypeTableEntryIdComptimeInt);
+ assert(end_val->type->id == TypeTableEntryIdInt || end_val->type->id == TypeTableEntryIdComptimeInt);
AstNode *prev_node = rangeset_add_range(&rs, &start_val->data.x_bigint, &end_val->data.x_bigint,
start_value->source_node);
if (prev_node != nullptr) {
@@ -18497,10 +18610,10 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdPromise:
zig_unreachable();
case TypeTableEntryIdVoid:
@@ -18564,10 +18677,10 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
case TypeTableEntryIdPromise:
zig_unreachable();
case TypeTableEntryIdVoid:
@@ -18645,10 +18758,10 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
ir_add_error(ira, dest_type_value,
buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
return ira->codegen->builtin_types.entry_invalid;
@@ -18671,10 +18784,10 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdComptimeFloat:
+ case TypeTableEntryIdComptimeInt:
+ case TypeTableEntryIdUndefined:
+ case TypeTableEntryIdNull:
ir_add_error(ira, dest_type_value,
buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
return ira->codegen->builtin_types.entry_invalid;
@@ -19447,7 +19560,7 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction
if (type_is_invalid(op->value.type))
return ira->codegen->builtin_types.entry_invalid;
- bool ok_type = float_type->id == TypeTableEntryIdNumLitFloat || float_type->id == TypeTableEntryIdFloat;
+ bool ok_type = float_type->id == TypeTableEntryIdComptimeFloat || float_type->id == TypeTableEntryIdFloat;
if (!ok_type) {
ir_add_error(ira, instruction->type, buf_sprintf("@sqrt does not support type '%s'", buf_ptr(&float_type->name)));
return ira->codegen->builtin_types.entry_invalid;
@@ -19464,7 +19577,7 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- if (float_type->id == TypeTableEntryIdNumLitFloat) {
+ if (float_type->id == TypeTableEntryIdComptimeFloat) {
bigfloat_sqrt(&out_val->data.x_bigfloat, &val->data.x_bigfloat);
} else if (float_type->id == TypeTableEntryIdFloat) {
switch (float_type->data.floating.bit_count) {
diff --git a/src/util.hpp b/src/util.hpp
index 25141d8435..52baab7ace 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -65,6 +65,11 @@ static inline int clzll(unsigned long long mask) {
template
ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {
+#ifndef NDEBUG
+ // make behavior when size == 0 portable
+ if (count == 0)
+ return nullptr;
+#endif
T *ptr = reinterpret_cast(malloc(count * sizeof(T)));
if (!ptr)
zig_panic("allocation failed");
@@ -73,6 +78,11 @@ ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {
template
ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) {
+#ifndef NDEBUG
+ // make behavior when size == 0 portable
+ if (count == 0)
+ return nullptr;
+#endif
T *ptr = reinterpret_cast(calloc(count, sizeof(T)));
if (!ptr)
zig_panic("allocation failed");
@@ -93,9 +103,7 @@ static inline void safe_memcpy(T *dest, const T *src, size_t count) {
template
static inline T *reallocate(T *old, size_t old_count, size_t new_count) {
- T *ptr = reinterpret_cast(realloc(old, new_count * sizeof(T)));
- if (!ptr)
- zig_panic("allocation failed");
+ T *ptr = reallocate_nonzero(old, old_count, new_count);
if (new_count > old_count) {
memset(&ptr[old_count], 0, (new_count - old_count) * sizeof(T));
}
@@ -104,6 +112,11 @@ static inline T *reallocate(T *old, size_t old_count, size_t new_count) {
template
static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count) {
+#ifndef NDEBUG
+ // make behavior when size == 0 portable
+ if (new_count == 0 && old == nullptr)
+ return nullptr;
+#endif
T *ptr = reinterpret_cast(realloc(old, new_count * sizeof(T)));
if (!ptr)
zig_panic("allocation failed");
diff --git a/std/fmt/errol/index.zig b/std/fmt/errol/index.zig
index 933958ac18..a906b714ab 100644
--- a/std/fmt/errol/index.zig
+++ b/std/fmt/errol/index.zig
@@ -59,7 +59,7 @@ pub fn roundToPrecision(float_decimal: *FloatDecimal, precision: usize, mode: Ro
float_decimal.exp += 1;
// Re-size the buffer to use the reserved leading byte.
- const one_before = @intToPtr(*u8, @ptrToInt(&float_decimal.digits[0]) - 1);
+ const one_before = @intToPtr([*]u8, @ptrToInt(&float_decimal.digits[0]) - 1);
float_decimal.digits = one_before[0 .. float_decimal.digits.len + 1];
float_decimal.digits[0] = '1';
return;
diff --git a/std/fmt/index.zig b/std/fmt/index.zig
index b522d9d37d..047a154bb8 100644
--- a/std/fmt/index.zig
+++ b/std/fmt/index.zig
@@ -16,27 +16,12 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
Start,
OpenBrace,
CloseBrace,
- Integer,
- IntegerWidth,
- Float,
- FloatWidth,
- FloatScientific,
- FloatScientificWidth,
- Character,
- Buf,
- BufWidth,
- Bytes,
- BytesBase,
- BytesWidth,
+ FormatString,
};
comptime var start_index = 0;
comptime var state = State.Start;
comptime var next_arg = 0;
- comptime var radix = 0;
- comptime var uppercase = false;
- comptime var width = 0;
- comptime var width_start = 0;
inline for (fmt) |c, i| {
switch (state) {
@@ -45,8 +30,10 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
if (start_index < i) {
try output(context, fmt[start_index..i]);
}
+ start_index = i;
state = State.OpenBrace;
},
+
'}' => {
if (start_index < i) {
try output(context, fmt[start_index..i]);
@@ -61,57 +48,14 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
start_index = i;
},
'}' => {
- try formatValue(args[next_arg], context, Errors, output);
+ try formatType(args[next_arg], fmt[0..0], context, Errors, output);
next_arg += 1;
state = State.Start;
start_index = i + 1;
},
- 'd' => {
- radix = 10;
- uppercase = false;
- width = 0;
- state = State.Integer;
+ else => {
+ state = State.FormatString;
},
- 'x' => {
- radix = 16;
- uppercase = false;
- width = 0;
- state = State.Integer;
- },
- 'X' => {
- radix = 16;
- uppercase = true;
- width = 0;
- state = State.Integer;
- },
- 'c' => {
- state = State.Character;
- },
- 's' => {
- state = State.Buf;
- },
- 'e' => {
- state = State.FloatScientific;
- },
- '.' => {
- state = State.Float;
- },
- 'B' => {
- width = 0;
- radix = 1000;
- state = State.Bytes;
- },
- else => @compileError("Unknown format character: " ++ []u8{c}),
- },
- State.Buf => switch (c) {
- '}' => {
- return output(context, args[next_arg]);
- },
- '0'...'9' => {
- width_start = i;
- state = State.BufWidth;
- },
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
},
State.CloseBrace => switch (c) {
'}' => {
@@ -120,138 +64,15 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
},
else => @compileError("Single '}' encountered in format string"),
},
- State.Integer => switch (c) {
+ State.FormatString => switch (c) {
'}' => {
- try formatInt(args[next_arg], radix, uppercase, width, context, Errors, output);
+ const s = start_index + 1;
+ try formatType(args[next_arg], fmt[s..i], context, Errors, output);
next_arg += 1;
state = State.Start;
start_index = i + 1;
},
- '0'...'9' => {
- width_start = i;
- state = State.IntegerWidth;
- },
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.IntegerWidth => switch (c) {
- '}' => {
- width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
- try formatInt(args[next_arg], radix, uppercase, width, context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- '0'...'9' => {},
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.FloatScientific => switch (c) {
- '}' => {
- try formatFloatScientific(args[next_arg], null, context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- '0'...'9' => {
- width_start = i;
- state = State.FloatScientificWidth;
- },
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.FloatScientificWidth => switch (c) {
- '}' => {
- width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
- try formatFloatScientific(args[next_arg], width, context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- '0'...'9' => {},
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.Float => switch (c) {
- '}' => {
- try formatFloatDecimal(args[next_arg], null, context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- '0'...'9' => {
- width_start = i;
- state = State.FloatWidth;
- },
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.FloatWidth => switch (c) {
- '}' => {
- width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
- try formatFloatDecimal(args[next_arg], width, context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- '0'...'9' => {},
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.BufWidth => switch (c) {
- '}' => {
- width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
- try formatBuf(args[next_arg], width, context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- '0'...'9' => {},
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.Character => switch (c) {
- '}' => {
- try formatAsciiChar(args[next_arg], context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.Bytes => switch (c) {
- '}' => {
- try formatBytes(args[next_arg], 0, radix, context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- 'i' => {
- radix = 1024;
- state = State.BytesBase;
- },
- '0'...'9' => {
- width_start = i;
- state = State.BytesWidth;
- },
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.BytesBase => switch (c) {
- '}' => {
- try formatBytes(args[next_arg], 0, radix, context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- '0'...'9' => {
- width_start = i;
- state = State.BytesWidth;
- },
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
- },
- State.BytesWidth => switch (c) {
- '}' => {
- width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
- try formatBytes(args[next_arg], width, radix, context, Errors, output);
- next_arg += 1;
- state = State.Start;
- start_index = i + 1;
- },
- '0'...'9' => {},
- else => @compileError("Unexpected character in format string: " ++ []u8{c}),
+ else => {},
},
}
}
@@ -268,14 +89,17 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
}
}
-pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
+pub fn formatType(
+ value: var,
+ comptime fmt: []const u8,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
const T = @typeOf(value);
switch (@typeId(T)) {
- builtin.TypeId.Int => {
- return formatInt(value, 10, false, 0, context, Errors, output);
- },
- builtin.TypeId.Float => {
- return formatFloatScientific(value, null, context, Errors, output);
+ builtin.TypeId.Int, builtin.TypeId.Float => {
+ return formatValue(value, fmt, context, Errors, output);
},
builtin.TypeId.Void => {
return output(context, "void");
@@ -285,16 +109,16 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (
},
builtin.TypeId.Nullable => {
if (value) |payload| {
- return formatValue(payload, context, Errors, output);
+ return formatType(payload, fmt, context, Errors, output);
} else {
return output(context, "null");
}
},
builtin.TypeId.ErrorUnion => {
if (value) |payload| {
- return formatValue(payload, context, Errors, output);
+ return formatType(payload, fmt, context, Errors, output);
} else |err| {
- return formatValue(err, context, Errors, output);
+ return formatType(err, fmt, context, Errors, output);
}
},
builtin.TypeId.ErrorSet => {
@@ -302,10 +126,34 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (
return output(context, @errorName(value));
},
builtin.TypeId.Pointer => {
- if (@typeId(T.Child) == builtin.TypeId.Array and T.Child.Child == u8) {
- return output(context, (value.*)[0..]);
- } else {
- return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
+ switch (@typeId(T.Child)) {
+ builtin.TypeId.Array => {
+ if (T.Child.Child == u8) {
+ return formatText(value, fmt, context, Errors, output);
+ }
+ },
+ builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
+ const has_cust_fmt = comptime cf: {
+ const info = @typeInfo(T.Child);
+ const defs = switch (info) {
+ builtin.TypeId.Struct => |s| s.defs,
+ builtin.TypeId.Union => |u| u.defs,
+ builtin.TypeId.Enum => |e| e.defs,
+ else => unreachable,
+ };
+
+ for (defs) |def| {
+ if (mem.eql(u8, def.name, "format")) {
+ break :cf true;
+ }
+ }
+ break :cf false;
+ };
+
+ if (has_cust_fmt) return value.format(fmt, context, Errors, output);
+ return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
+ },
+ else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),
}
},
else => if (@canImplicitCast([]const u8, value)) {
@@ -317,11 +165,129 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (
}
}
-pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
- return output(context, (&c)[0..1]);
+fn formatValue(
+ value: var,
+ comptime fmt: []const u8,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
+ if (fmt.len > 0) {
+ if (fmt[0] == 'B') {
+ comptime var width: ?usize = null;
+ if (fmt.len > 1) {
+ if (fmt[1] == 'i') {
+ if (fmt.len > 2) width = comptime (parseUnsigned(usize, fmt[2..], 10) catch unreachable);
+ return formatBytes(value, width, 1024, context, Errors, output);
+ }
+ width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
+ }
+ return formatBytes(value, width, 1000, context, Errors, output);
+ }
+ }
+
+ comptime var T = @typeOf(value);
+ switch (@typeId(T)) {
+ builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
+ builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),
+ else => unreachable,
+ }
}
-pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
+pub fn formatIntValue(
+ value: var,
+ comptime fmt: []const u8,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
+ comptime var radix = 10;
+ comptime var uppercase = false;
+ comptime var width = 0;
+ if (fmt.len > 0) {
+ switch (fmt[0]) {
+ 'c' => {
+ if (@typeOf(value) == u8) {
+ if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]});
+ return formatAsciiChar(value, context, Errors, output);
+ }
+ },
+ 'd' => {
+ radix = 10;
+ uppercase = false;
+ width = 0;
+ },
+ 'x' => {
+ radix = 16;
+ uppercase = false;
+ width = 0;
+ },
+ 'X' => {
+ radix = 16;
+ uppercase = true;
+ width = 0;
+ },
+ else => @compileError("Unknown format character: " ++ []u8{fmt[0]}),
+ }
+ if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
+ }
+ return formatInt(value, radix, uppercase, width, context, Errors, output);
+}
+
+fn formatFloatValue(
+ value: var,
+ comptime fmt: []const u8,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
+ comptime var width: ?usize = null;
+ comptime var float_fmt = 'e';
+ if (fmt.len > 0) {
+ float_fmt = fmt[0];
+ if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
+ }
+
+ switch (float_fmt) {
+ 'e' => try formatFloatScientific(value, width, context, Errors, output),
+ '.' => try formatFloatDecimal(value, width, context, Errors, output),
+ else => @compileError("Unknown format character: " ++ []u8{float_fmt}),
+ }
+}
+
+pub fn formatText(
+ bytes: []const u8,
+ comptime fmt: []const u8,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
+ if (fmt.len > 0) {
+ if (fmt[0] == 's') {
+ comptime var width = 0;
+ if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
+ return formatBuf(bytes, width, context, Errors, output);
+ } else @compileError("Unknown format character: " ++ []u8{fmt[0]});
+ }
+ return output(context, bytes);
+}
+
+pub fn formatAsciiChar(
+ c: u8,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
+ return output(context, (*[1]u8)(&c)[0..]);
+}
+
+pub fn formatBuf(
+ buf: []const u8,
+ width: usize,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
try output(context, buf);
var leftover_padding = if (width > buf.len) (width - buf.len) else return;
@@ -334,7 +300,13 @@ pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: t
// Print a float in scientific notation to the specified precision. Null uses full precision.
// It should be the case that every full precision, printed value can be re-parsed back to the
// same type unambiguously.
-pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
+pub fn formatFloatScientific(
+ value: var,
+ maybe_precision: ?usize,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
var x = f64(value);
// Errol doesn't handle these special cases.
@@ -423,7 +395,13 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var,
// Print a float of the format x.yyyyy where the number of y is specified by the precision argument.
// By default floats are printed at full precision (no rounding).
-pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
+pub fn formatFloatDecimal(
+ value: var,
+ maybe_precision: ?usize,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
var x = f64(value);
// Errol doesn't handle these special cases.
@@ -613,11 +591,19 @@ pub fn formatInt(
}
}
-fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
+fn formatIntSigned(
+ value: var,
+ base: u8,
+ uppercase: bool,
+ width: usize,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
const uint = @IntType(false, @typeOf(value).bit_count);
if (value < 0) {
const minus_sign: u8 = '-';
- try output(context, (&minus_sign)[0..1]);
+ try output(context, (*[1]u8)(&minus_sign)[0..]);
const new_value = uint(-(value + 1)) + 1;
const new_width = if (width == 0) 0 else (width - 1);
return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output);
@@ -625,14 +611,22 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context:
return formatIntUnsigned(uint(value), base, uppercase, width, context, Errors, output);
} else {
const plus_sign: u8 = '+';
- try output(context, (&plus_sign)[0..1]);
+ try output(context, (*[1]u8)(&plus_sign)[0..]);
const new_value = uint(value);
const new_width = if (width == 0) 0 else (width - 1);
return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output);
}
}
-fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
+fn formatIntUnsigned(
+ value: var,
+ base: u8,
+ uppercase: bool,
+ width: usize,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+) Errors!void {
// max_int_digits accounts for the minus sign. when printing an unsigned
// number we don't need to do that.
var buf: [max_int_digits - 1]u8 = undefined;
@@ -654,7 +648,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, contex
const zero_byte: u8 = '0';
var leftover_padding = padding - index;
while (true) {
- try output(context, (&zero_byte)[0..1]);
+ try output(context, (*[1]u8)(&zero_byte)[0..]);
leftover_padding -= 1;
if (leftover_padding == 0) break;
}
@@ -831,6 +825,10 @@ test "fmt.format" {
const value: u3 = 0b101;
try testFmt("u3: 5\n", "u3: {}\n", value);
}
+ {
+ const value: u8 = 'a';
+ try testFmt("u8: a\n", "u8: {c}\n", value);
+ }
try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));
try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024));
{
@@ -1048,6 +1046,42 @@ test "fmt.format" {
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
assert(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));
}
+ //custom type format
+ {
+ const Vec2 = struct {
+ const SelfType = this;
+ x: f32,
+ y: f32,
+
+ pub fn format(
+ self: *SelfType,
+ comptime fmt: []const u8,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+ ) Errors!void {
+ if (fmt.len > 0) {
+ if (fmt.len > 1) unreachable;
+ switch (fmt[0]) {
+ //point format
+ 'p' => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y),
+ //dimension format
+ 'd' => return std.fmt.format(context, Errors, output, "{.3}x{.3}", self.x, self.y),
+ else => unreachable,
+ }
+ }
+ return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y);
+ }
+ };
+
+ var buf1: [32]u8 = undefined;
+ var value = Vec2{
+ .x = 10.2,
+ .y = 2.22,
+ };
+ try testFmt("point: (10.200,2.220)\n", "point: {}\n", &value);
+ try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", &value);
+ }
}
fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {
diff --git a/std/heap.zig b/std/heap.zig
index 0b8f4aeb3f..4444a2307a 100644
--- a/std/heap.zig
+++ b/std/heap.zig
@@ -24,7 +24,7 @@ fn cAlloc(self: *Allocator, n: usize, alignment: u29) ![]u8 {
fn cRealloc(self: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
const old_ptr = @ptrCast([*]c_void, old_mem.ptr);
if (c.realloc(old_ptr, new_size)) |buf| {
- return @ptrCast(*u8, buf)[0..new_size];
+ return @ptrCast([*]u8, buf)[0..new_size];
} else if (new_size <= old_mem.len) {
return old_mem[0..new_size];
} else {
diff --git a/std/io.zig b/std/io.zig
index e20a284e4e..a603d0cf5e 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -219,12 +219,12 @@ pub fn OutStream(comptime WriteError: type) type {
}
pub fn writeByte(self: *Self, byte: u8) !void {
- const slice = (&byte)[0..1];
+ const slice = (*[1]u8)(&byte)[0..];
return self.writeFn(self, slice);
}
pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) !void {
- const slice = (&byte)[0..1];
+ const slice = (*[1]u8)(&byte)[0..];
var i: usize = 0;
while (i < n) : (i += 1) {
try self.writeFn(self, slice);
diff --git a/std/macho.zig b/std/macho.zig
index e71ac76b1a..d6eef9a325 100644
--- a/std/macho.zig
+++ b/std/macho.zig
@@ -164,7 +164,7 @@ fn readNoEof(in: *io.FileInStream, comptime T: type, result: []T) !void {
return in.stream.readNoEof(([]u8)(result));
}
fn readOneNoEof(in: *io.FileInStream, comptime T: type, result: *T) !void {
- return readNoEof(in, T, result[0..1]);
+ return readNoEof(in, T, (*[1]T)(result)[0..]);
}
fn isSymbol(sym: *const Nlist64) bool {
diff --git a/std/math/ln.zig b/std/math/ln.zig
index 263e5955cb..3fd75977b9 100644
--- a/std/math/ln.zig
+++ b/std/math/ln.zig
@@ -14,7 +14,7 @@ const TypeId = builtin.TypeId;
pub fn ln(x: var) @typeOf(x) {
const T = @typeOf(x);
switch (@typeId(T)) {
- TypeId.FloatLiteral => {
+ TypeId.ComptimeFloat => {
return @typeOf(1.0)(ln_64(x));
},
TypeId.Float => {
@@ -24,7 +24,7 @@ pub fn ln(x: var) @typeOf(x) {
else => @compileError("ln not implemented for " ++ @typeName(T)),
};
},
- TypeId.IntLiteral => {
+ TypeId.ComptimeInt => {
return @typeOf(1)(math.floor(ln_64(f64(x))));
},
TypeId.Int => {
diff --git a/std/math/log.zig b/std/math/log.zig
index 1cba1138db..2c876081d8 100644
--- a/std/math/log.zig
+++ b/std/math/log.zig
@@ -9,15 +9,15 @@ pub fn log(comptime T: type, base: T, x: T) T {
return math.log2(x);
} else if (base == 10) {
return math.log10(x);
- } else if ((@typeId(T) == TypeId.Float or @typeId(T) == TypeId.FloatLiteral) and base == math.e) {
+ } else if ((@typeId(T) == TypeId.Float or @typeId(T) == TypeId.ComptimeFloat) and base == math.e) {
return math.ln(x);
}
switch (@typeId(T)) {
- TypeId.FloatLiteral => {
+ TypeId.ComptimeFloat => {
return @typeOf(1.0)(math.ln(f64(x)) / math.ln(f64(base)));
},
- TypeId.IntLiteral => {
+ TypeId.ComptimeInt => {
return @typeOf(1)(math.floor(math.ln(f64(x)) / math.ln(f64(base))));
},
builtin.TypeId.Int => {
diff --git a/std/math/log10.zig b/std/math/log10.zig
index d9fa1dcb02..c444add9ac 100644
--- a/std/math/log10.zig
+++ b/std/math/log10.zig
@@ -14,7 +14,7 @@ const TypeId = builtin.TypeId;
pub fn log10(x: var) @typeOf(x) {
const T = @typeOf(x);
switch (@typeId(T)) {
- TypeId.FloatLiteral => {
+ TypeId.ComptimeFloat => {
return @typeOf(1.0)(log10_64(x));
},
TypeId.Float => {
@@ -24,7 +24,7 @@ pub fn log10(x: var) @typeOf(x) {
else => @compileError("log10 not implemented for " ++ @typeName(T)),
};
},
- TypeId.IntLiteral => {
+ TypeId.ComptimeInt => {
return @typeOf(1)(math.floor(log10_64(f64(x))));
},
TypeId.Int => {
diff --git a/std/math/log2.zig b/std/math/log2.zig
index 22cc8082b3..2530519941 100644
--- a/std/math/log2.zig
+++ b/std/math/log2.zig
@@ -14,7 +14,7 @@ const TypeId = builtin.TypeId;
pub fn log2(x: var) @typeOf(x) {
const T = @typeOf(x);
switch (@typeId(T)) {
- TypeId.FloatLiteral => {
+ TypeId.ComptimeFloat => {
return @typeOf(1.0)(log2_64(x));
},
TypeId.Float => {
@@ -24,7 +24,7 @@ pub fn log2(x: var) @typeOf(x) {
else => @compileError("log2 not implemented for " ++ @typeName(T)),
};
},
- TypeId.IntLiteral => comptime {
+ TypeId.ComptimeInt => comptime {
var result = 0;
var x_shifted = x;
while (b: {
diff --git a/std/math/sqrt.zig b/std/math/sqrt.zig
index 982bd28b72..7a3ddb3b96 100644
--- a/std/math/sqrt.zig
+++ b/std/math/sqrt.zig
@@ -14,9 +14,9 @@ const TypeId = builtin.TypeId;
pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) {
const T = @typeOf(x);
switch (@typeId(T)) {
- TypeId.FloatLiteral => return T(@sqrt(f64, x)), // TODO upgrade to f128
+ TypeId.ComptimeFloat => return T(@sqrt(f64, x)), // TODO upgrade to f128
TypeId.Float => return @sqrt(T, x),
- TypeId.IntLiteral => comptime {
+ TypeId.ComptimeInt => comptime {
if (x > @maxValue(u128)) {
@compileError("sqrt not implemented for comptime_int greater than 128 bits");
}
diff --git a/std/mem.zig b/std/mem.zig
index aec24e8491..423460e73b 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -31,14 +31,16 @@ pub const Allocator = struct {
/// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
freeFn: fn (self: *Allocator, old_mem: []u8) void,
- fn create(self: *Allocator, comptime T: type) !*T {
+ /// Call destroy with the result
+ pub fn create(self: *Allocator, comptime T: type) !*T {
if (@sizeOf(T) == 0) return *{};
const slice = try self.alloc(T, 1);
return &slice[0];
}
- // TODO once #733 is solved, this will replace create
- fn construct(self: *Allocator, init: var) t: {
+ /// Call destroy with the result
+ /// TODO once #733 is solved, this will replace create
+ pub fn construct(self: *Allocator, init: var) t: {
// TODO this is a workaround for type getting parsed as Error!&const T
const T = @typeOf(init).Child;
break :t Error!*T;
@@ -51,17 +53,19 @@ pub const Allocator = struct {
return ptr;
}
- fn destroy(self: *Allocator, ptr: var) void {
- self.free(ptr[0..1]);
+ /// `ptr` should be the return value of `construct` or `create`
+ pub fn destroy(self: *Allocator, ptr: var) void {
+ const non_const_ptr = @intToPtr([*]u8, @ptrToInt(ptr));
+ self.freeFn(self, non_const_ptr[0..@sizeOf(@typeOf(ptr).Child)]);
}
- fn alloc(self: *Allocator, comptime T: type, n: usize) ![]T {
+ pub fn alloc(self: *Allocator, comptime T: type, n: usize) ![]T {
return self.alignedAlloc(T, @alignOf(T), n);
}
- fn alignedAlloc(self: *Allocator, comptime T: type, comptime alignment: u29, n: usize) ![]align(alignment) T {
+ pub fn alignedAlloc(self: *Allocator, comptime T: type, comptime alignment: u29, n: usize) ![]align(alignment) T {
if (n == 0) {
- return (*align(alignment) T)(undefined)[0..0];
+ return ([*]align(alignment) T)(undefined)[0..0];
}
const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;
const byte_slice = try self.allocFn(self, byte_count, alignment);
@@ -73,17 +77,17 @@ pub const Allocator = struct {
return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
}
- fn realloc(self: *Allocator, comptime T: type, old_mem: []T, n: usize) ![]T {
+ pub fn realloc(self: *Allocator, comptime T: type, old_mem: []T, n: usize) ![]T {
return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
}
- fn alignedRealloc(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) ![]align(alignment) T {
+ pub fn alignedRealloc(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) ![]align(alignment) T {
if (old_mem.len == 0) {
return self.alloc(T, n);
}
if (n == 0) {
self.free(old_mem);
- return (*align(alignment) T)(undefined)[0..0];
+ return ([*]align(alignment) T)(undefined)[0..0];
}
const old_byte_slice = ([]u8)(old_mem);
@@ -102,11 +106,11 @@ pub const Allocator = struct {
/// Reallocate, but `n` must be less than or equal to `old_mem.len`.
/// Unlike `realloc`, this function cannot fail.
/// Shrinking to 0 is the same as calling `free`.
- fn shrink(self: *Allocator, comptime T: type, old_mem: []T, n: usize) []T {
+ pub fn shrink(self: *Allocator, comptime T: type, old_mem: []T, n: usize) []T {
return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
}
- fn alignedShrink(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) []align(alignment) T {
+ pub fn alignedShrink(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) []align(alignment) T {
if (n == 0) {
self.free(old_mem);
return old_mem[0..0];
@@ -123,10 +127,10 @@ pub const Allocator = struct {
return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
}
- fn free(self: *Allocator, memory: var) void {
+ pub fn free(self: *Allocator, memory: var) void {
const bytes = ([]const u8)(memory);
if (bytes.len == 0) return;
- const non_const_ptr = @intToPtr(*u8, @ptrToInt(bytes.ptr));
+ const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr));
self.freeFn(self, non_const_ptr[0..bytes.len]);
}
};
diff --git a/std/net.zig b/std/net.zig
index bfe4b1c2a0..f21611ff91 100644
--- a/std/net.zig
+++ b/std/net.zig
@@ -68,7 +68,7 @@ pub const Address = struct {
pub fn parseIp4(buf: []const u8) !u32 {
var result: u32 = undefined;
- const out_ptr = ([]u8)((&result)[0..1]);
+ const out_ptr = ([]u8)((*[1]u32)(&result)[0..]);
var x: u8 = 0;
var index: u8 = 0;
diff --git a/std/os/index.zig b/std/os/index.zig
index 7e908af9eb..6023929b04 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -1240,7 +1240,7 @@ pub const Dir = struct {
const next_index = self.index + darwin_entry.d_reclen;
self.index = next_index;
- const name = (&darwin_entry.d_name)[0..darwin_entry.d_namlen];
+ const name = @ptrCast([*]u8, &darwin_entry.d_name)[0..darwin_entry.d_namlen];
// skip . and .. entries
if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) {
@@ -1704,7 +1704,7 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
for (args_alloc) |arg| {
total_bytes += @sizeOf([]u8) + arg.len;
}
- const unaligned_allocated_buf = @ptrCast(*const u8, args_alloc.ptr)[0..total_bytes];
+ const unaligned_allocated_buf = @ptrCast([*]const u8, args_alloc.ptr)[0..total_bytes];
const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf);
return allocator.free(aligned_allocated_buf);
}
diff --git a/std/os/time.zig b/std/os/time.zig
index 8629504323..dd64df2156 100644
--- a/std/os/time.zig
+++ b/std/os/time.zig
@@ -266,7 +266,7 @@ test "os.time.timestamp" {
test "os.time.Timer" {
const ns_per_ms = (ns_per_s / ms_per_s);
- const margin = ns_per_ms * 50;
+ const margin = ns_per_ms * 150;
var timer = try Timer.start();
sleep(0, 10 * ns_per_ms);
diff --git a/std/special/compiler_rt/udivmoddi4_test.zig b/std/special/compiler_rt/udivmoddi4_test.zig
index 324626d3f9..34b9dda1ea 100644
--- a/std/special/compiler_rt/udivmoddi4_test.zig
+++ b/std/special/compiler_rt/udivmoddi4_test.zig
@@ -1,3 +1,5 @@
+// Disable formatting to avoid unnecessary source repository bloat.
+// zig fmt: off
const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;
const assert = @import("std").debug.assert;
diff --git a/std/special/compiler_rt/udivmodti4_test.zig b/std/special/compiler_rt/udivmodti4_test.zig
index 48d65b43c6..f6b370c26e 100644
--- a/std/special/compiler_rt/udivmodti4_test.zig
+++ b/std/special/compiler_rt/udivmodti4_test.zig
@@ -1,3 +1,5 @@
+// Disable formatting to avoid unnecessary source repository bloat.
+// zig fmt: off
const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4;
const assert = @import("std").debug.assert;
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index c28a70b770..91a56de827 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,3 +1,29 @@
+test "zig fmt: comment to disable/enable zig fmt first" {
+ try testCanonical(
+ \\// Test trailing comma syntax
+ \\// zig fmt: off
+ \\
+ \\const struct_trailing_comma = struct { x: i32, y: i32, };
+ );
+}
+
+test "zig fmt: comment to disable/enable zig fmt" {
+ try testTransform(
+ \\const a = b;
+ \\// zig fmt: off
+ \\const c = d;
+ \\// zig fmt: on
+ \\const e = f;
+ ,
+ \\const a = b;
+ \\// zig fmt: off
+ \\const c = d;
+ \\// zig fmt: on
+ \\const e = f;
+ \\
+ );
+}
+
test "zig fmt: pointer of unknown length" {
try testCanonical(
\\fn foo(ptr: [*]u8) void {}
diff --git a/std/zig/render.zig b/std/zig/render.zig
index 147adc6221..7c9b53b77a 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -82,8 +82,45 @@ fn renderRoot(
var start_col: usize = 0;
var it = tree.root_node.decls.iterator(0);
- while (it.next()) |decl| {
- try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl.*);
+ while (true) {
+ var decl = (it.next() ?? return).*;
+ // look for zig fmt: off comment
+ var start_token_index = decl.firstToken();
+ zig_fmt_loop: while (start_token_index != 0) {
+ start_token_index -= 1;
+ const start_token = tree.tokens.at(start_token_index);
+ switch (start_token.id) {
+ Token.Id.LineComment => {},
+ Token.Id.DocComment => continue,
+ else => break,
+ }
+ if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(start_token)[2..], " "), "zig fmt: off")) {
+ var end_token_index = start_token_index;
+ while (true) {
+ end_token_index += 1;
+ const end_token = tree.tokens.at(end_token_index);
+ switch (end_token.id) {
+ Token.Id.LineComment => {},
+ Token.Id.Eof => {
+ const start = tree.tokens.at(start_token_index + 1).start;
+ try stream.write(tree.source[start..]);
+ return;
+ },
+ else => continue,
+ }
+ if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(end_token)[2..], " "), "zig fmt: on")) {
+ const start = tree.tokens.at(start_token_index + 1).start;
+ try stream.print("{}\n", tree.source[start..end_token.end]);
+ while (tree.tokens.at(decl.firstToken()).start < end_token.end) {
+ decl = (it.next() ?? return).*;
+ }
+ break :zig_fmt_loop;
+ }
+ }
+ }
+ }
+
+ try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl);
if (it.peek()) |next_decl| {
try renderExtraNewline(tree, stream, &start_col, next_decl.*);
}
diff --git a/test/cases/align.zig b/test/cases/align.zig
index b80727258e..682c185e86 100644
--- a/test/cases/align.zig
+++ b/test/cases/align.zig
@@ -6,7 +6,7 @@ var foo: u8 align(4) = 100;
test "global variable alignment" {
assert(@typeOf(&foo).alignment == 4);
assert(@typeOf(&foo) == *align(4) u8);
- const slice = (&foo)[0..1];
+ const slice = (*[1]u8)(&foo)[0..];
assert(@typeOf(slice) == []align(4) u8);
}
@@ -60,7 +60,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
test "implicitly decreasing slice alignment" {
const a: u32 align(4) = 3;
const b: u32 align(8) = 4;
- assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);
+ assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
}
fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
return a[0] + b[0];
diff --git a/test/cases/array.zig b/test/cases/array.zig
index 9a405216d8..ef919b27bd 100644
--- a/test/cases/array.zig
+++ b/test/cases/array.zig
@@ -115,3 +115,32 @@ test "array len property" {
var x: [5]i32 = undefined;
assert(@typeOf(x).len == 5);
}
+
+test "single-item pointer to array indexing and slicing" {
+ testSingleItemPtrArrayIndexSlice();
+ comptime testSingleItemPtrArrayIndexSlice();
+}
+
+fn testSingleItemPtrArrayIndexSlice() void {
+ var array = "aaaa";
+ doSomeMangling(&array);
+ assert(mem.eql(u8, "azya", array));
+}
+
+fn doSomeMangling(array: *[4]u8) void {
+ array[1] = 'z';
+ array[2..3][0] = 'y';
+}
+
+test "implicit cast single-item pointer" {
+ testImplicitCastSingleItemPtr();
+ comptime testImplicitCastSingleItemPtr();
+}
+
+fn testImplicitCastSingleItemPtr() void {
+ var byte: u8 = 100;
+ const slice = (*[1]u8)(&byte)[0..];
+ slice[0] += 1;
+ assert(byte == 101);
+}
+
diff --git a/test/cases/eval.zig b/test/cases/eval.zig
index b6d6a4f37b..461408afea 100644
--- a/test/cases/eval.zig
+++ b/test/cases/eval.zig
@@ -418,9 +418,9 @@ test "string literal used as comptime slice is memoized" {
}
test "comptime slice of undefined pointer of length 0" {
- const slice1 = (*i32)(undefined)[0..0];
+ const slice1 = ([*]i32)(undefined)[0..0];
assert(slice1.len == 0);
- const slice2 = (*i32)(undefined)[100..100];
+ const slice2 = ([*]i32)(undefined)[100..100];
assert(slice2.len == 0);
}
@@ -508,7 +508,7 @@ test "comptime slice of slice preserves comptime var" {
test "comptime slice of pointer preserves comptime var" {
comptime {
var buff: [10]u8 = undefined;
- var a = &buff[0];
+ var a = buff[0..].ptr;
a[0..1][0] = 1;
assert(buff[0..][0..][0] == 1);
}
diff --git a/test/cases/math.zig b/test/cases/math.zig
index 0c18293dd5..0bf99cff0e 100644
--- a/test/cases/math.zig
+++ b/test/cases/math.zig
@@ -329,14 +329,14 @@ fn testShrExact(x: u8) void {
assert(shifted == 0b00101101);
}
-test "big number addition" {
+test "comptime_int addition" {
comptime {
assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
}
}
-test "big number multiplication" {
+test "comptime_int multiplication" {
comptime {
assert(
45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
@@ -347,13 +347,13 @@ test "big number multiplication" {
}
}
-test "big number shifting" {
+test "comptime_int shifting" {
comptime {
assert((u128(1) << 127) == 0x80000000000000000000000000000000);
}
}
-test "big number multi-limb shift and mask" {
+test "comptime_int multi-limb shift and mask" {
comptime {
var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
@@ -370,7 +370,7 @@ test "big number multi-limb shift and mask" {
}
}
-test "big number multi-limb partial shift right" {
+test "comptime_int multi-limb partial shift right" {
comptime {
var a = 0x1ffffffffeeeeeeee;
a >>= 16;
@@ -391,7 +391,7 @@ fn test_xor() void {
assert(0xFF ^ 0xFF == 0x00);
}
-test "big number xor" {
+test "comptime_int xor" {
comptime {
assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
@@ -449,3 +449,15 @@ test "@sqrt" {
fn testSqrt(comptime T: type, x: T) void {
assert(@sqrt(T, x * x) == x);
}
+
+test "comptime_int param and return" {
+ const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
+ assert(a == 137114567242441932203689521744947848950);
+
+ const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
+ assert(b == 985095453608931032642182098849559179469148836107390954364380);
+}
+
+fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
+ return a + b;
+}
diff --git a/test/cases/misc.zig b/test/cases/misc.zig
index 5899f20f9c..9450cf5e6e 100644
--- a/test/cases/misc.zig
+++ b/test/cases/misc.zig
@@ -274,7 +274,7 @@ test "generic malloc free" {
}
var some_mem: [100]u8 = undefined;
fn memAlloc(comptime T: type, n: usize) error![]T {
- return @ptrCast(*T, &some_mem[0])[0..n];
+ return @ptrCast([*]T, &some_mem[0])[0..n];
}
fn memFree(comptime T: type, memory: []T) void {}
@@ -501,10 +501,10 @@ test "@typeId" {
assert(@typeId(*f32) == Tid.Pointer);
assert(@typeId([2]u8) == Tid.Array);
assert(@typeId(AStruct) == Tid.Struct);
- assert(@typeId(@typeOf(1)) == Tid.IntLiteral);
- assert(@typeId(@typeOf(1.0)) == Tid.FloatLiteral);
- assert(@typeId(@typeOf(undefined)) == Tid.UndefinedLiteral);
- assert(@typeId(@typeOf(null)) == Tid.NullLiteral);
+ assert(@typeId(@typeOf(1)) == Tid.ComptimeInt);
+ assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
+ assert(@typeId(@typeOf(undefined)) == Tid.Undefined);
+ assert(@typeId(@typeOf(null)) == Tid.Null);
assert(@typeId(?i32) == Tid.Nullable);
assert(@typeId(error!i32) == Tid.ErrorUnion);
assert(@typeId(error) == Tid.ErrorSet);
@@ -588,7 +588,7 @@ var global_ptr = &gdt[0];
// can't really run this test but we can make sure it has no compile error
// and generates code
-const vram = @intToPtr(*volatile u8, 0x20000000)[0..0x8000];
+const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
export fn writeToVRam() void {
vram[0] = 'X';
}
diff --git a/test/cases/slice.zig b/test/cases/slice.zig
index 24e5239e2d..b4b43bdd19 100644
--- a/test/cases/slice.zig
+++ b/test/cases/slice.zig
@@ -1,7 +1,7 @@
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
-const x = @intToPtr(*i32, 0x1000)[0..0x500];
+const x = @intToPtr([*]i32, 0x1000)[0..0x500];
const y = x[0x100..];
test "compile time slice of pointer to hard coded address" {
assert(@ptrToInt(x.ptr) == 0x1000);
diff --git a/test/cases/syntax.zig b/test/cases/syntax.zig
index 20fb6cd203..b497b060c4 100644
--- a/test/cases/syntax.zig
+++ b/test/cases/syntax.zig
@@ -1,4 +1,5 @@
// Test trailing comma syntax
+// zig fmt: off
const struct_trailing_comma = struct { x: i32, y: i32, };
const struct_no_comma = struct { x: i32, y: i32 };
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 7e9ef82e42..e264d57b5e 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,13 +1,22 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "slicing single-item pointer",
+ \\export fn entry(ptr: *i32) void {
+ \\ const slice = ptr[0..2];
+ \\}
+ ,
+ ".tmp_source.zig:2:22: error: slice of single-item pointer",
+ );
+
cases.add(
"indexing single-item pointer",
\\export fn entry(ptr: *i32) i32 {
\\ return ptr[1];
\\}
,
- ".tmp_source.zig:2:15: error: indexing not allowed on pointer to single item",
+ ".tmp_source.zig:2:15: error: index of single-item pointer",
);
cases.add(
@@ -144,10 +153,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"comptime slice of undefined pointer non-zero len",
\\export fn entry() void {
- \\ const slice = (*i32)(undefined)[0..1];
+ \\ const slice = ([*]i32)(undefined)[0..1];
\\}
,
- ".tmp_source.zig:2:36: error: non-zero length slice of undefined pointer",
+ ".tmp_source.zig:2:38: error: non-zero length slice of undefined pointer",
);
cases.add(
@@ -1530,7 +1539,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\fn foo() *const i32 { return y; }
\\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
,
- ".tmp_source.zig:3:30: error: expected type '*const i32', found '*const (integer literal)'",
+ ".tmp_source.zig:3:30: error: expected type '*const i32', found '*const comptime_int'",
);
cases.add(
@@ -1546,7 +1555,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\const x = 2 == 2.0;
\\export fn entry() usize { return @sizeOf(@typeOf(x)); }
,
- ".tmp_source.zig:1:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'",
+ ".tmp_source.zig:1:11: error: integer value 2 cannot be implicitly casted to type 'comptime_float'",
);
cases.add(
@@ -2180,7 +2189,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\export fn entry() usize { return @sizeOf(@typeOf(block_aligned_stuff)); }
,
- ".tmp_source.zig:3:60: error: unable to perform binary not operation on type '(integer literal)'",
+ ".tmp_source.zig:3:60: error: unable to perform binary not operation on type 'comptime_int'",
);
cases.addCase(x: {
@@ -3129,14 +3138,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\export fn entry() void {
\\ var foo = Foo { .a = 1, .b = 10 };
\\ foo.b += 1;
- \\ bar((&foo.b)[0..1]);
+ \\ bar((*[1]u32)(&foo.b)[0..]);
\\}
\\
\\fn bar(x: []u32) void {
\\ x[0] += 1;
\\}
,
- ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align(1) u32'",
+ ".tmp_source.zig:9:18: error: cast increases pointer alignment",
+ ".tmp_source.zig:9:23: note: '*align(1) u32' has alignment 1",
+ ".tmp_source.zig:9:18: note: '*[1]u32' has alignment 4",
);
cases.add(
@@ -3258,10 +3269,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ fn bar(self: *const Foo) void {}
\\};
,
- ".tmp_source.zig:4:4: error: variable of type '*(integer literal)' must be const or comptime",
+ ".tmp_source.zig:4:4: error: variable of type '*comptime_int' must be const or comptime",
".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime",
- ".tmp_source.zig:8:4: error: variable of type '(integer literal)' must be const or comptime",
- ".tmp_source.zig:9:4: error: variable of type '(float literal)' must be const or comptime",
+ ".tmp_source.zig:8:4: error: variable of type 'comptime_int' must be const or comptime",
+ ".tmp_source.zig:9:4: error: variable of type 'comptime_float' must be const or comptime",
".tmp_source.zig:10:4: error: variable of type '(block)' must be const or comptime",
".tmp_source.zig:11:4: error: variable of type '(null)' must be const or comptime",
".tmp_source.zig:12:4: error: variable of type 'Opaque' must be const or comptime",