authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-12-01 23:26:02+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-04-09 01:51:51+02:00
log34b98ee372f8974e21cd34b3ca7588b13d93e31a
treeefd4176707e500d7521fd90a9515ba24ee6e84c7
parentf1229e0f00114e38001df8b57725de9c3e13a06d
signaturelock-open Commit is signed but in an unrecognized format.

spirv: start lowering non-function decls

Start to lower decls which are not functions. These generate an OpVariable instruction by which they can be used later on.

2 files changed, 57 insertions(+), 46 deletions(-)

src/codegen/spirv.zig+53-42
...@@ -225,7 +225,21 @@ pub const DeclGen = struct {...@@ -225,7 +225,21 @@ pub const DeclGen = struct {
225 /// Fetch the result-id for a previously generated instruction or constant.225 /// Fetch the result-id for a previously generated instruction or constant.
226 fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef {226 fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef {
227 if (self.air.value(inst)) |val| {227 if (self.air.value(inst)) |val| {
228 return self.genConstant(self.air.typeOf(inst), val, .direct);228 const ty = self.air.typeOf(inst);
229 if (ty.zigTypeTag() == .Fn) {
230 const fn_decl_index = switch (val.tag()) {
231 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
232 .function => val.castTag(.function).?.data.owner_decl,
233 else => unreachable,
234 };
235 const decl = self.module.declPtr(fn_decl_index);
236 self.module.markDeclAlive(decl);
237 return self.ids.get(fn_decl_index).?;
238 }
239
240 const result_id = self.spv.allocId();
241 try self.genConstant(result_id, ty, val, .direct);
242 return result_id;
229 }243 }
230 const index = Air.refToIndex(inst).?;244 const index = Air.refToIndex(inst).?;
231 return self.inst_results.get(index).?; // Assertion means instruction does not dominate usage.245 return self.inst_results.get(index).?; // Assertion means instruction does not dominate usage.
...@@ -339,7 +353,7 @@ pub const DeclGen = struct {...@@ -339,7 +353,7 @@ pub const DeclGen = struct {
339 };353 };
340 }354 }
341355
342 fn constInt(self: *DeclGen, ty_ref: SpvType.Ref, value: anytype) !IdRef {356 fn genConstInt(self: *DeclGen, ty_ref: SpvType.Ref, result_id: IdRef, value: anytype) !void {
343 const ty = self.spv.typeRefType(ty_ref);357 const ty = self.spv.typeRefType(ty_ref);
344 const ty_id = self.typeId(ty_ref);358 const ty_id = self.typeId(ty_ref);
345359
...@@ -356,51 +370,44 @@ pub const DeclGen = struct {...@@ -356,51 +370,44 @@ pub const DeclGen = struct {
356 },370 },
357 };371 };
358372
359 return try self.spv.emitConstant(ty_id, literal);373 try self.spv.emitConstant(ty_id, result_id, literal);
374 }
375
376 fn constInt(self: *DeclGen, ty_ref: SpvType.Ref, value: anytype) !IdRef {
377 const result_id = self.spv.allocId();
378 try self.genConstInt(ty_ref, result_id, value);
379 return result_id;
360 }380 }
361381
362 /// Generate a constant representing `val`.382 /// Generate a constant representing `val`.
363 /// TODO: Deduplication?383 /// TODO: Deduplication?
364 fn genConstant(self: *DeclGen, ty: Type, val: Value, repr: Repr) Error!IdRef {384 fn genConstant(self: *DeclGen, result_id: IdRef, ty: Type, val: Value, repr: Repr) Error!void {
365 if (ty.zigTypeTag() == .Fn) {
366 const fn_decl_index = switch (val.tag()) {
367 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
368 .function => val.castTag(.function).?.data.owner_decl,
369 else => unreachable,
370 };
371 const decl = self.module.declPtr(fn_decl_index);
372 self.module.markDeclAlive(decl);
373 return self.ids.get(fn_decl_index).?;
374 }
375
376 const target = self.getTarget();385 const target = self.getTarget();
377 const section = &self.spv.sections.types_globals_constants;386 const section = &self.spv.sections.types_globals_constants;
378 const result_ty_ref = try self.resolveType(ty, repr);387 const result_ty_ref = try self.resolveType(ty, repr);
379 const result_ty_id = self.typeId(result_ty_ref);388 const result_ty_id = self.typeId(result_ty_ref);
380389
390 log.debug("genConstant: ty = {}, val = {}", .{ ty.fmtDebug(), val.fmtDebug() });
391
381 if (val.isUndef()) {392 if (val.isUndef()) {
382 const result_id = self.spv.allocId();
383 try section.emit(self.spv.gpa, .OpUndef, .{ .id_result_type = result_ty_id, .id_result = result_id });393 try section.emit(self.spv.gpa, .OpUndef, .{ .id_result_type = result_ty_id, .id_result = result_id });
384 return result_id;
385 }394 }
386395
387 switch (ty.zigTypeTag()) {396 switch (ty.zigTypeTag()) {
388 .Int => {397 .Int => {
389 const int_bits = if (ty.isSignedInt()) @bitCast(u64, val.toSignedInt(target)) else val.toUnsignedInt(target);398 const int_bits = if (ty.isSignedInt()) @bitCast(u64, val.toSignedInt(target)) else val.toUnsignedInt(target);
390 return self.constInt(result_ty_ref, int_bits);399 try self.genConstInt(result_ty_ref, result_id, int_bits);
391 },400 },
392 .Bool => switch (repr) {401 .Bool => switch (repr) {
393 .direct => {402 .direct => {
394 const result_id = self.spv.allocId();
395 const operands = .{ .id_result_type = result_ty_id, .id_result = result_id };403 const operands = .{ .id_result_type = result_ty_id, .id_result = result_id };
396 if (val.toBool()) {404 if (val.toBool()) {
397 try section.emit(self.spv.gpa, .OpConstantTrue, operands);405 try section.emit(self.spv.gpa, .OpConstantTrue, operands);
398 } else {406 } else {
399 try section.emit(self.spv.gpa, .OpConstantFalse, operands);407 try section.emit(self.spv.gpa, .OpConstantFalse, operands);
400 }408 }
401 return result_id;
402 },409 },
403 .indirect => return try self.constInt(result_ty_ref, @boolToInt(val.toBool())),410 .indirect => try self.genConstInt(result_ty_ref, result_id, @boolToInt(val.toBool())),
404 },411 },
405 .Float => {412 .Float => {
406 // At this point we are guaranteed that the target floating point type is supported, otherwise the function413 // At this point we are guaranteed that the target floating point type is supported, otherwise the function
...@@ -415,7 +422,7 @@ pub const DeclGen = struct {...@@ -415,7 +422,7 @@ pub const DeclGen = struct {
415 else => unreachable,422 else => unreachable,
416 };423 };
417424
418 return try self.spv.emitConstant(result_ty_id, literal);425 try self.spv.emitConstant(result_ty_id, result_id, literal);
419 },426 },
420 .Array => switch (val.tag()) {427 .Array => switch (val.tag()) {
421 .aggregate => { // todo: combine with Vector428 .aggregate => { // todo: combine with Vector
...@@ -425,15 +432,14 @@ pub const DeclGen = struct {...@@ -425,15 +432,14 @@ pub const DeclGen = struct {
425 const constituents = try self.spv.gpa.alloc(IdRef, len);432 const constituents = try self.spv.gpa.alloc(IdRef, len);
426 defer self.spv.gpa.free(constituents);433 defer self.spv.gpa.free(constituents);
427 for (elem_vals[0..len], 0..) |elem_val, i| {434 for (elem_vals[0..len], 0..) |elem_val, i| {
428 constituents[i] = try self.genConstant(elem_ty, elem_val, repr);435 constituents[i] = self.spv.allocId();
436 try self.genConstant(constituents[i], elem_ty, elem_val, repr);
429 }437 }
430 const result_id = self.spv.allocId();
431 try section.emit(self.spv.gpa, .OpConstantComposite, .{438 try section.emit(self.spv.gpa, .OpConstantComposite, .{
432 .id_result_type = result_ty_id,439 .id_result_type = result_ty_id,
433 .id_result = result_id,440 .id_result = result_id,
434 .constituents = constituents,441 .constituents = constituents,
435 });442 });
436 return result_id;
437 },443 },
438 .repeated => {444 .repeated => {
439 const elem_val = val.castTag(.repeated).?.data;445 const elem_val = val.castTag(.repeated).?.data;
...@@ -442,20 +448,20 @@ pub const DeclGen = struct {...@@ -442,20 +448,20 @@ pub const DeclGen = struct {
442 const constituents = try self.spv.gpa.alloc(IdRef, len);448 const constituents = try self.spv.gpa.alloc(IdRef, len);
443 defer self.spv.gpa.free(constituents);449 defer self.spv.gpa.free(constituents);
444450
445 const elem_val_id = try self.genConstant(elem_ty, elem_val, repr);451 const elem_val_id = self.spv.allocId();
452 try self.genConstant(elem_val_id, elem_ty, elem_val, repr);
446 for (constituents[0..len]) |*elem| {453 for (constituents[0..len]) |*elem| {
447 elem.* = elem_val_id;454 elem.* = elem_val_id;
448 }455 }
449 if (ty.sentinel()) |sentinel| {456 if (ty.sentinel()) |sentinel| {
450 constituents[len] = try self.genConstant(elem_ty, sentinel, repr);457 constituents[len] = self.spv.allocId();
458 try self.genConstant(constituents[len], elem_ty, sentinel, repr);
451 }459 }
452 const result_id = self.spv.allocId();
453 try section.emit(self.spv.gpa, .OpConstantComposite, .{460 try section.emit(self.spv.gpa, .OpConstantComposite, .{
454 .id_result_type = result_ty_id,461 .id_result_type = result_ty_id,
455 .id_result = result_id,462 .id_result = result_id,
456 .constituents = constituents,463 .constituents = constituents,
457 });464 });
458 return result_id;
459 },465 },
460 else => return self.todo("array constant with tag {s}", .{@tagName(val.tag())}),466 else => return self.todo("array constant with tag {s}", .{@tagName(val.tag())}),
461 },467 },
...@@ -468,22 +474,21 @@ pub const DeclGen = struct {...@@ -468,22 +474,21 @@ pub const DeclGen = struct {
468 const elem_refs = try self.gpa.alloc(IdRef, vector_len);474 const elem_refs = try self.gpa.alloc(IdRef, vector_len);
469 defer self.gpa.free(elem_refs);475 defer self.gpa.free(elem_refs);
470 for (elem_refs, 0..) |*elem, i| {476 for (elem_refs, 0..) |*elem, i| {
471 elem.* = try self.genConstant(elem_ty, elem_vals[i], repr);477 elem.* = self.spv.allocId();
478 try self.genConstant(elem.*, elem_ty, elem_vals[i], repr);
472 }479 }
473 const result_id = self.spv.allocId();
474 try section.emit(self.spv.gpa, .OpConstantComposite, .{480 try section.emit(self.spv.gpa, .OpConstantComposite, .{
475 .id_result_type = result_ty_id,481 .id_result_type = result_ty_id,
476 .id_result = result_id,482 .id_result = result_id,
477 .constituents = elem_refs,483 .constituents = elem_refs,
478 });484 });
479 return result_id;
480 },485 },
481 else => return self.todo("vector constant with tag {s}", .{@tagName(val.tag())}),486 else => return self.todo("vector constant with tag {s}", .{@tagName(val.tag())}),
482 },487 },
483 .Enum => {488 .Enum => {
484 var int_buffer: Value.Payload.U64 = undefined;489 var int_buffer: Value.Payload.U64 = undefined;
485 const int_val = val.enumToInt(ty, &int_buffer).toUnsignedInt(target); // TODO: composite integer constants490 const int_val = val.enumToInt(ty, &int_buffer).toUnsignedInt(target); // TODO: composite integer constants
486 return self.constInt(result_ty_ref, int_val);491 return self.genConstInt(result_ty_ref, result_id, int_val);
487 },492 },
488 .Struct => {493 .Struct => {
489 const constituents = if (ty.isSimpleTupleOrAnonStruct()) blk: {494 const constituents = if (ty.isSimpleTupleOrAnonStruct()) blk: {
...@@ -495,7 +500,9 @@ pub const DeclGen = struct {...@@ -495,7 +500,9 @@ pub const DeclGen = struct {
495 for (tuple.types, 0..) |field_ty, i| {500 for (tuple.types, 0..) |field_ty, i| {
496 const field_val = tuple.values[i];501 const field_val = tuple.values[i];
497 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;502 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
498 constituents[member_index] = try self.genConstant(field_ty, field_val, repr);503 const member_id = self.spv.allocId();
504 try self.genConstant(member_id, field_ty, field_val, repr);
505 constituents[member_index] = member_id;
499 member_index += 1;506 member_index += 1;
500 }507 }
501508
...@@ -513,7 +520,9 @@ pub const DeclGen = struct {...@@ -513,7 +520,9 @@ pub const DeclGen = struct {
513 var member_index: usize = 0;520 var member_index: usize = 0;
514 for (struct_ty.fields.values(), 0..) |field, i| {521 for (struct_ty.fields.values(), 0..) |field, i| {
515 if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;522 if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;
516 constituents[member_index] = try self.genConstant(field.ty, field_vals[i], repr);523 const member_id = self.spv.allocId();
524 try self.genConstant(member_id, field.ty, field_vals[i], repr);
525 constituents[member_index] = member_id;
517 member_index += 1;526 member_index += 1;
518 }527 }
519528
...@@ -521,16 +530,17 @@ pub const DeclGen = struct {...@@ -521,16 +530,17 @@ pub const DeclGen = struct {
521 };530 };
522 defer self.spv.gpa.free(constituents);531 defer self.spv.gpa.free(constituents);
523532
524 const result_id = self.spv.allocId();
525 try section.emit(self.spv.gpa, .OpConstantComposite, .{533 try section.emit(self.spv.gpa, .OpConstantComposite, .{
526 .id_result_type = result_ty_id,534 .id_result_type = result_ty_id,
527 .id_result = result_id,535 .id_result = result_id,
528 .constituents = constituents,536 .constituents = constituents,
529 });537 });
530 return result_id;538 },
539 .Fn => switch (repr) {
540 .direct => unreachable,
541 .indirect => return self.todo("function pointers", .{}),
531 },542 },
532 .Void => unreachable,543 .Void => unreachable,
533 .Fn => unreachable,
534 else => return self.todo("constant generation of type {s}: {}", .{ @tagName(ty.zigTypeTag()), ty.fmtDebug() }),544 else => return self.todo("constant generation of type {s}: {}", .{ @tagName(ty.zigTypeTag()), ty.fmtDebug() }),
535 }545 }
536 }546 }
...@@ -579,6 +589,7 @@ pub const DeclGen = struct {...@@ -579,6 +589,7 @@ pub const DeclGen = struct {
579589
580 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.590 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.
581 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!SpvType.Ref {591 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!SpvType.Ref {
592 log.debug("resolveType: ty = {}", .{ty.fmtDebug()});
582 const target = self.getTarget();593 const target = self.getTarget();
583 switch (ty.zigTypeTag()) {594 switch (ty.zigTypeTag()) {
584 .Void, .NoReturn => return try self.spv.resolveType(SpvType.initTag(.void)),595 .Void, .NoReturn => return try self.spv.resolveType(SpvType.initTag(.void)),
...@@ -808,8 +819,7 @@ pub const DeclGen = struct {...@@ -808,8 +819,7 @@ pub const DeclGen = struct {
808 .name = fqn,819 .name = fqn,
809 });820 });
810 } else {821 } else {
811 // TODO822 try self.genConstant(result_id, decl.ty, decl.val, .direct);
812 // return self.todo("generate decl type {}", .{decl.ty.zigTypeTag()});
813 }823 }
814 }824 }
815825
...@@ -1417,7 +1427,8 @@ pub const DeclGen = struct {...@@ -1417,7 +1427,8 @@ pub const DeclGen = struct {
1417 .Packed => unreachable, // TODO1427 .Packed => unreachable, // TODO
1418 else => {1428 else => {
1419 const u32_ty_id = self.typeId(try self.intType(.unsigned, 32));1429 const u32_ty_id = self.typeId(try self.intType(.unsigned, 32));
1420 const field_index_id = try self.spv.emitConstant(u32_ty_id, .{ .uint32 = field_index });1430 const field_index_id = self.spv.allocId();
1431 try self.spv.emitConstant(u32_ty_id, field_index_id, .{ .uint32 = field_index });
1421 const result_id = self.spv.allocId();1432 const result_id = self.spv.allocId();
1422 const result_type_id = try self.resolveTypeId(result_ptr_ty);1433 const result_type_id = try self.resolveTypeId(result_ptr_ty);
1423 const indexes = [_]IdRef{field_index_id};1434 const indexes = [_]IdRef{field_index_id};
...@@ -1960,7 +1971,7 @@ pub const DeclGen = struct {...@@ -1960,7 +1971,7 @@ pub const DeclGen = struct {
1960 return null;1971 return null;
1961 }1972 }
19621973
1963 fn airCall(self: *DeclGen, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.Modifier) !?IdRef {1974 fn airCall(self: *DeclGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !?IdRef {
1964 _ = modifier;1975 _ = modifier;
19651976
1966 const pl_op = self.air.instructions.items(.data)[inst].pl_op;1977 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
src/codegen/spirv/Module.zig+4-4
...@@ -353,7 +353,8 @@ pub fn emitType(self: *Module, ty: Type) error{OutOfMemory}!IdResultType {...@@ -353,7 +353,8 @@ pub fn emitType(self: *Module, ty: Type) error{OutOfMemory}!IdResultType {
353353
354 const size_type = Type.initTag(.u32);354 const size_type = Type.initTag(.u32);
355 const size_type_id = try self.resolveTypeId(size_type);355 const size_type_id = try self.resolveTypeId(size_type);
356 const length_id = try self.emitConstant(size_type_id, .{ .uint32 = info.length });356 const length_id = self.allocId();
357 try self.emitConstant(size_type_id, length_id, .{ .uint32 = info.length });
357358
358 try types.emit(self.gpa, .OpTypeArray, .{359 try types.emit(self.gpa, .OpTypeArray, .{
359 .id_result = result_id,360 .id_result = result_id,
...@@ -558,15 +559,14 @@ fn decorateStruct(self: *Module, target: IdRef, info: *const Type.Payload.Struct...@@ -558,15 +559,14 @@ fn decorateStruct(self: *Module, target: IdRef, info: *const Type.Payload.Struct
558pub fn emitConstant(559pub fn emitConstant(
559 self: *Module,560 self: *Module,
560 ty_id: spec.IdRef,561 ty_id: spec.IdRef,
562 result_id: IdRef,
561 value: spec.LiteralContextDependentNumber,563 value: spec.LiteralContextDependentNumber,
562) !IdRef {564) !void {
563 const result_id = self.allocId();
564 try self.sections.types_globals_constants.emit(self.gpa, .OpConstant, .{565 try self.sections.types_globals_constants.emit(self.gpa, .OpConstant, .{
565 .id_result_type = ty_id,566 .id_result_type = ty_id,
566 .id_result = result_id,567 .id_result = result_id,
567 .value = value,568 .value = value,
568 });569 });
569 return result_id;
570}570}
571571
572/// Decorate a result-id.572/// Decorate a result-id.