| author | |
| committer | |
| log | 2687b8f7f4825c9018af6998e1de140e6185f9cd |
| tree | 4bbd5f609153618e883ad4cce09c7a8c920a22b0 |
| parent | 32e89a98d82c0f4505a3f3d4cd72e7db2eadfbb9 |
The ZIR instruction `union_init_ptr` is renamed to `union_init`.
I made it always use by-value semantics for now, not taking the time to
invest in result location semantics, in case we decide to change the
rules for unions. This way is much simpler.
There is a new AIR instruction: union_init. This is for a comptime known
tag, runtime-known field value.
vector_init is renamed to aggregate_init, which solves a TODO comment.16 files changed, 370 insertions(+), 110 deletions(-)
src/Air.zig+13-5| ... | @@ -561,13 +561,15 @@ pub const Inst = struct { | ... | @@ -561,13 +561,15 @@ pub const Inst = struct { |
| 561 | /// Uses the `un_op` field. | 561 | /// Uses the `un_op` field. |
| 562 | error_name, | 562 | error_name, |
| 563 | 563 | ||
| 564 | /// Constructs a vector, tuple, or array value out of runtime-known elements. | 564 | /// Constructs a vector, tuple, struct, or array value out of runtime-known elements. |
| 565 | /// Some of the elements may be comptime-known. | 565 | /// Some of the elements may be comptime-known. |
| 566 | /// Uses the `ty_pl` field, payload is index of an array of elements, each of which | 566 | /// Uses the `ty_pl` field, payload is index of an array of elements, each of which |
| 567 | /// is a `Ref`. Length of the array is given by the vector type. | 567 | /// is a `Ref`. Length of the array is given by the vector type. |
| 568 | /// TODO rename this to `aggregate_init` and make it support array values and | 568 | aggregate_init, |
| 569 | /// struct values too. | 569 | |
| 570 | vector_init, | 570 | /// Constructs a union from a field index and a runtime-known init value. |
| 571 | /// Uses the `ty_pl` field with payload `UnionInit`. | ||
| 572 | union_init, | ||
| 571 | 573 | ||
| 572 | /// Communicates an intent to load memory. | 574 | /// Communicates an intent to load memory. |
| 573 | /// Result is always unused. | 575 | /// Result is always unused. |
| ... | @@ -768,6 +770,11 @@ pub const AtomicRmw = struct { | ... | @@ -768,6 +770,11 @@ pub const AtomicRmw = struct { |
| 768 | } | 770 | } |
| 769 | }; | 771 | }; |
| 770 | 772 | ||
| 773 | pub const UnionInit = struct { | ||
| 774 | field_index: u32, | ||
| 775 | init: Inst.Ref, | ||
| 776 | }; | ||
| 777 | |||
| 771 | pub fn getMainBody(air: Air) []const Air.Inst.Index { | 778 | pub fn getMainBody(air: Air) []const Air.Inst.Index { |
| 772 | const body_index = air.extra[@enumToInt(ExtraIndex.main_block)]; | 779 | const body_index = air.extra[@enumToInt(ExtraIndex.main_block)]; |
| 773 | const extra = air.extraData(Block, body_index); | 780 | const extra = air.extraData(Block, body_index); |
| ... | @@ -864,7 +871,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -864,7 +871,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 864 | .cmpxchg_weak, | 871 | .cmpxchg_weak, |
| 865 | .cmpxchg_strong, | 872 | .cmpxchg_strong, |
| 866 | .slice, | 873 | .slice, |
| 867 | .vector_init, | 874 | .aggregate_init, |
| 875 | .union_init, | ||
| 868 | .field_parent_ptr, | 876 | .field_parent_ptr, |
| 869 | => return air.getRefType(datas[inst].ty_pl.ty), | 877 | => return air.getRefType(datas[inst].ty_pl.ty), |
| 870 | 878 |
src/AstGen.zig+11-34| ... | @@ -2052,8 +2052,8 @@ fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Sc | ... | @@ -2052,8 +2052,8 @@ fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Sc |
| 2052 | _ = try unusedResultExpr(gz, expr_scope, expr_node); | 2052 | _ = try unusedResultExpr(gz, expr_scope, expr_node); |
| 2053 | } | 2053 | } |
| 2054 | 2054 | ||
| 2055 | /// Returns AST source node of the thing that is noreturn if the statement is definitely `noreturn`. | 2055 | /// Returns AST source node of the thing that is noreturn if the statement is |
| 2056 | /// Otherwise returns 0. | 2056 | /// definitely `noreturn`. Otherwise returns 0. |
| 2057 | fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index { | 2057 | fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index { |
| 2058 | try emitDbgNode(gz, statement); | 2058 | try emitDbgNode(gz, statement); |
| 2059 | // We need to emit an error if the result is not `noreturn` or `void`, but | 2059 | // We need to emit an error if the result is not `noreturn` or `void`, but |
| ... | @@ -2201,7 +2201,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner | ... | @@ -2201,7 +2201,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2201 | .array_init_anon, | 2201 | .array_init_anon, |
| 2202 | .array_init_ref, | 2202 | .array_init_ref, |
| 2203 | .array_init_anon_ref, | 2203 | .array_init_anon_ref, |
| 2204 | .union_init_ptr, | 2204 | .union_init, |
| 2205 | .field_type, | 2205 | .field_type, |
| 2206 | .field_type_ref, | 2206 | .field_type_ref, |
| 2207 | .error_set_decl, | 2207 | .error_set_decl, |
| ... | @@ -6802,40 +6802,17 @@ fn unionInit( | ... | @@ -6802,40 +6802,17 @@ fn unionInit( |
| 6802 | ) InnerError!Zir.Inst.Ref { | 6802 | ) InnerError!Zir.Inst.Ref { |
| 6803 | const union_type = try typeExpr(gz, scope, params[0]); | 6803 | const union_type = try typeExpr(gz, scope, params[0]); |
| 6804 | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); | 6804 | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); |
| 6805 | switch (rl) { | 6805 | const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{ |
| 6806 | .none, .discard, .ref, .ty, .coerced_ty, .inferred_ptr => { | 6806 | .container_type = union_type, |
| 6807 | _ = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{ | 6807 | .field_name = field_name, |
| 6808 | .container_type = union_type, | 6808 | }); |
| 6809 | .field_name = field_name, | 6809 | const init = try reachableExpr(gz, scope, .{ .ty = field_type }, params[2], node); |
| 6810 | }); | 6810 | const result = try gz.addPlNode(.union_init, node, Zir.Inst.UnionInit{ |
| 6811 | const result = try expr(gz, scope, .{ .ty = union_type }, params[2]); | ||
| 6812 | return rvalue(gz, rl, result, node); | ||
| 6813 | }, | ||
| 6814 | .ptr => |result_ptr| { | ||
| 6815 | return unionInitRlPtr(gz, scope, node, result_ptr, params[2], union_type, field_name); | ||
| 6816 | }, | ||
| 6817 | .block_ptr => |block_scope| { | ||
| 6818 | return unionInitRlPtr(gz, scope, node, block_scope.rl_ptr, params[2], union_type, field_name); | ||
| 6819 | }, | ||
| 6820 | } | ||
| 6821 | } | ||
| 6822 | |||
| 6823 | fn unionInitRlPtr( | ||
| 6824 | parent_gz: *GenZir, | ||
| 6825 | scope: *Scope, | ||
| 6826 | node: Ast.Node.Index, | ||
| 6827 | result_ptr: Zir.Inst.Ref, | ||
| 6828 | expr_node: Ast.Node.Index, | ||
| 6829 | union_type: Zir.Inst.Ref, | ||
| 6830 | field_name: Zir.Inst.Ref, | ||
| 6831 | ) InnerError!Zir.Inst.Ref { | ||
| 6832 | const union_init_ptr = try parent_gz.addPlNode(.union_init_ptr, node, Zir.Inst.UnionInitPtr{ | ||
| 6833 | .result_ptr = result_ptr, | ||
| 6834 | .union_type = union_type, | 6811 | .union_type = union_type, |
| 6812 | .init = init, | ||
| 6835 | .field_name = field_name, | 6813 | .field_name = field_name, |
| 6836 | }); | 6814 | }); |
| 6837 | // TODO check if we need to do the elision like below in asRlPtr | 6815 | return rvalue(gz, rl, result, node); |
| 6838 | return expr(parent_gz, scope, .{ .ptr = union_init_ptr }, expr_node); | ||
| 6839 | } | 6816 | } |
| 6840 | 6817 | ||
| 6841 | fn asRlPtr( | 6818 | fn asRlPtr( |
src/Liveness.zig+8-4| ... | @@ -25,7 +25,7 @@ tomb_bits: []usize, | ... | @@ -25,7 +25,7 @@ tomb_bits: []usize, |
| 25 | /// array. The meaning of the data depends on the AIR tag. | 25 | /// array. The meaning of the data depends on the AIR tag. |
| 26 | /// * `cond_br` - points to a `CondBr` in `extra` at this index. | 26 | /// * `cond_br` - points to a `CondBr` in `extra` at this index. |
| 27 | /// * `switch_br` - points to a `SwitchBr` in `extra` at this index. | 27 | /// * `switch_br` - points to a `SwitchBr` in `extra` at this index. |
| 28 | /// * `asm`, `call`, `vector_init` - the value is a set of bits which are the extra tomb | 28 | /// * `asm`, `call`, `aggregate_init` - the value is a set of bits which are the extra tomb |
| 29 | /// bits of operands. | 29 | /// bits of operands. |
| 30 | /// The main tomb bits are still used and the extra ones are starting with the lsb of the | 30 | /// The main tomb bits are still used and the extra ones are starting with the lsb of the |
| 31 | /// value here. | 31 | /// value here. |
| ... | @@ -420,10 +420,10 @@ fn analyzeInst( | ... | @@ -420,10 +420,10 @@ fn analyzeInst( |
| 420 | } | 420 | } |
| 421 | return extra_tombs.finish(); | 421 | return extra_tombs.finish(); |
| 422 | }, | 422 | }, |
| 423 | .vector_init => { | 423 | .aggregate_init => { |
| 424 | const ty_pl = inst_datas[inst].ty_pl; | 424 | const ty_pl = inst_datas[inst].ty_pl; |
| 425 | const vector_ty = a.air.getRefType(ty_pl.ty); | 425 | const aggregate_ty = a.air.getRefType(ty_pl.ty); |
| 426 | const len = @intCast(usize, vector_ty.arrayLen()); | 426 | const len = @intCast(usize, aggregate_ty.arrayLen()); |
| 427 | const elements = @bitCast([]const Air.Inst.Ref, a.air.extra[ty_pl.payload..][0..len]); | 427 | const elements = @bitCast([]const Air.Inst.Ref, a.air.extra[ty_pl.payload..][0..len]); |
| 428 | 428 | ||
| 429 | if (elements.len <= bpi - 1) { | 429 | if (elements.len <= bpi - 1) { |
| ... | @@ -442,6 +442,10 @@ fn analyzeInst( | ... | @@ -442,6 +442,10 @@ fn analyzeInst( |
| 442 | } | 442 | } |
| 443 | return extra_tombs.finish(); | 443 | return extra_tombs.finish(); |
| 444 | }, | 444 | }, |
| 445 | .union_init => { | ||
| 446 | const extra = a.air.extraData(Air.UnionInit, inst_datas[inst].ty_pl.payload).data; | ||
| 447 | return trackOperands(a, new_set, inst, main_tomb, .{ extra.init, .none, .none }); | ||
| 448 | }, | ||
| 445 | .struct_field_ptr, .struct_field_val => { | 449 | .struct_field_ptr, .struct_field_val => { |
| 446 | const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data; | 450 | const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data; |
| 447 | return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_operand, .none, .none }); | 451 | return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_operand, .none, .none }); |
src/Module.zig+9| ... | @@ -1123,6 +1123,15 @@ pub const Union = struct { | ... | @@ -1123,6 +1123,15 @@ pub const Union = struct { |
| 1123 | /// undefined until `status` is `have_field_types` or `have_layout`. | 1123 | /// undefined until `status` is `have_field_types` or `have_layout`. |
| 1124 | ty: Type, | 1124 | ty: Type, |
| 1125 | abi_align: Value, | 1125 | abi_align: Value, |
| 1126 | |||
| 1127 | /// Returns the field alignment, assuming the union is not packed. | ||
| 1128 | pub fn normalAlignment(field: Field, target: Target) u32 { | ||
| 1129 | if (field.abi_align.tag() == .abi_align_default) { | ||
| 1130 | return field.ty.abiAlignment(target); | ||
| 1131 | } else { | ||
| 1132 | return @intCast(u32, field.abi_align.toUnsignedInt()); | ||
| 1133 | } | ||
| 1134 | } | ||
| 1126 | }; | 1135 | }; |
| 1127 | 1136 | ||
| 1128 | pub const Fields = std.StringArrayHashMapUnmanaged(Field); | 1137 | pub const Fields = std.StringArrayHashMapUnmanaged(Field); |
src/Sema.zig+84-29| ... | @@ -204,7 +204,7 @@ pub const Block = struct { | ... | @@ -204,7 +204,7 @@ pub const Block = struct { |
| 204 | return block.namespace.file_scope; | 204 | return block.namespace.file_scope; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | pub fn addTy( | 207 | fn addTy( |
| 208 | block: *Block, | 208 | block: *Block, |
| 209 | tag: Air.Inst.Tag, | 209 | tag: Air.Inst.Tag, |
| 210 | ty: Type, | 210 | ty: Type, |
| ... | @@ -215,7 +215,7 @@ pub const Block = struct { | ... | @@ -215,7 +215,7 @@ pub const Block = struct { |
| 215 | }); | 215 | }); |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | pub fn addTyOp( | 218 | fn addTyOp( |
| 219 | block: *Block, | 219 | block: *Block, |
| 220 | tag: Air.Inst.Tag, | 220 | tag: Air.Inst.Tag, |
| 221 | ty: Type, | 221 | ty: Type, |
| ... | @@ -230,7 +230,7 @@ pub const Block = struct { | ... | @@ -230,7 +230,7 @@ pub const Block = struct { |
| 230 | }); | 230 | }); |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | pub fn addBitCast(block: *Block, ty: Type, operand: Air.Inst.Ref) Allocator.Error!Air.Inst.Ref { | 233 | fn addBitCast(block: *Block, ty: Type, operand: Air.Inst.Ref) Allocator.Error!Air.Inst.Ref { |
| 234 | return block.addInst(.{ | 234 | return block.addInst(.{ |
| 235 | .tag = .bitcast, | 235 | .tag = .bitcast, |
| 236 | .data = .{ .ty_op = .{ | 236 | .data = .{ .ty_op = .{ |
| ... | @@ -240,14 +240,14 @@ pub const Block = struct { | ... | @@ -240,14 +240,14 @@ pub const Block = struct { |
| 240 | }); | 240 | }); |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref { | 243 | fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref { |
| 244 | return block.addInst(.{ | 244 | return block.addInst(.{ |
| 245 | .tag = tag, | 245 | .tag = tag, |
| 246 | .data = .{ .no_op = {} }, | 246 | .data = .{ .no_op = {} }, |
| 247 | }); | 247 | }); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | pub fn addUnOp( | 250 | fn addUnOp( |
| 251 | block: *Block, | 251 | block: *Block, |
| 252 | tag: Air.Inst.Tag, | 252 | tag: Air.Inst.Tag, |
| 253 | operand: Air.Inst.Ref, | 253 | operand: Air.Inst.Ref, |
| ... | @@ -258,7 +258,7 @@ pub const Block = struct { | ... | @@ -258,7 +258,7 @@ pub const Block = struct { |
| 258 | }); | 258 | }); |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | pub fn addBr( | 261 | fn addBr( |
| 262 | block: *Block, | 262 | block: *Block, |
| 263 | target_block: Air.Inst.Index, | 263 | target_block: Air.Inst.Index, |
| 264 | operand: Air.Inst.Ref, | 264 | operand: Air.Inst.Ref, |
| ... | @@ -328,7 +328,7 @@ pub const Block = struct { | ... | @@ -328,7 +328,7 @@ pub const Block = struct { |
| 328 | }); | 328 | }); |
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | pub fn addStructFieldVal( | 331 | fn addStructFieldVal( |
| 332 | block: *Block, | 332 | block: *Block, |
| 333 | struct_val: Air.Inst.Ref, | 333 | struct_val: Air.Inst.Ref, |
| 334 | field_index: u32, | 334 | field_index: u32, |
| ... | @@ -346,7 +346,7 @@ pub const Block = struct { | ... | @@ -346,7 +346,7 @@ pub const Block = struct { |
| 346 | }); | 346 | }); |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | pub fn addSliceElemPtr( | 349 | fn addSliceElemPtr( |
| 350 | block: *Block, | 350 | block: *Block, |
| 351 | slice: Air.Inst.Ref, | 351 | slice: Air.Inst.Ref, |
| 352 | elem_index: Air.Inst.Ref, | 352 | elem_index: Air.Inst.Ref, |
| ... | @@ -364,7 +364,7 @@ pub const Block = struct { | ... | @@ -364,7 +364,7 @@ pub const Block = struct { |
| 364 | }); | 364 | }); |
| 365 | } | 365 | } |
| 366 | 366 | ||
| 367 | pub fn addPtrElemPtr( | 367 | fn addPtrElemPtr( |
| 368 | block: *Block, | 368 | block: *Block, |
| 369 | array_ptr: Air.Inst.Ref, | 369 | array_ptr: Air.Inst.Ref, |
| 370 | elem_index: Air.Inst.Ref, | 370 | elem_index: Air.Inst.Ref, |
| ... | @@ -374,7 +374,7 @@ pub const Block = struct { | ... | @@ -374,7 +374,7 @@ pub const Block = struct { |
| 374 | return block.addPtrElemPtrTypeRef(array_ptr, elem_index, ty_ref); | 374 | return block.addPtrElemPtrTypeRef(array_ptr, elem_index, ty_ref); |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | pub fn addPtrElemPtrTypeRef( | 377 | fn addPtrElemPtrTypeRef( |
| 378 | block: *Block, | 378 | block: *Block, |
| 379 | array_ptr: Air.Inst.Ref, | 379 | array_ptr: Air.Inst.Ref, |
| 380 | elem_index: Air.Inst.Ref, | 380 | elem_index: Air.Inst.Ref, |
| ... | @@ -392,7 +392,7 @@ pub const Block = struct { | ... | @@ -392,7 +392,7 @@ pub const Block = struct { |
| 392 | }); | 392 | }); |
| 393 | } | 393 | } |
| 394 | 394 | ||
| 395 | pub fn addVectorInit( | 395 | fn addAggregateInit( |
| 396 | block: *Block, | 396 | block: *Block, |
| 397 | vector_ty: Type, | 397 | vector_ty: Type, |
| 398 | elements: []const Air.Inst.Ref, | 398 | elements: []const Air.Inst.Ref, |
| ... | @@ -404,7 +404,7 @@ pub const Block = struct { | ... | @@ -404,7 +404,7 @@ pub const Block = struct { |
| 404 | sema.appendRefsAssumeCapacity(elements); | 404 | sema.appendRefsAssumeCapacity(elements); |
| 405 | 405 | ||
| 406 | return block.addInst(.{ | 406 | return block.addInst(.{ |
| 407 | .tag = .vector_init, | 407 | .tag = .aggregate_init, |
| 408 | .data = .{ .ty_pl = .{ | 408 | .data = .{ .ty_pl = .{ |
| 409 | .ty = ty_ref, | 409 | .ty = ty_ref, |
| 410 | .payload = extra_index, | 410 | .payload = extra_index, |
| ... | @@ -412,6 +412,24 @@ pub const Block = struct { | ... | @@ -412,6 +412,24 @@ pub const Block = struct { |
| 412 | }); | 412 | }); |
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | fn addUnionInit( | ||
| 416 | block: *Block, | ||
| 417 | union_ty: Type, | ||
| 418 | field_index: u32, | ||
| 419 | init: Air.Inst.Ref, | ||
| 420 | ) !Air.Inst.Ref { | ||
| 421 | return block.addInst(.{ | ||
| 422 | .tag = .union_init, | ||
| 423 | .data = .{ .ty_pl = .{ | ||
| 424 | .ty = try block.sema.addType(union_ty), | ||
| 425 | .payload = try block.sema.addExtra(Air.UnionInit{ | ||
| 426 | .field_index = field_index, | ||
| 427 | .init = init, | ||
| 428 | }), | ||
| 429 | } }, | ||
| 430 | }); | ||
| 431 | } | ||
| 432 | |||
| 415 | pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { | 433 | pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { |
| 416 | return Air.indexToRef(try block.addInstAsIndex(inst)); | 434 | return Air.indexToRef(try block.addInstAsIndex(inst)); |
| 417 | } | 435 | } |
| ... | @@ -697,7 +715,7 @@ fn analyzeBodyInner( | ... | @@ -697,7 +715,7 @@ fn analyzeBodyInner( |
| 697 | .array_init_ref => try sema.zirArrayInit(block, inst, true), | 715 | .array_init_ref => try sema.zirArrayInit(block, inst, true), |
| 698 | .array_init_anon => try sema.zirArrayInitAnon(block, inst, false), | 716 | .array_init_anon => try sema.zirArrayInitAnon(block, inst, false), |
| 699 | .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true), | 717 | .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true), |
| 700 | .union_init_ptr => try sema.zirUnionInitPtr(block, inst), | 718 | .union_init => try sema.zirUnionInit(block, inst), |
| 701 | .field_type => try sema.zirFieldType(block, inst), | 719 | .field_type => try sema.zirFieldType(block, inst), |
| 702 | .field_type_ref => try sema.zirFieldTypeRef(block, inst), | 720 | .field_type_ref => try sema.zirFieldTypeRef(block, inst), |
| 703 | .ptr_to_int => try sema.zirPtrToInt(block, inst), | 721 | .ptr_to_int => try sema.zirPtrToInt(block, inst), |
| ... | @@ -11273,10 +11291,31 @@ fn arrayInitEmpty(sema: *Sema, obj_ty: Type) CompileError!Air.Inst.Ref { | ... | @@ -11273,10 +11291,31 @@ fn arrayInitEmpty(sema: *Sema, obj_ty: Type) CompileError!Air.Inst.Ref { |
| 11273 | } | 11291 | } |
| 11274 | } | 11292 | } |
| 11275 | 11293 | ||
| 11276 | fn zirUnionInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 11294 | fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 11277 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 11295 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 11278 | const src = inst_data.src(); | 11296 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 11279 | return sema.fail(block, src, "TODO: Sema.zirUnionInitPtr", .{}); | 11297 | const field_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 11298 | const init_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; | ||
| 11299 | const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data; | ||
| 11300 | const union_ty = try sema.resolveType(block, ty_src, extra.union_type); | ||
| 11301 | const field_name = try sema.resolveConstString(block, field_src, extra.field_name); | ||
| 11302 | const init = sema.resolveInst(extra.init); | ||
| 11303 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | ||
| 11304 | const field_index_usize = union_obj.fields.getIndex(field_name) orelse | ||
| 11305 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); | ||
| 11306 | const field_index = @intCast(u32, field_index_usize); | ||
| 11307 | |||
| 11308 | if (try sema.resolveMaybeUndefVal(block, init_src, init)) |init_val| { | ||
| 11309 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); | ||
| 11310 | return sema.addConstant( | ||
| 11311 | union_ty, | ||
| 11312 | try Value.Tag.@"union".create(sema.arena, .{ .tag = tag_val, .val = init_val }), | ||
| 11313 | ); | ||
| 11314 | } | ||
| 11315 | |||
| 11316 | try sema.requireRuntimeBlock(block, init_src); | ||
| 11317 | try sema.resolveTypeLayout(block, ty_src, union_ty); | ||
| 11318 | return block.addUnionInit(union_ty, field_index, init); | ||
| 11280 | } | 11319 | } |
| 11281 | 11320 | ||
| 11282 | fn zirStructInit( | 11321 | fn zirStructInit( |
| ... | @@ -11447,7 +11486,7 @@ fn finishStructInit( | ... | @@ -11447,7 +11486,7 @@ fn finishStructInit( |
| 11447 | } | 11486 | } |
| 11448 | 11487 | ||
| 11449 | try sema.requireRuntimeBlock(block, src); | 11488 | try sema.requireRuntimeBlock(block, src); |
| 11450 | return block.addVectorInit(struct_ty, field_inits); | 11489 | return block.addAggregateInit(struct_ty, field_inits); |
| 11451 | } | 11490 | } |
| 11452 | 11491 | ||
| 11453 | fn zirStructInitAnon(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { | 11492 | fn zirStructInitAnon(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { |
| ... | @@ -11527,7 +11566,7 @@ fn zirArrayInit( | ... | @@ -11527,7 +11566,7 @@ fn zirArrayInit( |
| 11527 | return alloc; | 11566 | return alloc; |
| 11528 | } | 11567 | } |
| 11529 | 11568 | ||
| 11530 | return block.addVectorInit(array_ty, resolved_args); | 11569 | return block.addAggregateInit(array_ty, resolved_args); |
| 11531 | } | 11570 | } |
| 11532 | 11571 | ||
| 11533 | fn zirArrayInitAnon( | 11572 | fn zirArrayInitAnon( |
| ... | @@ -11593,7 +11632,7 @@ fn zirArrayInitAnon( | ... | @@ -11593,7 +11632,7 @@ fn zirArrayInitAnon( |
| 11593 | element_refs[i] = sema.resolveInst(operand); | 11632 | element_refs[i] = sema.resolveInst(operand); |
| 11594 | } | 11633 | } |
| 11595 | 11634 | ||
| 11596 | return block.addVectorInit(tuple_ty, element_refs); | 11635 | return block.addAggregateInit(tuple_ty, element_refs); |
| 11597 | } | 11636 | } |
| 11598 | 11637 | ||
| 11599 | fn addConstantMaybeRef( | 11638 | fn addConstantMaybeRef( |
| ... | @@ -11617,31 +11656,47 @@ fn addConstantMaybeRef( | ... | @@ -11617,31 +11656,47 @@ fn addConstantMaybeRef( |
| 11617 | 11656 | ||
| 11618 | fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 11657 | fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 11619 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 11658 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 11620 | const src = inst_data.src(); | 11659 | const extra = sema.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data; |
| 11621 | return sema.fail(block, src, "TODO: Sema.zirFieldTypeRef", .{}); | 11660 | const ty_src = inst_data.src(); |
| 11661 | const field_src = inst_data.src(); | ||
| 11662 | const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type); | ||
| 11663 | const field_name = try sema.resolveConstString(block, field_src, extra.field_name); | ||
| 11664 | return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src); | ||
| 11622 | } | 11665 | } |
| 11623 | 11666 | ||
| 11624 | fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 11667 | fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 11625 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 11668 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 11626 | const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; | 11669 | const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; |
| 11627 | const src = inst_data.src(); | 11670 | const ty_src = inst_data.src(); |
| 11671 | const field_src = inst_data.src(); | ||
| 11672 | const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type); | ||
| 11628 | const field_name = sema.code.nullTerminatedString(extra.name_start); | 11673 | const field_name = sema.code.nullTerminatedString(extra.name_start); |
| 11629 | const unresolved_ty = try sema.resolveType(block, src, extra.container_type); | 11674 | return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src); |
| 11630 | const resolved_ty = try sema.resolveTypeFields(block, src, unresolved_ty); | 11675 | } |
| 11676 | |||
| 11677 | fn fieldType( | ||
| 11678 | sema: *Sema, | ||
| 11679 | block: *Block, | ||
| 11680 | aggregate_ty: Type, | ||
| 11681 | field_name: []const u8, | ||
| 11682 | field_src: LazySrcLoc, | ||
| 11683 | ty_src: LazySrcLoc, | ||
| 11684 | ) CompileError!Air.Inst.Ref { | ||
| 11685 | const resolved_ty = try sema.resolveTypeFields(block, ty_src, aggregate_ty); | ||
| 11631 | switch (resolved_ty.zigTypeTag()) { | 11686 | switch (resolved_ty.zigTypeTag()) { |
| 11632 | .Struct => { | 11687 | .Struct => { |
| 11633 | const struct_obj = resolved_ty.castTag(.@"struct").?.data; | 11688 | const struct_obj = resolved_ty.castTag(.@"struct").?.data; |
| 11634 | const field = struct_obj.fields.get(field_name) orelse | 11689 | const field = struct_obj.fields.get(field_name) orelse |
| 11635 | return sema.failWithBadStructFieldAccess(block, struct_obj, src, field_name); | 11690 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 11636 | return sema.addType(field.ty); | 11691 | return sema.addType(field.ty); |
| 11637 | }, | 11692 | }, |
| 11638 | .Union => { | 11693 | .Union => { |
| 11639 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; | 11694 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; |
| 11640 | const field = union_obj.fields.get(field_name) orelse | 11695 | const field = union_obj.fields.get(field_name) orelse |
| 11641 | return sema.failWithBadUnionFieldAccess(block, union_obj, src, field_name); | 11696 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| 11642 | return sema.addType(field.ty); | 11697 | return sema.addType(field.ty); |
| 11643 | }, | 11698 | }, |
| 11644 | else => return sema.fail(block, src, "expected struct or union; found '{}'", .{ | 11699 | else => return sema.fail(block, ty_src, "expected struct or union; found '{}'", .{ |
| 11645 | resolved_ty, | 11700 | resolved_ty, |
| 11646 | }), | 11701 | }), |
| 11647 | } | 11702 | } |
| ... | @@ -16396,7 +16451,7 @@ fn coerceArrayLike( | ... | @@ -16396,7 +16451,7 @@ fn coerceArrayLike( |
| 16396 | 16451 | ||
| 16397 | if (runtime_src) |rs| { | 16452 | if (runtime_src) |rs| { |
| 16398 | try sema.requireRuntimeBlock(block, rs); | 16453 | try sema.requireRuntimeBlock(block, rs); |
| 16399 | return block.addVectorInit(dest_ty, element_refs); | 16454 | return block.addAggregateInit(dest_ty, element_refs); |
| 16400 | } | 16455 | } |
| 16401 | 16456 | ||
| 16402 | return sema.addConstant( | 16457 | return sema.addConstant( |
| ... | @@ -16453,7 +16508,7 @@ fn coerceTupleToArray( | ... | @@ -16453,7 +16508,7 @@ fn coerceTupleToArray( |
| 16453 | 16508 | ||
| 16454 | if (runtime_src) |rs| { | 16509 | if (runtime_src) |rs| { |
| 16455 | try sema.requireRuntimeBlock(block, rs); | 16510 | try sema.requireRuntimeBlock(block, rs); |
| 16456 | return block.addVectorInit(dest_ty, element_refs); | 16511 | return block.addAggregateInit(dest_ty, element_refs); |
| 16457 | } | 16512 | } |
| 16458 | 16513 | ||
| 16459 | return sema.addConstant( | 16514 | return sema.addConstant( |
src/Zir.zig+7-8| ... | @@ -721,10 +721,9 @@ pub const Inst = struct { | ... | @@ -721,10 +721,9 @@ pub const Inst = struct { |
| 721 | /// Anonymous array initialization syntax, make the result a pointer. | 721 | /// Anonymous array initialization syntax, make the result a pointer. |
| 722 | /// Uses the `pl_node` field. Payload is `MultiOp`. | 722 | /// Uses the `pl_node` field. Payload is `MultiOp`. |
| 723 | array_init_anon_ref, | 723 | array_init_anon_ref, |
| 724 | /// Given a pointer to a union and a comptime known field name, activates that field | 724 | /// Implements the `@unionInit` builtin. |
| 725 | /// and returns a pointer to it. | 725 | /// Uses the `pl_node` field. Payload is `UnionInit`. |
| 726 | /// Uses the `pl_node` field. Payload is `UnionInitPtr`. | 726 | union_init, |
| 727 | union_init_ptr, | ||
| 728 | /// Implements the `@typeInfo` builtin. Uses `un_node`. | 727 | /// Implements the `@typeInfo` builtin. Uses `un_node`. |
| 729 | type_info, | 728 | type_info, |
| 730 | /// Implements the `@sizeOf` builtin. Uses `un_node`. | 729 | /// Implements the `@sizeOf` builtin. Uses `un_node`. |
| ... | @@ -1125,7 +1124,7 @@ pub const Inst = struct { | ... | @@ -1125,7 +1124,7 @@ pub const Inst = struct { |
| 1125 | .array_init_anon, | 1124 | .array_init_anon, |
| 1126 | .array_init_ref, | 1125 | .array_init_ref, |
| 1127 | .array_init_anon_ref, | 1126 | .array_init_anon_ref, |
| 1128 | .union_init_ptr, | 1127 | .union_init, |
| 1129 | .field_type, | 1128 | .field_type, |
| 1130 | .field_type_ref, | 1129 | .field_type_ref, |
| 1131 | .int_to_enum, | 1130 | .int_to_enum, |
| ... | @@ -1383,7 +1382,7 @@ pub const Inst = struct { | ... | @@ -1383,7 +1382,7 @@ pub const Inst = struct { |
| 1383 | .array_init_anon = .pl_node, | 1382 | .array_init_anon = .pl_node, |
| 1384 | .array_init_ref = .pl_node, | 1383 | .array_init_ref = .pl_node, |
| 1385 | .array_init_anon_ref = .pl_node, | 1384 | .array_init_anon_ref = .pl_node, |
| 1386 | .union_init_ptr = .pl_node, | 1385 | .union_init = .pl_node, |
| 1387 | .type_info = .un_node, | 1386 | .type_info = .un_node, |
| 1388 | .size_of = .un_node, | 1387 | .size_of = .un_node, |
| 1389 | .bit_size_of = .un_node, | 1388 | .bit_size_of = .un_node, |
| ... | @@ -2896,10 +2895,10 @@ pub const Inst = struct { | ... | @@ -2896,10 +2895,10 @@ pub const Inst = struct { |
| 2896 | ordering: Ref, | 2895 | ordering: Ref, |
| 2897 | }; | 2896 | }; |
| 2898 | 2897 | ||
| 2899 | pub const UnionInitPtr = struct { | 2898 | pub const UnionInit = struct { |
| 2900 | result_ptr: Ref, | ||
| 2901 | union_type: Ref, | 2899 | union_type: Ref, |
| 2902 | field_name: Ref, | 2900 | field_name: Ref, |
| 2901 | init: Ref, | ||
| 2903 | }; | 2902 | }; |
| 2904 | 2903 | ||
| 2905 | pub const AtomicStore = struct { | 2904 | pub const AtomicStore = struct { |
src/arch/aarch64/CodeGen.zig+11-3| ... | @@ -625,7 +625,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -625,7 +625,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 625 | .tag_name => try self.airTagName(inst), | 625 | .tag_name => try self.airTagName(inst), |
| 626 | .error_name => try self.airErrorName(inst), | 626 | .error_name => try self.airErrorName(inst), |
| 627 | .splat => try self.airSplat(inst), | 627 | .splat => try self.airSplat(inst), |
| 628 | .vector_init => try self.airVectorInit(inst), | 628 | .aggregate_init => try self.airAggregateInit(inst), |
| 629 | .union_init => try self.airUnionInit(inst), | ||
| 629 | .prefetch => try self.airPrefetch(inst), | 630 | .prefetch => try self.airPrefetch(inst), |
| 630 | 631 | ||
| 631 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), | 632 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), |
| ... | @@ -3472,14 +3473,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3472,14 +3473,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 3472 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 3473 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3473 | } | 3474 | } |
| 3474 | 3475 | ||
| 3475 | fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { | 3476 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 3476 | const vector_ty = self.air.typeOfIndex(inst); | 3477 | const vector_ty = self.air.typeOfIndex(inst); |
| 3477 | const len = vector_ty.vectorLen(); | 3478 | const len = vector_ty.vectorLen(); |
| 3478 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 3479 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3479 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 3480 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 3480 | const result: MCValue = res: { | 3481 | const result: MCValue = res: { |
| 3481 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; | 3482 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; |
| 3482 | return self.fail("TODO implement airVectorInit for {}", .{self.target.cpu.arch}); | 3483 | return self.fail("TODO implement airAggregateInit for {}", .{self.target.cpu.arch}); |
| 3483 | }; | 3484 | }; |
| 3484 | 3485 | ||
| 3485 | if (elements.len <= Liveness.bpi - 1) { | 3486 | if (elements.len <= Liveness.bpi - 1) { |
| ... | @@ -3494,6 +3495,13 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3494,6 +3495,13 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { |
| 3494 | return bt.finishAir(result); | 3495 | return bt.finishAir(result); |
| 3495 | } | 3496 | } |
| 3496 | 3497 | ||
| 3498 | fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { | ||
| 3499 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | ||
| 3500 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; | ||
| 3501 | _ = extra; | ||
| 3502 | return self.fail("TODO implement airUnionInit for aarch64", .{}); | ||
| 3503 | } | ||
| 3504 | |||
| 3497 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { | 3505 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { |
| 3498 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; | 3506 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; |
| 3499 | return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none }); | 3507 | return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none }); |
src/arch/arm/CodeGen.zig+12-3| ... | @@ -609,7 +609,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -609,7 +609,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 609 | .tag_name => try self.airTagName(inst), | 609 | .tag_name => try self.airTagName(inst), |
| 610 | .error_name => try self.airErrorName(inst), | 610 | .error_name => try self.airErrorName(inst), |
| 611 | .splat => try self.airSplat(inst), | 611 | .splat => try self.airSplat(inst), |
| 612 | .vector_init => try self.airVectorInit(inst), | 612 | .aggregate_init => try self.airAggregateInit(inst), |
| 613 | .union_init => try self.airUnionInit(inst), | ||
| 613 | .prefetch => try self.airPrefetch(inst), | 614 | .prefetch => try self.airPrefetch(inst), |
| 614 | 615 | ||
| 615 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), | 616 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), |
| ... | @@ -3937,14 +3938,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3937,14 +3938,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 3937 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 3938 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3938 | } | 3939 | } |
| 3939 | 3940 | ||
| 3940 | fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { | 3941 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 3941 | const vector_ty = self.air.typeOfIndex(inst); | 3942 | const vector_ty = self.air.typeOfIndex(inst); |
| 3942 | const len = vector_ty.vectorLen(); | 3943 | const len = vector_ty.vectorLen(); |
| 3943 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 3944 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3944 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 3945 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 3945 | const result: MCValue = res: { | 3946 | const result: MCValue = res: { |
| 3946 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; | 3947 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; |
| 3947 | return self.fail("TODO implement airVectorInit for arm", .{}); | 3948 | return self.fail("TODO implement airAggregateInit for arm", .{}); |
| 3948 | }; | 3949 | }; |
| 3949 | 3950 | ||
| 3950 | if (elements.len <= Liveness.bpi - 1) { | 3951 | if (elements.len <= Liveness.bpi - 1) { |
| ... | @@ -3959,6 +3960,14 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3959,6 +3960,14 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { |
| 3959 | return bt.finishAir(result); | 3960 | return bt.finishAir(result); |
| 3960 | } | 3961 | } |
| 3961 | 3962 | ||
| 3963 | fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { | ||
| 3964 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | ||
| 3965 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; | ||
| 3966 | _ = extra; | ||
| 3967 | |||
| 3968 | return self.fail("TODO implement airUnionInit for arm", .{}); | ||
| 3969 | } | ||
| 3970 | |||
| 3962 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { | 3971 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { |
| 3963 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; | 3972 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; |
| 3964 | return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none }); | 3973 | return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none }); |
src/arch/riscv64/CodeGen.zig+12-3| ... | @@ -596,7 +596,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -596,7 +596,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 596 | .tag_name => try self.airTagName(inst), | 596 | .tag_name => try self.airTagName(inst), |
| 597 | .error_name => try self.airErrorName(inst), | 597 | .error_name => try self.airErrorName(inst), |
| 598 | .splat => try self.airSplat(inst), | 598 | .splat => try self.airSplat(inst), |
| 599 | .vector_init => try self.airVectorInit(inst), | 599 | .aggregate_init => try self.airAggregateInit(inst), |
| 600 | .union_init => try self.airUnionInit(inst), | ||
| 600 | .prefetch => try self.airPrefetch(inst), | 601 | .prefetch => try self.airPrefetch(inst), |
| 601 | 602 | ||
| 602 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), | 603 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), |
| ... | @@ -2157,14 +2158,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2157,14 +2158,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 2157 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2158 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2158 | } | 2159 | } |
| 2159 | 2160 | ||
| 2160 | fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { | 2161 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 2161 | const vector_ty = self.air.typeOfIndex(inst); | 2162 | const vector_ty = self.air.typeOfIndex(inst); |
| 2162 | const len = vector_ty.vectorLen(); | 2163 | const len = vector_ty.vectorLen(); |
| 2163 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2164 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2164 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 2165 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 2165 | const result: MCValue = res: { | 2166 | const result: MCValue = res: { |
| 2166 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; | 2167 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; |
| 2167 | return self.fail("TODO implement airVectorInit for riscv64", .{}); | 2168 | return self.fail("TODO implement airAggregateInit for riscv64", .{}); |
| 2168 | }; | 2169 | }; |
| 2169 | 2170 | ||
| 2170 | if (elements.len <= Liveness.bpi - 1) { | 2171 | if (elements.len <= Liveness.bpi - 1) { |
| ... | @@ -2179,6 +2180,14 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2179,6 +2180,14 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { |
| 2179 | return bt.finishAir(result); | 2180 | return bt.finishAir(result); |
| 2180 | } | 2181 | } |
| 2181 | 2182 | ||
| 2183 | fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { | ||
| 2184 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | ||
| 2185 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; | ||
| 2186 | _ = extra; | ||
| 2187 | return self.fail("TODO implement airUnionInit for riscv64", .{}); | ||
| 2188 | // return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value }); | ||
| 2189 | } | ||
| 2190 | |||
| 2182 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { | 2191 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { |
| 2183 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; | 2192 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; |
| 2184 | return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none }); | 2193 | return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none }); |
src/arch/wasm/CodeGen.zig+9-3| ... | @@ -1642,7 +1642,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1642,7 +1642,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1642 | .ret_ptr => self.airRetPtr(inst), | 1642 | .ret_ptr => self.airRetPtr(inst), |
| 1643 | .ret_load => self.airRetLoad(inst), | 1643 | .ret_load => self.airRetLoad(inst), |
| 1644 | .splat => self.airSplat(inst), | 1644 | .splat => self.airSplat(inst), |
| 1645 | .vector_init => self.airVectorInit(inst), | 1645 | .aggregate_init => self.airAggregateInit(inst), |
| 1646 | .union_init => self.airUnionInit(inst), | ||
| 1646 | .prefetch => self.airPrefetch(inst), | 1647 | .prefetch => self.airPrefetch(inst), |
| 1647 | 1648 | ||
| 1648 | .slice => self.airSlice(inst), | 1649 | .slice => self.airSlice(inst), |
| ... | @@ -3350,7 +3351,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3350,7 +3351,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3350 | return self.fail("TODO: Implement wasm airSplat", .{}); | 3351 | return self.fail("TODO: Implement wasm airSplat", .{}); |
| 3351 | } | 3352 | } |
| 3352 | 3353 | ||
| 3353 | fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 3354 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3354 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; | 3355 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 3355 | 3356 | ||
| 3356 | const vector_ty = self.air.typeOfIndex(inst); | 3357 | const vector_ty = self.air.typeOfIndex(inst); |
| ... | @@ -3359,7 +3360,7 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3359,7 +3360,7 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3359 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 3360 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 3360 | 3361 | ||
| 3361 | switch (vector_ty.zigTypeTag()) { | 3362 | switch (vector_ty.zigTypeTag()) { |
| 3362 | .Vector => return self.fail("TODO: Wasm backend: implement airVectorInit for vectors", .{}), | 3363 | .Vector => return self.fail("TODO: Wasm backend: implement airAggregateInit for vectors", .{}), |
| 3363 | .Array => { | 3364 | .Array => { |
| 3364 | const result = try self.allocStack(vector_ty); | 3365 | const result = try self.allocStack(vector_ty); |
| 3365 | const elem_ty = vector_ty.childType(); | 3366 | const elem_ty = vector_ty.childType(); |
| ... | @@ -3413,6 +3414,11 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3413,6 +3414,11 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3413 | } | 3414 | } |
| 3414 | } | 3415 | } |
| 3415 | 3416 | ||
| 3417 | fn airUnionInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ||
| 3418 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; | ||
| 3419 | return self.fail("TODO: Wasm backend: implement airUnionInit", .{}); | ||
| 3420 | } | ||
| 3421 | |||
| 3416 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 3422 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3417 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; | 3423 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; |
| 3418 | _ = prefetch; | 3424 | _ = prefetch; |
src/arch/x86_64/CodeGen.zig+14-3| ... | @@ -708,7 +708,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -708,7 +708,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 708 | .tag_name => try self.airTagName(inst), | 708 | .tag_name => try self.airTagName(inst), |
| 709 | .error_name => try self.airErrorName(inst), | 709 | .error_name => try self.airErrorName(inst), |
| 710 | .splat => try self.airSplat(inst), | 710 | .splat => try self.airSplat(inst), |
| 711 | .vector_init => try self.airVectorInit(inst), | 711 | .aggregate_init => try self.airAggregateInit(inst), |
| 712 | .union_init => try self.airUnionInit(inst), | ||
| 712 | .prefetch => try self.airPrefetch(inst), | 713 | .prefetch => try self.airPrefetch(inst), |
| 713 | 714 | ||
| 714 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), | 715 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), |
| ... | @@ -5232,14 +5233,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5232,14 +5233,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 5232 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 5233 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 5233 | } | 5234 | } |
| 5234 | 5235 | ||
| 5235 | fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { | 5236 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 5236 | const vector_ty = self.air.typeOfIndex(inst); | 5237 | const vector_ty = self.air.typeOfIndex(inst); |
| 5237 | const len = vector_ty.vectorLen(); | 5238 | const len = vector_ty.vectorLen(); |
| 5238 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 5239 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 5239 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 5240 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 5240 | const result: MCValue = res: { | 5241 | const result: MCValue = res: { |
| 5241 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; | 5242 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; |
| 5242 | return self.fail("TODO implement airVectorInit for x86_64", .{}); | 5243 | return self.fail("TODO implement airAggregateInit for x86_64", .{}); |
| 5243 | }; | 5244 | }; |
| 5244 | 5245 | ||
| 5245 | if (elements.len <= Liveness.bpi - 1) { | 5246 | if (elements.len <= Liveness.bpi - 1) { |
| ... | @@ -5254,6 +5255,16 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5254,6 +5255,16 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void { |
| 5254 | return bt.finishAir(result); | 5255 | return bt.finishAir(result); |
| 5255 | } | 5256 | } |
| 5256 | 5257 | ||
| 5258 | fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { | ||
| 5259 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | ||
| 5260 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; | ||
| 5261 | const result: MCValue = res: { | ||
| 5262 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; | ||
| 5263 | return self.fail("TODO implement airAggregateInit for x86_64", .{}); | ||
| 5264 | }; | ||
| 5265 | return self.finishAir(inst, result, .{ extra.init, .none, .none }); | ||
| 5266 | } | ||
| 5267 | |||
| 5257 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { | 5268 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { |
| 5258 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; | 5269 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; |
| 5259 | return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none }); | 5270 | return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none }); |
src/codegen/c.zig+19-3| ... | @@ -1713,7 +1713,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -1713,7 +1713,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1713 | .tag_name => try airTagName(f, inst), | 1713 | .tag_name => try airTagName(f, inst), |
| 1714 | .error_name => try airErrorName(f, inst), | 1714 | .error_name => try airErrorName(f, inst), |
| 1715 | .splat => try airSplat(f, inst), | 1715 | .splat => try airSplat(f, inst), |
| 1716 | .vector_init => try airVectorInit(f, inst), | 1716 | .aggregate_init => try airAggregateInit(f, inst), |
| 1717 | .union_init => try airUnionInit(f, inst), | ||
| 1717 | .prefetch => try airPrefetch(f, inst), | 1718 | .prefetch => try airPrefetch(f, inst), |
| 1718 | 1719 | ||
| 1719 | .int_to_float, | 1720 | .int_to_float, |
| ... | @@ -3526,7 +3527,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3526,7 +3527,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3526 | return f.fail("TODO: C backend: implement airSplat", .{}); | 3527 | return f.fail("TODO: C backend: implement airSplat", .{}); |
| 3527 | } | 3528 | } |
| 3528 | 3529 | ||
| 3529 | fn airVectorInit(f: *Function, inst: Air.Inst.Index) !CValue { | 3530 | fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3530 | if (f.liveness.isUnused(inst)) return CValue.none; | 3531 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 3531 | 3532 | ||
| 3532 | const inst_ty = f.air.typeOfIndex(inst); | 3533 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -3541,7 +3542,22 @@ fn airVectorInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3541,7 +3542,22 @@ fn airVectorInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3541 | 3542 | ||
| 3542 | _ = elements; | 3543 | _ = elements; |
| 3543 | _ = local; | 3544 | _ = local; |
| 3544 | return f.fail("TODO: C backend: implement airVectorInit", .{}); | 3545 | return f.fail("TODO: C backend: implement airAggregateInit", .{}); |
| 3546 | } | ||
| 3547 | |||
| 3548 | fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ||
| 3549 | if (f.liveness.isUnused(inst)) return CValue.none; | ||
| 3550 | |||
| 3551 | const inst_ty = f.air.typeOfIndex(inst); | ||
| 3552 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | ||
| 3553 | |||
| 3554 | const writer = f.object.writer(); | ||
| 3555 | const local = try f.allocLocal(inst_ty, .Const); | ||
| 3556 | try writer.writeAll(" = "); | ||
| 3557 | |||
| 3558 | _ = local; | ||
| 3559 | _ = ty_pl; | ||
| 3560 | return f.fail("TODO: C backend: implement airUnionInit", .{}); | ||
| 3545 | } | 3561 | } |
| 3546 | 3562 | ||
| 3547 | fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { | 3563 | fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
src/codegen/llvm.zig+106-2| ... | @@ -2175,7 +2175,8 @@ pub const FuncGen = struct { | ... | @@ -2175,7 +2175,8 @@ pub const FuncGen = struct { |
| 2175 | .tag_name => try self.airTagName(inst), | 2175 | .tag_name => try self.airTagName(inst), |
| 2176 | .error_name => try self.airErrorName(inst), | 2176 | .error_name => try self.airErrorName(inst), |
| 2177 | .splat => try self.airSplat(inst), | 2177 | .splat => try self.airSplat(inst), |
| 2178 | .vector_init => try self.airVectorInit(inst), | 2178 | .aggregate_init => try self.airAggregateInit(inst), |
| 2179 | .union_init => try self.airUnionInit(inst), | ||
| 2179 | .prefetch => try self.airPrefetch(inst), | 2180 | .prefetch => try self.airPrefetch(inst), |
| 2180 | 2181 | ||
| 2181 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), | 2182 | .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), |
| ... | @@ -4608,7 +4609,7 @@ pub const FuncGen = struct { | ... | @@ -4608,7 +4609,7 @@ pub const FuncGen = struct { |
| 4608 | return self.builder.buildShuffleVector(op_vector, undef_vector, mask_llvm_ty.constNull(), ""); | 4609 | return self.builder.buildShuffleVector(op_vector, undef_vector, mask_llvm_ty.constNull(), ""); |
| 4609 | } | 4610 | } |
| 4610 | 4611 | ||
| 4611 | fn airVectorInit(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 4612 | fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 4612 | if (self.liveness.isUnused(inst)) return null; | 4613 | if (self.liveness.isUnused(inst)) return null; |
| 4613 | 4614 | ||
| 4614 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 4615 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| ... | @@ -4693,6 +4694,109 @@ pub const FuncGen = struct { | ... | @@ -4693,6 +4694,109 @@ pub const FuncGen = struct { |
| 4693 | } | 4694 | } |
| 4694 | } | 4695 | } |
| 4695 | 4696 | ||
| 4697 | fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | ||
| 4698 | if (self.liveness.isUnused(inst)) return null; | ||
| 4699 | |||
| 4700 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | ||
| 4701 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; | ||
| 4702 | const union_ty = self.air.typeOfIndex(inst); | ||
| 4703 | const union_llvm_ty = try self.dg.llvmType(union_ty); | ||
| 4704 | const target = self.dg.module.getTarget(); | ||
| 4705 | const layout = union_ty.unionGetLayout(target); | ||
| 4706 | if (layout.payload_size == 0) { | ||
| 4707 | if (layout.tag_size == 0) { | ||
| 4708 | return null; | ||
| 4709 | } | ||
| 4710 | assert(!isByRef(union_ty)); | ||
| 4711 | return union_llvm_ty.constInt(extra.field_index, .False); | ||
| 4712 | } | ||
| 4713 | assert(isByRef(union_ty)); | ||
| 4714 | // The llvm type of the alloca will the the named LLVM union type, which will not | ||
| 4715 | // necessarily match the format that we need, depending on which tag is active. We | ||
| 4716 | // must construct the correct unnamed struct type here and bitcast, in order to | ||
| 4717 | // then set the fields appropriately. | ||
| 4718 | const result_ptr = self.buildAlloca(union_llvm_ty); | ||
| 4719 | const llvm_payload = try self.resolveInst(extra.init); | ||
| 4720 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | ||
| 4721 | assert(union_obj.haveFieldTypes()); | ||
| 4722 | const field = union_obj.fields.values()[extra.field_index]; | ||
| 4723 | const field_llvm_ty = try self.dg.llvmType(field.ty); | ||
| 4724 | const tag_llvm_ty = try self.dg.llvmType(union_obj.tag_ty); | ||
| 4725 | const field_size = field.ty.abiSize(target); | ||
| 4726 | const field_align = field.normalAlignment(target); | ||
| 4727 | |||
| 4728 | const llvm_union_ty = t: { | ||
| 4729 | const payload = p: { | ||
| 4730 | if (!field.ty.hasRuntimeBits()) { | ||
| 4731 | const padding_len = @intCast(c_uint, layout.payload_size); | ||
| 4732 | break :p self.context.intType(8).arrayType(padding_len); | ||
| 4733 | } | ||
| 4734 | if (field_size == layout.payload_size) { | ||
| 4735 | break :p field_llvm_ty; | ||
| 4736 | } | ||
| 4737 | const padding_len = @intCast(c_uint, layout.payload_size - field_size); | ||
| 4738 | const fields: [2]*const llvm.Type = .{ | ||
| 4739 | field_llvm_ty, self.context.intType(8).arrayType(padding_len), | ||
| 4740 | }; | ||
| 4741 | break :p self.context.structType(&fields, fields.len, .False); | ||
| 4742 | }; | ||
| 4743 | if (layout.tag_size == 0) { | ||
| 4744 | const fields: [1]*const llvm.Type = .{payload}; | ||
| 4745 | break :t self.context.structType(&fields, fields.len, .False); | ||
| 4746 | } | ||
| 4747 | var fields: [2]*const llvm.Type = undefined; | ||
| 4748 | if (layout.tag_align >= layout.payload_align) { | ||
| 4749 | fields = .{ tag_llvm_ty, payload }; | ||
| 4750 | } else { | ||
| 4751 | fields = .{ payload, tag_llvm_ty }; | ||
| 4752 | } | ||
| 4753 | break :t self.context.structType(&fields, fields.len, .False); | ||
| 4754 | }; | ||
| 4755 | |||
| 4756 | const casted_ptr = self.builder.buildBitCast(result_ptr, llvm_union_ty.pointerType(0), ""); | ||
| 4757 | |||
| 4758 | // Now we follow the layout as expressed above with GEP instructions to set the | ||
| 4759 | // tag and the payload. | ||
| 4760 | const index_type = self.context.intType(32); | ||
| 4761 | |||
| 4762 | if (layout.tag_size == 0) { | ||
| 4763 | const indices: [3]*const llvm.Value = .{ | ||
| 4764 | index_type.constNull(), | ||
| 4765 | index_type.constNull(), | ||
| 4766 | index_type.constNull(), | ||
| 4767 | }; | ||
| 4768 | const len: c_uint = if (field_size == layout.payload_size) 2 else 3; | ||
| 4769 | const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); | ||
| 4770 | const store_inst = self.builder.buildStore(llvm_payload, field_ptr); | ||
| 4771 | store_inst.setAlignment(field_align); | ||
| 4772 | return result_ptr; | ||
| 4773 | } | ||
| 4774 | |||
| 4775 | { | ||
| 4776 | const indices: [3]*const llvm.Value = .{ | ||
| 4777 | index_type.constNull(), | ||
| 4778 | index_type.constInt(@boolToInt(layout.tag_align >= layout.payload_align), .False), | ||
| 4779 | index_type.constNull(), | ||
| 4780 | }; | ||
| 4781 | const len: c_uint = if (field_size == layout.payload_size) 2 else 3; | ||
| 4782 | const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); | ||
| 4783 | const store_inst = self.builder.buildStore(llvm_payload, field_ptr); | ||
| 4784 | store_inst.setAlignment(field_align); | ||
| 4785 | } | ||
| 4786 | { | ||
| 4787 | const indices: [2]*const llvm.Value = .{ | ||
| 4788 | index_type.constNull(), | ||
| 4789 | index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False), | ||
| 4790 | }; | ||
| 4791 | const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, ""); | ||
| 4792 | const llvm_tag = union_llvm_ty.constInt(extra.field_index, .False); | ||
| 4793 | const store_inst = self.builder.buildStore(llvm_tag, field_ptr); | ||
| 4794 | store_inst.setAlignment(union_obj.tag_ty.abiAlignment(target)); | ||
| 4795 | } | ||
| 4796 | |||
| 4797 | return result_ptr; | ||
| 4798 | } | ||
| 4799 | |||
| 4696 | fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 4800 | fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 4697 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; | 4801 | const prefetch = self.air.instructions.items(.data)[inst].prefetch; |
| 4698 | 4802 |
src/print_air.zig+11-2| ... | @@ -232,7 +232,8 @@ const Writer = struct { | ... | @@ -232,7 +232,8 @@ const Writer = struct { |
| 232 | .assembly => try w.writeAssembly(s, inst), | 232 | .assembly => try w.writeAssembly(s, inst), |
| 233 | .dbg_stmt => try w.writeDbgStmt(s, inst), | 233 | .dbg_stmt => try w.writeDbgStmt(s, inst), |
| 234 | .call => try w.writeCall(s, inst), | 234 | .call => try w.writeCall(s, inst), |
| 235 | .vector_init => try w.writeVectorInit(s, inst), | 235 | .aggregate_init => try w.writeAggregateInit(s, inst), |
| 236 | .union_init => try w.writeUnionInit(s, inst), | ||
| 236 | .br => try w.writeBr(s, inst), | 237 | .br => try w.writeBr(s, inst), |
| 237 | .cond_br => try w.writeCondBr(s, inst), | 238 | .cond_br => try w.writeCondBr(s, inst), |
| 238 | .switch_br => try w.writeSwitchBr(s, inst), | 239 | .switch_br => try w.writeSwitchBr(s, inst), |
| ... | @@ -301,7 +302,7 @@ const Writer = struct { | ... | @@ -301,7 +302,7 @@ const Writer = struct { |
| 301 | try s.writeAll("}"); | 302 | try s.writeAll("}"); |
| 302 | } | 303 | } |
| 303 | 304 | ||
| 304 | fn writeVectorInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 305 | fn writeAggregateInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 305 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; | 306 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; |
| 306 | const vector_ty = w.air.getRefType(ty_pl.ty); | 307 | const vector_ty = w.air.getRefType(ty_pl.ty); |
| 307 | const len = @intCast(usize, vector_ty.arrayLen()); | 308 | const len = @intCast(usize, vector_ty.arrayLen()); |
| ... | @@ -315,6 +316,14 @@ const Writer = struct { | ... | @@ -315,6 +316,14 @@ const Writer = struct { |
| 315 | try s.writeAll("]"); | 316 | try s.writeAll("]"); |
| 316 | } | 317 | } |
| 317 | 318 | ||
| 319 | fn writeUnionInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 320 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; | ||
| 321 | const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data; | ||
| 322 | |||
| 323 | try s.print("{d}, ", .{extra.field_index}); | ||
| 324 | try w.writeOperand(s, inst, 0, extra.init); | ||
| 325 | } | ||
| 326 | |||
| 318 | fn writeStructField(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 327 | fn writeStructField(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 319 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; | 328 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; |
| 320 | const extra = w.air.extraData(Air.StructField, ty_pl.payload).data; | 329 | const extra = w.air.extraData(Air.StructField, ty_pl.payload).data; |
src/print_zir.zig+5-5| ... | @@ -273,7 +273,7 @@ const Writer = struct { | ... | @@ -273,7 +273,7 @@ const Writer = struct { |
| 273 | .slice_end => try self.writeSliceEnd(stream, inst), | 273 | .slice_end => try self.writeSliceEnd(stream, inst), |
| 274 | .slice_sentinel => try self.writeSliceSentinel(stream, inst), | 274 | .slice_sentinel => try self.writeSliceSentinel(stream, inst), |
| 275 | 275 | ||
| 276 | .union_init_ptr => try self.writeUnionInitPtr(stream, inst), | 276 | .union_init => try self.writeUnionInit(stream, inst), |
| 277 | 277 | ||
| 278 | .struct_init, | 278 | .struct_init, |
| 279 | .struct_init_ref, | 279 | .struct_init_ref, |
| ... | @@ -692,14 +692,14 @@ const Writer = struct { | ... | @@ -692,14 +692,14 @@ const Writer = struct { |
| 692 | try self.writeSrc(stream, inst_data.src()); | 692 | try self.writeSrc(stream, inst_data.src()); |
| 693 | } | 693 | } |
| 694 | 694 | ||
| 695 | fn writeUnionInitPtr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | 695 | fn writeUnionInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { |
| 696 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | 696 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 697 | const extra = self.code.extraData(Zir.Inst.UnionInitPtr, inst_data.payload_index).data; | 697 | const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data; |
| 698 | try self.writeInstRef(stream, extra.result_ptr); | ||
| 699 | try stream.writeAll(", "); | ||
| 700 | try self.writeInstRef(stream, extra.union_type); | 698 | try self.writeInstRef(stream, extra.union_type); |
| 701 | try stream.writeAll(", "); | 699 | try stream.writeAll(", "); |
| 702 | try self.writeInstRef(stream, extra.field_name); | 700 | try self.writeInstRef(stream, extra.field_name); |
| 701 | try stream.writeAll(", "); | ||
| 702 | try self.writeInstRef(stream, extra.init); | ||
| 703 | try stream.writeAll(") "); | 703 | try stream.writeAll(") "); |
| 704 | try self.writeSrc(stream, inst_data.src()); | 704 | try self.writeSrc(stream, inst_data.src()); |
| 705 | } | 705 | } |
test/behavior/union.zig+39-3| ... | @@ -785,8 +785,40 @@ test "return union init with void payload" { | ... | @@ -785,8 +785,40 @@ test "return union init with void payload" { |
| 785 | comptime try S.entry(); | 785 | comptime try S.entry(); |
| 786 | } | 786 | } |
| 787 | 787 | ||
| 788 | test "@unionInit stored to a const" { | ||
| 789 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 790 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 791 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 792 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 793 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 794 | |||
| 795 | const S = struct { | ||
| 796 | const U = union(enum) { | ||
| 797 | boolean: bool, | ||
| 798 | byte: u8, | ||
| 799 | }; | ||
| 800 | fn doTheTest() !void { | ||
| 801 | { | ||
| 802 | var t = true; | ||
| 803 | const u = @unionInit(U, "boolean", t); | ||
| 804 | try expect(u.boolean); | ||
| 805 | } | ||
| 806 | { | ||
| 807 | var byte: u8 = 69; | ||
| 808 | const u = @unionInit(U, "byte", byte); | ||
| 809 | try expect(u.byte == 69); | ||
| 810 | } | ||
| 811 | } | ||
| 812 | }; | ||
| 813 | |||
| 814 | comptime try S.doTheTest(); | ||
| 815 | try S.doTheTest(); | ||
| 816 | } | ||
| 817 | |||
| 788 | test "@unionInit can modify a union type" { | 818 | test "@unionInit can modify a union type" { |
| 789 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 819 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 820 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 821 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 790 | 822 | ||
| 791 | const UnionInitEnum = union(enum) { | 823 | const UnionInitEnum = union(enum) { |
| 792 | Boolean: bool, | 824 | Boolean: bool, |
| ... | @@ -807,7 +839,9 @@ test "@unionInit can modify a union type" { | ... | @@ -807,7 +839,9 @@ test "@unionInit can modify a union type" { |
| 807 | } | 839 | } |
| 808 | 840 | ||
| 809 | test "@unionInit can modify a pointer value" { | 841 | test "@unionInit can modify a pointer value" { |
| 810 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 842 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 843 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 844 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 811 | 845 | ||
| 812 | const UnionInitEnum = union(enum) { | 846 | const UnionInitEnum = union(enum) { |
| 813 | Boolean: bool, | 847 | Boolean: bool, |
| ... | @@ -825,7 +859,9 @@ test "@unionInit can modify a pointer value" { | ... | @@ -825,7 +859,9 @@ test "@unionInit can modify a pointer value" { |
| 825 | } | 859 | } |
| 826 | 860 | ||
| 827 | test "union no tag with struct member" { | 861 | test "union no tag with struct member" { |
| 828 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 862 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 863 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 864 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 829 | 865 | ||
| 830 | const Struct = struct {}; | 866 | const Struct = struct {}; |
| 831 | const Union = union { | 867 | const Union = union { |