| author | |
| committer | |
| log | 545064c1d9137a603e3e28aa066ce9e65a1ed4b6 |
| tree | 1ab105ff0a2ec650c82aca4cb688b28ee54191b2 |
| parent | 169a789b343e9070b4658de9c8bd96c6736c6edc |
| signature | Commit is signed but in an unrecognized format. |
See #903
* create with `@Vector(len, ElemType)`
* only wrapping addition is implemented
This feature is far from complete; this is only the beginning.12 files changed, 419 insertions(+), 54 deletions(-)
doc/langref.html.in+34| ... | ... | @@ -1531,6 +1531,29 @@ test "array initialization with function calls" { |
| 1531 | 1531 | {#code_end#} |
| 1532 | 1532 | {#see_also|for|Slices#} |
| 1533 | 1533 | {#header_close#} |
| 1534 | ||
| 1535 | {#header_open|Vectors#} | |
| 1536 | <p> | |
| 1537 | A vector is a group of {#link|Integers#}, {#link|Floats#}, or {#link|Pointers#} which are operated on | |
| 1538 | in parallel using a single instruction ({#link|SIMD#}). Vector types are created with the builtin | |
| 1539 | function {#link|@Vector#}. | |
| 1540 | </p> | |
| 1541 | <p> | |
| 1542 | TODO talk about C ABI interop | |
| 1543 | </p> | |
| 1544 | {#header_open|SIMD#} | |
| 1545 | <p> | |
| 1546 | TODO Zig's SIMD abilities are just beginning to be fleshed out. Here are some talking points to update the | |
| 1547 | docs with: | |
| 1548 | * What kind of operations can you do? All the operations on integers and floats? What about mixing scalar and vector? | |
| 1549 | * How to convert to/from vectors/arrays | |
| 1550 | * How to access individual elements from vectors, how to loop over the elements | |
| 1551 | * "shuffle" | |
| 1552 | * Advice on writing high perf software, how to abstract the best way | |
| 1553 | </p> | |
| 1554 | {#header_close#} | |
| 1555 | {#header_close#} | |
| 1556 | ||
| 1534 | 1557 | {#header_open|Pointers#} |
| 1535 | 1558 | <p> |
| 1536 | 1559 | Zig has two kinds of pointers: |
| ... | ... | @@ -6607,6 +6630,17 @@ pub const TypeInfo = union(TypeId) { |
| 6607 | 6630 | expression passed as an argument. The expression is evaluated. |
| 6608 | 6631 | </p> |
| 6609 | 6632 | |
| 6633 | {#header_close#} | |
| 6634 | ||
| 6635 | {#header_open|@Vector#} | |
| 6636 | <pre>{#syntax#}@Vector(comptime len: u32, comptime ElemType: type) type{#endsyntax#}</pre> | |
| 6637 | <p> | |
| 6638 | This function returns a vector type for {#link|SIMD#}. | |
| 6639 | </p> | |
| 6640 | <p> | |
| 6641 | {#syntax#}ElemType{#endsyntax#} must be an {#link|integer|Integers#}, a {#link|float|Floats#}, or a | |
| 6642 | {#link|pointer|Pointers#}. | |
| 6643 | </p> | |
| 6610 | 6644 | {#header_close#} |
| 6611 | 6645 | {#header_close#} |
| 6612 | 6646 |
src-self-hosted/type.zig+16| ... | ... | @@ -44,6 +44,7 @@ pub const Type = struct { |
| 44 | 44 | Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp), |
| 45 | 45 | Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp), |
| 46 | 46 | Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp), |
| 47 | Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp), | |
| 47 | 48 | } |
| 48 | 49 | } |
| 49 | 50 | |
| ... | ... | @@ -77,6 +78,7 @@ pub const Type = struct { |
| 77 | 78 | Id.ArgTuple => unreachable, |
| 78 | 79 | Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context), |
| 79 | 80 | Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context), |
| 81 | Id.Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context), | |
| 80 | 82 | } |
| 81 | 83 | } |
| 82 | 84 | |
| ... | ... | @@ -103,6 +105,7 @@ pub const Type = struct { |
| 103 | 105 | Id.Enum, |
| 104 | 106 | Id.Fn, |
| 105 | 107 | Id.Promise, |
| 108 | Id.Vector, | |
| 106 | 109 | => return false, |
| 107 | 110 | |
| 108 | 111 | Id.Struct => @panic("TODO"), |
| ... | ... | @@ -135,6 +138,7 @@ pub const Type = struct { |
| 135 | 138 | Id.Float, |
| 136 | 139 | Id.Fn, |
| 137 | 140 | Id.Promise, |
| 141 | Id.Vector, | |
| 138 | 142 | => return true, |
| 139 | 143 | |
| 140 | 144 | Id.Pointer => { |
| ... | ... | @@ -902,6 +906,18 @@ pub const Type = struct { |
| 902 | 906 | } |
| 903 | 907 | }; |
| 904 | 908 | |
| 909 | pub const Vector = struct { | |
| 910 | base: Type, | |
| 911 | ||
| 912 | pub fn destroy(self: *Vector, comp: *Compilation) void { | |
| 913 | comp.gpa().destroy(self); | |
| 914 | } | |
| 915 | ||
| 916 | pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 917 | @panic("TODO"); | |
| 918 | } | |
| 919 | }; | |
| 920 | ||
| 905 | 921 | pub const ComptimeFloat = struct { |
| 906 | 922 | base: Type, |
| 907 | 923 |
src/all_types.hpp+26| ... | ... | @@ -252,6 +252,10 @@ struct ConstArgTuple { |
| 252 | 252 | size_t end_index; |
| 253 | 253 | }; |
| 254 | 254 | |
| 255 | struct ConstVector { | |
| 256 | ConstExprValue *elements; | |
| 257 | }; | |
| 258 | ||
| 255 | 259 | enum ConstValSpecial { |
| 256 | 260 | ConstValSpecialRuntime, |
| 257 | 261 | ConstValSpecialStatic, |
| ... | ... | @@ -318,6 +322,7 @@ struct ConstExprValue { |
| 318 | 322 | ConstPtrValue x_ptr; |
| 319 | 323 | ImportTableEntry *x_import; |
| 320 | 324 | ConstArgTuple x_arg_tuple; |
| 325 | ConstVector x_vector; | |
| 321 | 326 | |
| 322 | 327 | // populated if special == ConstValSpecialRuntime |
| 323 | 328 | RuntimeHintErrorUnion rh_error_union; |
| ... | ... | @@ -1210,6 +1215,12 @@ struct ZigTypePromise { |
| 1210 | 1215 | ZigType *result_type; |
| 1211 | 1216 | }; |
| 1212 | 1217 | |
| 1218 | struct ZigTypeVector { | |
| 1219 | // The type must be a pointer, integer, or float | |
| 1220 | ZigType *elem_type; | |
| 1221 | uint32_t len; | |
| 1222 | }; | |
| 1223 | ||
| 1213 | 1224 | enum ZigTypeId { |
| 1214 | 1225 | ZigTypeIdInvalid, |
| 1215 | 1226 | ZigTypeIdMetaType, |
| ... | ... | @@ -1236,6 +1247,7 @@ enum ZigTypeId { |
| 1236 | 1247 | ZigTypeIdArgTuple, |
| 1237 | 1248 | ZigTypeIdOpaque, |
| 1238 | 1249 | ZigTypeIdPromise, |
| 1250 | ZigTypeIdVector, | |
| 1239 | 1251 | }; |
| 1240 | 1252 | |
| 1241 | 1253 | struct ZigType { |
| ... | ... | @@ -1262,6 +1274,7 @@ struct ZigType { |
| 1262 | 1274 | ZigTypeFn fn; |
| 1263 | 1275 | ZigTypeBoundFn bound_fn; |
| 1264 | 1276 | ZigTypePromise promise; |
| 1277 | ZigTypeVector vector; | |
| 1265 | 1278 | } data; |
| 1266 | 1279 | |
| 1267 | 1280 | // use these fields to make sure we don't duplicate type table entries for the same type |
| ... | ... | @@ -1415,6 +1428,7 @@ enum BuiltinFnId { |
| 1415 | 1428 | BuiltinFnIdEnumToInt, |
| 1416 | 1429 | BuiltinFnIdIntToEnum, |
| 1417 | 1430 | BuiltinFnIdIntType, |
| 1431 | BuiltinFnIdVectorType, | |
| 1418 | 1432 | BuiltinFnIdSetCold, |
| 1419 | 1433 | BuiltinFnIdSetRuntimeSafety, |
| 1420 | 1434 | BuiltinFnIdSetFloatMode, |
| ... | ... | @@ -1505,6 +1519,10 @@ struct TypeId { |
| 1505 | 1519 | ZigType *err_set_type; |
| 1506 | 1520 | ZigType *payload_type; |
| 1507 | 1521 | } error_union; |
| 1522 | struct { | |
| 1523 | ZigType *elem_type; | |
| 1524 | uint32_t len; | |
| 1525 | } vector; | |
| 1508 | 1526 | } data; |
| 1509 | 1527 | }; |
| 1510 | 1528 | |
| ... | ... | @@ -2139,6 +2157,7 @@ enum IrInstructionId { |
| 2139 | 2157 | IrInstructionIdFloatToInt, |
| 2140 | 2158 | IrInstructionIdBoolToInt, |
| 2141 | 2159 | IrInstructionIdIntType, |
| 2160 | IrInstructionIdVectorType, | |
| 2142 | 2161 | IrInstructionIdBoolNot, |
| 2143 | 2162 | IrInstructionIdMemset, |
| 2144 | 2163 | IrInstructionIdMemcpy, |
| ... | ... | @@ -2807,6 +2826,13 @@ struct IrInstructionIntType { |
| 2807 | 2826 | IrInstruction *bit_count; |
| 2808 | 2827 | }; |
| 2809 | 2828 | |
| 2829 | struct IrInstructionVectorType { | |
| 2830 | IrInstruction base; | |
| 2831 | ||
| 2832 | IrInstruction *len; | |
| 2833 | IrInstruction *elem_type; | |
| 2834 | }; | |
| 2835 | ||
| 2810 | 2836 | struct IrInstructionBoolNot { |
| 2811 | 2837 | IrInstruction base; |
| 2812 | 2838 |
src/analyze.cpp+85-6| ... | ... | @@ -250,6 +250,7 @@ AstNode *type_decl_node(ZigType *type_entry) { |
| 250 | 250 | case ZigTypeIdBoundFn: |
| 251 | 251 | case ZigTypeIdArgTuple: |
| 252 | 252 | case ZigTypeIdPromise: |
| 253 | case ZigTypeIdVector: | |
| 253 | 254 | return nullptr; |
| 254 | 255 | } |
| 255 | 256 | zig_unreachable(); |
| ... | ... | @@ -311,6 +312,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { |
| 311 | 312 | case ZigTypeIdBoundFn: |
| 312 | 313 | case ZigTypeIdArgTuple: |
| 313 | 314 | case ZigTypeIdPromise: |
| 315 | case ZigTypeIdVector: | |
| 314 | 316 | return true; |
| 315 | 317 | } |
| 316 | 318 | zig_unreachable(); |
| ... | ... | @@ -1055,11 +1057,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { |
| 1055 | 1057 | } |
| 1056 | 1058 | if (g->zig_target.arch.arch == ZigLLVM_x86_64) { |
| 1057 | 1059 | X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); |
| 1058 | if (abi_class == X64CABIClass_MEMORY) { | |
| 1059 | return true; | |
| 1060 | } | |
| 1061 | zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481", | |
| 1062 | buf_ptr(&fn_type_id->return_type->name)); | |
| 1060 | return abi_class == X64CABIClass_MEMORY; | |
| 1063 | 1061 | } else if (target_is_arm(&g->zig_target)) { |
| 1064 | 1062 | return type_size(g, fn_type_id->return_type) > 16; |
| 1065 | 1063 | } |
| ... | ... | @@ -1424,6 +1422,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) { |
| 1424 | 1422 | case ZigTypeIdPointer: |
| 1425 | 1423 | case ZigTypeIdArray: |
| 1426 | 1424 | case ZigTypeIdFn: |
| 1425 | case ZigTypeIdVector: | |
| 1427 | 1426 | return true; |
| 1428 | 1427 | case ZigTypeIdStruct: |
| 1429 | 1428 | return type_entry->data.structure.layout == ContainerLayoutPacked; |
| ... | ... | @@ -1472,6 +1471,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1472 | 1471 | default: |
| 1473 | 1472 | return false; |
| 1474 | 1473 | } |
| 1474 | case ZigTypeIdVector: | |
| 1475 | return type_allowed_in_extern(g, type_entry->data.vector.elem_type); | |
| 1475 | 1476 | case ZigTypeIdFloat: |
| 1476 | 1477 | return true; |
| 1477 | 1478 | case ZigTypeIdArray: |
| ... | ... | @@ -1625,6 +1626,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1625 | 1626 | case ZigTypeIdUnion: |
| 1626 | 1627 | case ZigTypeIdFn: |
| 1627 | 1628 | case ZigTypeIdPromise: |
| 1629 | case ZigTypeIdVector: | |
| 1628 | 1630 | switch (type_requires_comptime(g, type_entry)) { |
| 1629 | 1631 | case ReqCompTimeNo: |
| 1630 | 1632 | break; |
| ... | ... | @@ -1720,6 +1722,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1720 | 1722 | case ZigTypeIdUnion: |
| 1721 | 1723 | case ZigTypeIdFn: |
| 1722 | 1724 | case ZigTypeIdPromise: |
| 1725 | case ZigTypeIdVector: | |
| 1723 | 1726 | switch (type_requires_comptime(g, fn_type_id.return_type)) { |
| 1724 | 1727 | case ReqCompTimeInvalid: |
| 1725 | 1728 | return g->builtin_types.entry_invalid; |
| ... | ... | @@ -3577,6 +3580,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry |
| 3577 | 3580 | case ZigTypeIdFn: |
| 3578 | 3581 | case ZigTypeIdBoundFn: |
| 3579 | 3582 | case ZigTypeIdPromise: |
| 3583 | case ZigTypeIdVector: | |
| 3580 | 3584 | return type_entry; |
| 3581 | 3585 | } |
| 3582 | 3586 | zig_unreachable(); |
| ... | ... | @@ -3943,6 +3947,7 @@ static bool is_container(ZigType *type_entry) { |
| 3943 | 3947 | case ZigTypeIdArgTuple: |
| 3944 | 3948 | case ZigTypeIdOpaque: |
| 3945 | 3949 | case ZigTypeIdPromise: |
| 3950 | case ZigTypeIdVector: | |
| 3946 | 3951 | return false; |
| 3947 | 3952 | } |
| 3948 | 3953 | zig_unreachable(); |
| ... | ... | @@ -4002,6 +4007,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) { |
| 4002 | 4007 | case ZigTypeIdArgTuple: |
| 4003 | 4008 | case ZigTypeIdOpaque: |
| 4004 | 4009 | case ZigTypeIdPromise: |
| 4010 | case ZigTypeIdVector: | |
| 4005 | 4011 | zig_unreachable(); |
| 4006 | 4012 | } |
| 4007 | 4013 | } |
| ... | ... | @@ -4451,6 +4457,34 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { |
| 4451 | 4457 | return new_entry; |
| 4452 | 4458 | } |
| 4453 | 4459 | |
| 4460 | ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) { | |
| 4461 | TypeId type_id = {}; | |
| 4462 | type_id.id = ZigTypeIdVector; | |
| 4463 | type_id.data.vector.len = len; | |
| 4464 | type_id.data.vector.elem_type = elem_type; | |
| 4465 | ||
| 4466 | { | |
| 4467 | auto entry = g->type_table.maybe_get(type_id); | |
| 4468 | if (entry) | |
| 4469 | return entry->value; | |
| 4470 | } | |
| 4471 | ||
| 4472 | ZigType *entry = new_type_table_entry(ZigTypeIdVector); | |
| 4473 | entry->zero_bits = (len == 0) || !type_has_bits(elem_type); | |
| 4474 | entry->type_ref = entry->zero_bits ? LLVMVoidType() : LLVMVectorType(elem_type->type_ref, len); | |
| 4475 | entry->data.vector.len = len; | |
| 4476 | entry->data.vector.elem_type = elem_type; | |
| 4477 | ||
| 4478 | buf_resize(&entry->name, 0); | |
| 4479 | buf_appendf(&entry->name, "@Vector(%u, %s)", len, buf_ptr(&elem_type->name)); | |
| 4480 | ||
| 4481 | entry->di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder, len, | |
| 4482 | LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref), elem_type->di_type); | |
| 4483 | ||
| 4484 | g->type_table.put(type_id, entry); | |
| 4485 | return entry; | |
| 4486 | } | |
| 4487 | ||
| 4454 | 4488 | ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) { |
| 4455 | 4489 | return &g->builtin_types.entry_c_int[c_int_type]; |
| 4456 | 4490 | } |
| ... | ... | @@ -4482,6 +4516,7 @@ bool handle_is_ptr(ZigType *type_entry) { |
| 4482 | 4516 | case ZigTypeIdFn: |
| 4483 | 4517 | case ZigTypeIdEnum: |
| 4484 | 4518 | case ZigTypeIdPromise: |
| 4519 | case ZigTypeIdVector: | |
| 4485 | 4520 | return false; |
| 4486 | 4521 | case ZigTypeIdArray: |
| 4487 | 4522 | case ZigTypeIdStruct: |
| ... | ... | @@ -4914,6 +4949,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4914 | 4949 | return hash_const_val_error_set(const_val); |
| 4915 | 4950 | case ZigTypeIdNamespace: |
| 4916 | 4951 | return hash_ptr(const_val->data.x_import); |
| 4952 | case ZigTypeIdVector: | |
| 4953 | // TODO better hashing algorithm | |
| 4954 | return 3647867726; | |
| 4917 | 4955 | case ZigTypeIdBoundFn: |
| 4918 | 4956 | case ZigTypeIdInvalid: |
| 4919 | 4957 | case ZigTypeIdUnreachable: |
| ... | ... | @@ -4966,6 +5004,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { |
| 4966 | 5004 | case ZigTypeIdBool: |
| 4967 | 5005 | case ZigTypeIdUnreachable: |
| 4968 | 5006 | case ZigTypeIdInt: |
| 5007 | case ZigTypeIdVector: | |
| 4969 | 5008 | case ZigTypeIdFloat: |
| 4970 | 5009 | case ZigTypeIdComptimeFloat: |
| 4971 | 5010 | case ZigTypeIdComptimeInt: |
| ... | ... | @@ -5049,6 +5088,7 @@ static bool return_type_is_cacheable(ZigType *return_type) { |
| 5049 | 5088 | case ZigTypeIdErrorSet: |
| 5050 | 5089 | case ZigTypeIdEnum: |
| 5051 | 5090 | case ZigTypeIdPointer: |
| 5091 | case ZigTypeIdVector: | |
| 5052 | 5092 | return true; |
| 5053 | 5093 | |
| 5054 | 5094 | case ZigTypeIdArray: |
| ... | ... | @@ -5201,6 +5241,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { |
| 5201 | 5241 | case ZigTypeIdErrorSet: |
| 5202 | 5242 | case ZigTypeIdEnum: |
| 5203 | 5243 | case ZigTypeIdInt: |
| 5244 | case ZigTypeIdVector: | |
| 5204 | 5245 | return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes; |
| 5205 | 5246 | case ZigTypeIdPointer: |
| 5206 | 5247 | return type_has_one_possible_value(g, type_entry->data.pointer.child_type); |
| ... | ... | @@ -5251,6 +5292,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { |
| 5251 | 5292 | case ZigTypeIdErrorSet: |
| 5252 | 5293 | case ZigTypeIdBool: |
| 5253 | 5294 | case ZigTypeIdInt: |
| 5295 | case ZigTypeIdVector: | |
| 5254 | 5296 | case ZigTypeIdFloat: |
| 5255 | 5297 | case ZigTypeIdVoid: |
| 5256 | 5298 | case ZigTypeIdUnreachable: |
| ... | ... | @@ -5777,7 +5819,7 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5777 | 5819 | ConstExprValue *a_elems = a->data.x_array.data.s_none.elements; |
| 5778 | 5820 | ConstExprValue *b_elems = b->data.x_array.data.s_none.elements; |
| 5779 | 5821 | |
| 5780 | for (size_t i = 0; i < len; ++i) { | |
| 5822 | for (size_t i = 0; i < len; i += 1) { | |
| 5781 | 5823 | if (!const_values_equal(g, &a_elems[i], &b_elems[i])) |
| 5782 | 5824 | return false; |
| 5783 | 5825 | } |
| ... | ... | @@ -5811,6 +5853,20 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5811 | 5853 | case ZigTypeIdArgTuple: |
| 5812 | 5854 | return a->data.x_arg_tuple.start_index == b->data.x_arg_tuple.start_index && |
| 5813 | 5855 | a->data.x_arg_tuple.end_index == b->data.x_arg_tuple.end_index; |
| 5856 | case ZigTypeIdVector: { | |
| 5857 | assert(a->type->data.vector.len == b->type->data.vector.len); | |
| 5858 | ||
| 5859 | size_t len = a->type->data.vector.len; | |
| 5860 | ConstExprValue *a_elems = a->data.x_vector.elements; | |
| 5861 | ConstExprValue *b_elems = b->data.x_vector.elements; | |
| 5862 | ||
| 5863 | for (size_t i = 0; i < len; i += 1) { | |
| 5864 | if (!const_values_equal(g, &a_elems[i], &b_elems[i])) | |
| 5865 | return false; | |
| 5866 | } | |
| 5867 | ||
| 5868 | return true; | |
| 5869 | } | |
| 5814 | 5870 | case ZigTypeIdBoundFn: |
| 5815 | 5871 | case ZigTypeIdInvalid: |
| 5816 | 5872 | case ZigTypeIdUnreachable: |
| ... | ... | @@ -6042,6 +6098,18 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 6042 | 6098 | } |
| 6043 | 6099 | } |
| 6044 | 6100 | zig_unreachable(); |
| 6101 | case ZigTypeIdVector: { | |
| 6102 | buf_appendf(buf, "%s{", buf_ptr(&type_entry->name)); | |
| 6103 | uint64_t len = type_entry->data.vector.len; | |
| 6104 | for (uint32_t i = 0; i < len; i += 1) { | |
| 6105 | if (i != 0) | |
| 6106 | buf_appendf(buf, ","); | |
| 6107 | ConstExprValue *child_value = &const_val->data.x_vector.elements[i]; | |
| 6108 | render_const_value(g, buf, child_value); | |
| 6109 | } | |
| 6110 | buf_appendf(buf, "}"); | |
| 6111 | return; | |
| 6112 | } | |
| 6045 | 6113 | case ZigTypeIdNull: |
| 6046 | 6114 | { |
| 6047 | 6115 | buf_appendf(buf, "null"); |
| ... | ... | @@ -6200,6 +6268,8 @@ uint32_t type_id_hash(TypeId x) { |
| 6200 | 6268 | case ZigTypeIdInt: |
| 6201 | 6269 | return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) + |
| 6202 | 6270 | (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557); |
| 6271 | case ZigTypeIdVector: | |
| 6272 | return hash_ptr(x.data.vector.elem_type) * (x.data.vector.len * 526582681); | |
| 6203 | 6273 | } |
| 6204 | 6274 | zig_unreachable(); |
| 6205 | 6275 | } |
| ... | ... | @@ -6248,6 +6318,9 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 6248 | 6318 | case ZigTypeIdInt: |
| 6249 | 6319 | return a.data.integer.is_signed == b.data.integer.is_signed && |
| 6250 | 6320 | a.data.integer.bit_count == b.data.integer.bit_count; |
| 6321 | case ZigTypeIdVector: | |
| 6322 | return a.data.vector.elem_type == b.data.vector.elem_type && | |
| 6323 | a.data.vector.len == b.data.vector.len; | |
| 6251 | 6324 | } |
| 6252 | 6325 | zig_unreachable(); |
| 6253 | 6326 | } |
| ... | ... | @@ -6382,6 +6455,7 @@ static const ZigTypeId all_type_ids[] = { |
| 6382 | 6455 | ZigTypeIdArgTuple, |
| 6383 | 6456 | ZigTypeIdOpaque, |
| 6384 | 6457 | ZigTypeIdPromise, |
| 6458 | ZigTypeIdVector, | |
| 6385 | 6459 | }; |
| 6386 | 6460 | |
| 6387 | 6461 | ZigTypeId type_id_at_index(size_t index) { |
| ... | ... | @@ -6447,6 +6521,8 @@ size_t type_id_index(ZigType *entry) { |
| 6447 | 6521 | return 22; |
| 6448 | 6522 | case ZigTypeIdPromise: |
| 6449 | 6523 | return 23; |
| 6524 | case ZigTypeIdVector: | |
| 6525 | return 24; | |
| 6450 | 6526 | } |
| 6451 | 6527 | zig_unreachable(); |
| 6452 | 6528 | } |
| ... | ... | @@ -6503,6 +6579,8 @@ const char *type_id_name(ZigTypeId id) { |
| 6503 | 6579 | return "Opaque"; |
| 6504 | 6580 | case ZigTypeIdPromise: |
| 6505 | 6581 | return "Promise"; |
| 6582 | case ZigTypeIdVector: | |
| 6583 | return "Vector"; | |
| 6506 | 6584 | } |
| 6507 | 6585 | zig_unreachable(); |
| 6508 | 6586 | } |
| ... | ... | @@ -6658,6 +6736,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) { |
| 6658 | 6736 | case ZigTypeIdBool: |
| 6659 | 6737 | return X64CABIClass_INTEGER; |
| 6660 | 6738 | case ZigTypeIdFloat: |
| 6739 | case ZigTypeIdVector: | |
| 6661 | 6740 | return X64CABIClass_SSE; |
| 6662 | 6741 | case ZigTypeIdStruct: { |
| 6663 | 6742 | // "If the size of an object is larger than four eightbytes, or it contains unaligned |
src/analyze.hpp+1| ... | ... | @@ -20,6 +20,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 20 | 20 | uint64_t type_size(CodeGen *g, ZigType *type_entry); |
| 21 | 21 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); |
| 22 | 22 | ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); |
| 23 | ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type); | |
| 23 | 24 | ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type); |
| 24 | 25 | ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type); |
| 25 | 26 | ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); |
src/codegen.cpp+46-1| ... | ... | @@ -1980,7 +1980,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1980 | 1980 | break; |
| 1981 | 1981 | } |
| 1982 | 1982 | |
| 1983 | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || | |
| 1983 | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdVector || | |
| 1984 | 1984 | ty->id == ZigTypeIdInt // TODO investigate if we need to change this |
| 1985 | 1985 | ) { |
| 1986 | 1986 | switch (fn_walk->id) { |
| ... | ... | @@ -2660,6 +2660,27 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2660 | 2660 | } else { |
| 2661 | 2661 | return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, ""); |
| 2662 | 2662 | } |
| 2663 | } else if (type_entry->id == ZigTypeIdVector) { | |
| 2664 | ZigType *elem_type = type_entry->data.vector.elem_type; | |
| 2665 | if (elem_type->id == ZigTypeIdFloat) { | |
| 2666 | ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base)); | |
| 2667 | return LLVMBuildFAdd(g->builder, op1_value, op2_value, ""); | |
| 2668 | } else if (elem_type->id == ZigTypeIdPointer) { | |
| 2669 | zig_panic("TODO codegen for pointers in vectors"); | |
| 2670 | } else if (elem_type->id == ZigTypeIdInt) { | |
| 2671 | bool is_wrapping = (op_id == IrBinOpAddWrap); | |
| 2672 | if (is_wrapping) { | |
| 2673 | return LLVMBuildAdd(g->builder, op1_value, op2_value, ""); | |
| 2674 | } else if (want_runtime_safety) { | |
| 2675 | zig_panic("TODO runtime safety for vector integer addition"); | |
| 2676 | } else if (elem_type->data.integral.is_signed) { | |
| 2677 | return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, ""); | |
| 2678 | } else { | |
| 2679 | return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, ""); | |
| 2680 | } | |
| 2681 | } else { | |
| 2682 | zig_unreachable(); | |
| 2683 | } | |
| 2663 | 2684 | } else { |
| 2664 | 2685 | zig_unreachable(); |
| 2665 | 2686 | } |
| ... | ... | @@ -5211,6 +5232,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5211 | 5232 | case IrInstructionIdCUndef: |
| 5212 | 5233 | case IrInstructionIdEmbedFile: |
| 5213 | 5234 | case IrInstructionIdIntType: |
| 5235 | case IrInstructionIdVectorType: | |
| 5214 | 5236 | case IrInstructionIdMemberCount: |
| 5215 | 5237 | case IrInstructionIdMemberType: |
| 5216 | 5238 | case IrInstructionIdMemberName: |
| ... | ... | @@ -5620,6 +5642,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 5620 | 5642 | } |
| 5621 | 5643 | case ZigTypeIdArray: |
| 5622 | 5644 | zig_panic("TODO bit pack an array"); |
| 5645 | case ZigTypeIdVector: | |
| 5646 | zig_panic("TODO bit pack a vector"); | |
| 5623 | 5647 | case ZigTypeIdUnion: |
| 5624 | 5648 | zig_panic("TODO bit pack a union"); |
| 5625 | 5649 | case ZigTypeIdStruct: |
| ... | ... | @@ -5992,6 +6016,14 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5992 | 6016 | } |
| 5993 | 6017 | } |
| 5994 | 6018 | } |
| 6019 | case ZigTypeIdVector: { | |
| 6020 | uint32_t len = type_entry->data.vector.len; | |
| 6021 | LLVMValueRef *values = allocate<LLVMValueRef>(len); | |
| 6022 | for (uint32_t i = 0; i < len; i += 1) { | |
| 6023 | values[i] = gen_const_val(g, &const_val->data.x_vector.elements[i], ""); | |
| 6024 | } | |
| 6025 | return LLVMConstVector(values, len); | |
| 6026 | } | |
| 5995 | 6027 | case ZigTypeIdUnion: |
| 5996 | 6028 | { |
| 5997 | 6029 | LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref; |
| ... | ... | @@ -6927,6 +6959,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 6927 | 6959 | create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); |
| 6928 | 6960 | create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); |
| 6929 | 6961 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int |
| 6962 | create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2); | |
| 6930 | 6963 | create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1); |
| 6931 | 6964 | create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1); |
| 6932 | 6965 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1); |
| ... | ... | @@ -7152,6 +7185,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7152 | 7185 | " ArgTuple: void,\n" |
| 7153 | 7186 | " Opaque: void,\n" |
| 7154 | 7187 | " Promise: Promise,\n" |
| 7188 | " Vector: Vector,\n" | |
| 7155 | 7189 | "\n\n" |
| 7156 | 7190 | " pub const Int = struct {\n" |
| 7157 | 7191 | " is_signed: bool,\n" |
| ... | ... | @@ -7270,6 +7304,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7270 | 7304 | " child: ?type,\n" |
| 7271 | 7305 | " };\n" |
| 7272 | 7306 | "\n" |
| 7307 | " pub const Vector = struct {\n" | |
| 7308 | " len: u32,\n" | |
| 7309 | " child: type,\n" | |
| 7310 | " };\n" | |
| 7311 | "\n" | |
| 7273 | 7312 | " pub const Definition = struct {\n" |
| 7274 | 7313 | " name: []const u8,\n" |
| 7275 | 7314 | " is_pub: bool,\n" |
| ... | ... | @@ -7841,6 +7880,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e |
| 7841 | 7880 | case ZigTypeIdArray: |
| 7842 | 7881 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type); |
| 7843 | 7882 | return; |
| 7883 | case ZigTypeIdVector: | |
| 7884 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.vector.elem_type); | |
| 7885 | return; | |
| 7844 | 7886 | case ZigTypeIdOptional: |
| 7845 | 7887 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type); |
| 7846 | 7888 | return; |
| ... | ... | @@ -7972,6 +8014,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu |
| 7972 | 8014 | buf_appendf(out_buf, "%s", buf_ptr(child_buf)); |
| 7973 | 8015 | return; |
| 7974 | 8016 | } |
| 8017 | case ZigTypeIdVector: | |
| 8018 | zig_panic("TODO implement get_c_type for vector types"); | |
| 7975 | 8019 | case ZigTypeIdErrorUnion: |
| 7976 | 8020 | case ZigTypeIdErrorSet: |
| 7977 | 8021 | case ZigTypeIdFn: |
| ... | ... | @@ -8137,6 +8181,7 @@ static void gen_h_file(CodeGen *g) { |
| 8137 | 8181 | case ZigTypeIdOptional: |
| 8138 | 8182 | case ZigTypeIdFn: |
| 8139 | 8183 | case ZigTypeIdPromise: |
| 8184 | case ZigTypeIdVector: | |
| 8140 | 8185 | zig_unreachable(); |
| 8141 | 8186 | case ZigTypeIdEnum: |
| 8142 | 8187 | if (type_entry->data.enumeration.layout == ContainerLayoutExtern) { |
src/ir.cpp+168-45| ... | ... | @@ -587,6 +587,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) { |
| 587 | 587 | return IrInstructionIdIntType; |
| 588 | 588 | } |
| 589 | 589 | |
| 590 | static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) { | |
| 591 | return IrInstructionIdVectorType; | |
| 592 | } | |
| 593 | ||
| 590 | 594 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) { |
| 591 | 595 | return IrInstructionIdBoolNot; |
| 592 | 596 | } |
| ... | ... | @@ -1953,6 +1957,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s |
| 1953 | 1957 | return &instruction->base; |
| 1954 | 1958 | } |
| 1955 | 1959 | |
| 1960 | static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *len, | |
| 1961 | IrInstruction *elem_type) | |
| 1962 | { | |
| 1963 | IrInstructionVectorType *instruction = ir_build_instruction<IrInstructionVectorType>(irb, scope, source_node); | |
| 1964 | instruction->len = len; | |
| 1965 | instruction->elem_type = elem_type; | |
| 1966 | ||
| 1967 | ir_ref_instruction(len, irb->current_basic_block); | |
| 1968 | ir_ref_instruction(elem_type, irb->current_basic_block); | |
| 1969 | ||
| 1970 | return &instruction->base; | |
| 1971 | } | |
| 1972 | ||
| 1956 | 1973 | static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1957 | 1974 | IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node); |
| 1958 | 1975 | instruction->value = value; |
| ... | ... | @@ -4230,6 +4247,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4230 | 4247 | IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value); |
| 4231 | 4248 | return ir_lval_wrap(irb, scope, int_type, lval); |
| 4232 | 4249 | } |
| 4250 | case BuiltinFnIdVectorType: | |
| 4251 | { | |
| 4252 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 4253 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | |
| 4254 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 4255 | return arg0_value; | |
| 4256 | ||
| 4257 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | |
| 4258 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | |
| 4259 | if (arg1_value == irb->codegen->invalid_instruction) | |
| 4260 | return arg1_value; | |
| 4261 | ||
| 4262 | IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value); | |
| 4263 | return ir_lval_wrap(irb, scope, vector_type, lval); | |
| 4264 | } | |
| 4233 | 4265 | case BuiltinFnIdMemcpy: |
| 4234 | 4266 | { |
| 4235 | 4267 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| ... | ... | @@ -11617,6 +11649,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11617 | 11649 | case ZigTypeIdComptimeInt: |
| 11618 | 11650 | case ZigTypeIdInt: |
| 11619 | 11651 | case ZigTypeIdFloat: |
| 11652 | case ZigTypeIdVector: | |
| 11620 | 11653 | operator_allowed = true; |
| 11621 | 11654 | break; |
| 11622 | 11655 | |
| ... | ... | @@ -12032,6 +12065,48 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b |
| 12032 | 12065 | return result; |
| 12033 | 12066 | } |
| 12034 | 12067 | |
| 12068 | static bool ok_float_op(IrBinOp op) { | |
| 12069 | switch (op) { | |
| 12070 | case IrBinOpInvalid: | |
| 12071 | zig_unreachable(); | |
| 12072 | case IrBinOpAdd: | |
| 12073 | case IrBinOpSub: | |
| 12074 | case IrBinOpMult: | |
| 12075 | case IrBinOpDivUnspecified: | |
| 12076 | case IrBinOpDivTrunc: | |
| 12077 | case IrBinOpDivFloor: | |
| 12078 | case IrBinOpDivExact: | |
| 12079 | case IrBinOpRemRem: | |
| 12080 | case IrBinOpRemMod: | |
| 12081 | return true; | |
| 12082 | ||
| 12083 | case IrBinOpBoolOr: | |
| 12084 | case IrBinOpBoolAnd: | |
| 12085 | case IrBinOpCmpEq: | |
| 12086 | case IrBinOpCmpNotEq: | |
| 12087 | case IrBinOpCmpLessThan: | |
| 12088 | case IrBinOpCmpGreaterThan: | |
| 12089 | case IrBinOpCmpLessOrEq: | |
| 12090 | case IrBinOpCmpGreaterOrEq: | |
| 12091 | case IrBinOpBinOr: | |
| 12092 | case IrBinOpBinXor: | |
| 12093 | case IrBinOpBinAnd: | |
| 12094 | case IrBinOpBitShiftLeftLossy: | |
| 12095 | case IrBinOpBitShiftLeftExact: | |
| 12096 | case IrBinOpBitShiftRightLossy: | |
| 12097 | case IrBinOpBitShiftRightExact: | |
| 12098 | case IrBinOpAddWrap: | |
| 12099 | case IrBinOpSubWrap: | |
| 12100 | case IrBinOpMultWrap: | |
| 12101 | case IrBinOpRemUnspecified: | |
| 12102 | case IrBinOpArrayCat: | |
| 12103 | case IrBinOpArrayMult: | |
| 12104 | case IrBinOpMergeErrorSets: | |
| 12105 | return false; | |
| 12106 | } | |
| 12107 | zig_unreachable(); | |
| 12108 | } | |
| 12109 | ||
| 12035 | 12110 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { |
| 12036 | 12111 | IrInstruction *op1 = instruction->op1->child; |
| 12037 | 12112 | if (type_is_invalid(op1->value.type)) |
| ... | ... | @@ -12169,21 +12244,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 12169 | 12244 | op_id = IrBinOpRemRem; |
| 12170 | 12245 | } |
| 12171 | 12246 | |
| 12247 | bool ok = false; | |
| 12172 | 12248 | if (is_int) { |
| 12173 | // int | |
| 12174 | } else if (is_float && | |
| 12175 | (op_id == IrBinOpAdd || | |
| 12176 | op_id == IrBinOpSub || | |
| 12177 | op_id == IrBinOpMult || | |
| 12178 | op_id == IrBinOpDivUnspecified || | |
| 12179 | op_id == IrBinOpDivTrunc || | |
| 12180 | op_id == IrBinOpDivFloor || | |
| 12181 | op_id == IrBinOpDivExact || | |
| 12182 | op_id == IrBinOpRemRem || | |
| 12183 | op_id == IrBinOpRemMod)) | |
| 12184 | { | |
| 12185 | // float | |
| 12186 | } else { | |
| 12249 | ok = true; | |
| 12250 | } else if (is_float && ok_float_op(op_id)) { | |
| 12251 | ok = true; | |
| 12252 | } else if (resolved_type->id == ZigTypeIdVector) { | |
| 12253 | ZigType *elem_type = resolved_type->data.vector.elem_type; | |
| 12254 | if (elem_type->id == ZigTypeIdInt || elem_type->id == ZigTypeIdComptimeInt) { | |
| 12255 | ok = true; | |
| 12256 | } else if ((elem_type->id == ZigTypeIdFloat || elem_type->id == ZigTypeIdComptimeFloat) && ok_float_op(op_id)) { | |
| 12257 | ok = true; | |
| 12258 | } | |
| 12259 | } | |
| 12260 | if (!ok) { | |
| 12187 | 12261 | AstNode *source_node = instruction->base.source_node; |
| 12188 | 12262 | ir_add_error_node(ira, source_node, |
| 12189 | 12263 | buf_sprintf("invalid operands to binary expression: '%s' and '%s'", |
| ... | ... | @@ -12817,6 +12891,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 12817 | 12891 | case ZigTypeIdPointer: |
| 12818 | 12892 | case ZigTypeIdArray: |
| 12819 | 12893 | case ZigTypeIdBool: |
| 12894 | case ZigTypeIdVector: | |
| 12820 | 12895 | break; |
| 12821 | 12896 | case ZigTypeIdMetaType: |
| 12822 | 12897 | case ZigTypeIdVoid: |
| ... | ... | @@ -12851,6 +12926,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 12851 | 12926 | case ZigTypeIdOptional: |
| 12852 | 12927 | case ZigTypeIdErrorUnion: |
| 12853 | 12928 | case ZigTypeIdErrorSet: |
| 12929 | case ZigTypeIdVector: | |
| 12854 | 12930 | zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name)); |
| 12855 | 12931 | case ZigTypeIdNamespace: |
| 12856 | 12932 | case ZigTypeIdBoundFn: |
| ... | ... | @@ -14009,6 +14085,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_ |
| 14009 | 14085 | case ZigTypeIdVoid: |
| 14010 | 14086 | case ZigTypeIdBool: |
| 14011 | 14087 | case ZigTypeIdInt: |
| 14088 | case ZigTypeIdVector: | |
| 14012 | 14089 | case ZigTypeIdFloat: |
| 14013 | 14090 | case ZigTypeIdPointer: |
| 14014 | 14091 | case ZigTypeIdArray: |
| ... | ... | @@ -15383,37 +15460,7 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio |
| 15383 | 15460 | ZigType *type_entry = expr_value->value.type; |
| 15384 | 15461 | if (type_is_invalid(type_entry)) |
| 15385 | 15462 | return ira->codegen->invalid_instruction; |
| 15386 | switch (type_entry->id) { | |
| 15387 | case ZigTypeIdInvalid: | |
| 15388 | zig_unreachable(); // handled above | |
| 15389 | case ZigTypeIdComptimeFloat: | |
| 15390 | case ZigTypeIdComptimeInt: | |
| 15391 | case ZigTypeIdUndefined: | |
| 15392 | case ZigTypeIdNull: | |
| 15393 | case ZigTypeIdNamespace: | |
| 15394 | case ZigTypeIdBoundFn: | |
| 15395 | case ZigTypeIdMetaType: | |
| 15396 | case ZigTypeIdVoid: | |
| 15397 | case ZigTypeIdBool: | |
| 15398 | case ZigTypeIdUnreachable: | |
| 15399 | case ZigTypeIdInt: | |
| 15400 | case ZigTypeIdFloat: | |
| 15401 | case ZigTypeIdPointer: | |
| 15402 | case ZigTypeIdArray: | |
| 15403 | case ZigTypeIdStruct: | |
| 15404 | case ZigTypeIdOptional: | |
| 15405 | case ZigTypeIdErrorUnion: | |
| 15406 | case ZigTypeIdErrorSet: | |
| 15407 | case ZigTypeIdEnum: | |
| 15408 | case ZigTypeIdUnion: | |
| 15409 | case ZigTypeIdFn: | |
| 15410 | case ZigTypeIdArgTuple: | |
| 15411 | case ZigTypeIdOpaque: | |
| 15412 | case ZigTypeIdPromise: | |
| 15413 | return ir_const_type(ira, &typeof_instruction->base, type_entry); | |
| 15414 | } | |
| 15415 | ||
| 15416 | zig_unreachable(); | |
| 15463 | return ir_const_type(ira, &typeof_instruction->base, type_entry); | |
| 15417 | 15464 | } |
| 15418 | 15465 | |
| 15419 | 15466 | static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira, |
| ... | ... | @@ -15652,6 +15699,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 15652 | 15699 | case ZigTypeIdNamespace: |
| 15653 | 15700 | case ZigTypeIdBoundFn: |
| 15654 | 15701 | case ZigTypeIdPromise: |
| 15702 | case ZigTypeIdVector: | |
| 15655 | 15703 | { |
| 15656 | 15704 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) |
| 15657 | 15705 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -15772,6 +15820,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 15772 | 15820 | case ZigTypeIdNamespace: |
| 15773 | 15821 | case ZigTypeIdBoundFn: |
| 15774 | 15822 | case ZigTypeIdPromise: |
| 15823 | case ZigTypeIdVector: | |
| 15775 | 15824 | { |
| 15776 | 15825 | if ((err = ensure_complete_type(ira->codegen, child_type))) |
| 15777 | 15826 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -15838,6 +15887,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 15838 | 15887 | case ZigTypeIdUnion: |
| 15839 | 15888 | case ZigTypeIdFn: |
| 15840 | 15889 | case ZigTypeIdPromise: |
| 15890 | case ZigTypeIdVector: | |
| 15841 | 15891 | { |
| 15842 | 15892 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); |
| 15843 | 15893 | return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes); |
| ... | ... | @@ -16307,6 +16357,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 16307 | 16357 | case ZigTypeIdBoundFn: |
| 16308 | 16358 | case ZigTypeIdArgTuple: |
| 16309 | 16359 | case ZigTypeIdOpaque: |
| 16360 | case ZigTypeIdVector: | |
| 16310 | 16361 | ir_add_error(ira, &switch_target_instruction->base, |
| 16311 | 16362 | buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); |
| 16312 | 16363 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -17496,6 +17547,27 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17496 | 17547 | |
| 17497 | 17548 | break; |
| 17498 | 17549 | } |
| 17550 | case ZigTypeIdVector: { | |
| 17551 | result = create_const_vals(1); | |
| 17552 | result->special = ConstValSpecialStatic; | |
| 17553 | result->type = ir_type_info_get_type(ira, "Vector", nullptr); | |
| 17554 | ||
| 17555 | ConstExprValue *fields = create_const_vals(2); | |
| 17556 | result->data.x_struct.fields = fields; | |
| 17557 | ||
| 17558 | // len: usize | |
| 17559 | ensure_field_index(result->type, "len", 0); | |
| 17560 | fields[0].special = ConstValSpecialStatic; | |
| 17561 | fields[0].type = ira->codegen->builtin_types.entry_u32; | |
| 17562 | bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.vector.len); | |
| 17563 | // child: type | |
| 17564 | ensure_field_index(result->type, "child", 1); | |
| 17565 | fields[1].special = ConstValSpecialStatic; | |
| 17566 | fields[1].type = ira->codegen->builtin_types.entry_type; | |
| 17567 | fields[1].data.x_type = type_entry->data.vector.elem_type; | |
| 17568 | ||
| 17569 | break; | |
| 17570 | } | |
| 17499 | 17571 | case ZigTypeIdOptional: |
| 17500 | 17572 | { |
| 17501 | 17573 | result = create_const_vals(1); |
| ... | ... | @@ -18671,6 +18743,30 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct |
| 18671 | 18743 | return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count)); |
| 18672 | 18744 | } |
| 18673 | 18745 | |
| 18746 | static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstructionVectorType *instruction) { | |
| 18747 | uint64_t len; | |
| 18748 | if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len)) | |
| 18749 | return ira->codegen->invalid_instruction; | |
| 18750 | ||
| 18751 | ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child); | |
| 18752 | if (type_is_invalid(elem_type)) | |
| 18753 | return ira->codegen->invalid_instruction; | |
| 18754 | ||
| 18755 | if (elem_type->id != ZigTypeIdInt && | |
| 18756 | elem_type->id != ZigTypeIdFloat && | |
| 18757 | get_codegen_ptr_type(elem_type) == nullptr) | |
| 18758 | { | |
| 18759 | ir_add_error(ira, instruction->elem_type, | |
| 18760 | buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid", | |
| 18761 | buf_ptr(&elem_type->name))); | |
| 18762 | return ira->codegen->invalid_instruction; | |
| 18763 | } | |
| 18764 | ||
| 18765 | ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type); | |
| 18766 | ||
| 18767 | return ir_const_type(ira, &instruction->base, vector_type); | |
| 18768 | } | |
| 18769 | ||
| 18674 | 18770 | static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) { |
| 18675 | 18771 | IrInstruction *value = instruction->value->child; |
| 18676 | 18772 | if (type_is_invalid(value->value.type)) |
| ... | ... | @@ -19474,6 +19570,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct |
| 19474 | 19570 | case ZigTypeIdEnum: |
| 19475 | 19571 | case ZigTypeIdUnion: |
| 19476 | 19572 | case ZigTypeIdFn: |
| 19573 | case ZigTypeIdVector: | |
| 19477 | 19574 | { |
| 19478 | 19575 | uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); |
| 19479 | 19576 | return ir_const_unsigned(ira, &instruction->base, align_in_bytes); |
| ... | ... | @@ -20311,6 +20408,15 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20311 | 20408 | } |
| 20312 | 20409 | } |
| 20313 | 20410 | return; |
| 20411 | case ZigTypeIdVector: { | |
| 20412 | size_t buf_i = 0; | |
| 20413 | for (uint32_t elem_i = 0; elem_i < val->type->data.vector.len; elem_i += 1) { | |
| 20414 | ConstExprValue *elem = &val->data.x_vector.elements[elem_i]; | |
| 20415 | buf_write_value_bytes(codegen, &buf[buf_i], elem); | |
| 20416 | buf_i += type_size(codegen, elem->type); | |
| 20417 | } | |
| 20418 | return; | |
| 20419 | } | |
| 20314 | 20420 | case ZigTypeIdStruct: |
| 20315 | 20421 | zig_panic("TODO buf_write_value_bytes struct type"); |
| 20316 | 20422 | case ZigTypeIdOptional: |
| ... | ... | @@ -20387,6 +20493,20 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 20387 | 20493 | } |
| 20388 | 20494 | zig_unreachable(); |
| 20389 | 20495 | } |
| 20496 | case ZigTypeIdVector: { | |
| 20497 | uint64_t elem_size = type_size(codegen, val->type->data.vector.elem_type); | |
| 20498 | uint32_t len = val->type->data.vector.len; | |
| 20499 | ||
| 20500 | val->data.x_vector.elements = create_const_vals(len); | |
| 20501 | for (uint32_t i = 0; i < len; i += 1) { | |
| 20502 | ConstExprValue *elem = &val->data.x_vector.elements[i]; | |
| 20503 | elem->special = ConstValSpecialStatic; | |
| 20504 | elem->type = val->type->data.vector.elem_type; | |
| 20505 | if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem))) | |
| 20506 | return err; | |
| 20507 | } | |
| 20508 | return ErrorNone; | |
| 20509 | } | |
| 20390 | 20510 | case ZigTypeIdEnum: |
| 20391 | 20511 | switch (val->type->data.enumeration.layout) { |
| 20392 | 20512 | case ContainerLayoutAuto: |
| ... | ... | @@ -21633,6 +21753,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21633 | 21753 | return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction); |
| 21634 | 21754 | case IrInstructionIdIntType: |
| 21635 | 21755 | return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction); |
| 21756 | case IrInstructionIdVectorType: | |
| 21757 | return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction); | |
| 21636 | 21758 | case IrInstructionIdBoolNot: |
| 21637 | 21759 | return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction); |
| 21638 | 21760 | case IrInstructionIdMemset: |
| ... | ... | @@ -21943,6 +22065,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21943 | 22065 | case IrInstructionIdEmbedFile: |
| 21944 | 22066 | case IrInstructionIdTruncate: |
| 21945 | 22067 | case IrInstructionIdIntType: |
| 22068 | case IrInstructionIdVectorType: | |
| 21946 | 22069 | case IrInstructionIdBoolNot: |
| 21947 | 22070 | case IrInstructionIdSlice: |
| 21948 | 22071 | case IrInstructionIdMemberCount: |
src/ir_print.cpp+11| ... | ... | @@ -719,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) { |
| 719 | 719 | fprintf(irp->f, ")"); |
| 720 | 720 | } |
| 721 | 721 | |
| 722 | static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruction) { | |
| 723 | fprintf(irp->f, "@Vector("); | |
| 724 | ir_print_other_instruction(irp, instruction->len); | |
| 725 | fprintf(irp->f, ", "); | |
| 726 | ir_print_other_instruction(irp, instruction->elem_type); | |
| 727 | fprintf(irp->f, ")"); | |
| 728 | } | |
| 729 | ||
| 722 | 730 | static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) { |
| 723 | 731 | fprintf(irp->f, "! "); |
| 724 | 732 | ir_print_other_instruction(irp, instruction->value); |
| ... | ... | @@ -1577,6 +1585,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1577 | 1585 | case IrInstructionIdIntType: |
| 1578 | 1586 | ir_print_int_type(irp, (IrInstructionIntType *)instruction); |
| 1579 | 1587 | break; |
| 1588 | case IrInstructionIdVectorType: | |
| 1589 | ir_print_vector_type(irp, (IrInstructionVectorType *)instruction); | |
| 1590 | break; | |
| 1580 | 1591 | case IrInstructionIdBoolNot: |
| 1581 | 1592 | ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction); |
| 1582 | 1593 | break; |
src/zig_llvm.cpp+13| ... | ... | @@ -263,6 +263,19 @@ ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const ch |
| 263 | 263 | return reinterpret_cast<ZigLLVMDIType*>(di_type); |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder, | |
| 267 | uint64_t Size, uint32_t AlignInBits, struct ZigLLVMDIType *Ty) | |
| 268 | { | |
| 269 | SmallVector<Metadata *, 1> subrange; | |
| 270 | subrange.push_back(reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateSubrange(0, Size)); | |
| 271 | DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createVectorType( | |
| 272 | Size, | |
| 273 | AlignInBits, | |
| 274 | reinterpret_cast<DIType*>(Ty), | |
| 275 | reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(subrange)); | |
| 276 | return reinterpret_cast<ZigLLVMDIType*>(di_type); | |
| 277 | } | |
| 278 | ||
| 266 | 279 | ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits, |
| 267 | 280 | uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count) |
| 268 | 281 | { |
src/zig_llvm.h+3| ... | ... | @@ -191,6 +191,9 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB |
| 191 | 191 | unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition, |
| 192 | 192 | unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram); |
| 193 | 193 | |
| 194 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder, | |
| 195 | uint64_t Size, uint32_t AlignInBits, struct ZigLLVMDIType *Ty); | |
| 196 | ||
| 194 | 197 | ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram); |
| 195 | 198 | |
| 196 | 199 | ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder); |
std/hash_map.zig+2| ... | ... | @@ -508,6 +508,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type |
| 508 | 508 | |
| 509 | 509 | builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"), |
| 510 | 510 | builtin.TypeId.Array => @compileError("TODO auto hash for arrays"), |
| 511 | builtin.TypeId.Vector => @compileError("TODO auto hash for vectors"), | |
| 511 | 512 | builtin.TypeId.Struct => @compileError("TODO auto hash for structs"), |
| 512 | 513 | builtin.TypeId.Union => @compileError("TODO auto hash for unions"), |
| 513 | 514 | builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"), |
| ... | ... | @@ -555,5 +556,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool { |
| 555 | 556 | builtin.TypeId.Struct => @compileError("TODO auto eql for structs"), |
| 556 | 557 | builtin.TypeId.Union => @compileError("TODO auto eql for unions"), |
| 557 | 558 | builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"), |
| 559 | builtin.TypeId.Vector => @compileError("TODO auto eql for vectors"), | |
| 558 | 560 | } |
| 559 | 561 | } |
test/stage1/behavior/type_info.zig+14-2| ... | ... | @@ -171,11 +171,11 @@ fn testUnion() void { |
| 171 | 171 | assertOrPanic(TypeId(typeinfo_info) == TypeId.Union); |
| 172 | 172 | assertOrPanic(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); |
| 173 | 173 | assertOrPanic(typeinfo_info.Union.tag_type.? == TypeId); |
| 174 | assertOrPanic(typeinfo_info.Union.fields.len == 24); | |
| 174 | assertOrPanic(typeinfo_info.Union.fields.len == 25); | |
| 175 | 175 | assertOrPanic(typeinfo_info.Union.fields[4].enum_field != null); |
| 176 | 176 | assertOrPanic(typeinfo_info.Union.fields[4].enum_field.?.value == 4); |
| 177 | 177 | assertOrPanic(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); |
| 178 | assertOrPanic(typeinfo_info.Union.defs.len == 20); | |
| 178 | assertOrPanic(typeinfo_info.Union.defs.len == 21); | |
| 179 | 179 | |
| 180 | 180 | const TestNoTagUnion = union { |
| 181 | 181 | Foo: void, |
| ... | ... | @@ -262,3 +262,15 @@ test "typeInfo with comptime parameter in struct fn def" { |
| 262 | 262 | }; |
| 263 | 263 | comptime var info = @typeInfo(S); |
| 264 | 264 | } |
| 265 | ||
| 266 | test "type info: vectors" { | |
| 267 | testVector(); | |
| 268 | comptime testVector(); | |
| 269 | } | |
| 270 | ||
| 271 | fn testVector() void { | |
| 272 | const vec_info = @typeInfo(@Vector(4, i32)); | |
| 273 | assertOrPanic(TypeId(vec_info) == TypeId.Vector); | |
| 274 | assertOrPanic(vec_info.Vector.len == 4); | |
| 275 | assertOrPanic(vec_info.Vector.child == i32); | |
| 276 | } |