| ... | @@ -450,6 +450,42 @@ pub const DeclGen = struct { | ... | @@ -450,6 +450,42 @@ pub const DeclGen = struct { |
| 450 | return result_id; | 450 | return result_id; |
| 451 | } | 451 | } |
| 452 | | 452 | |
| | 453 | fn constructDeclRef(self: *DeclGen, ty: Type, decl_index: Decl.Index) !IdRef { |
| | 454 | const mod = self.module; |
| | 455 | const ty_ref = try self.resolveType(ty, .direct); |
| | 456 | const ty_id = self.typeId(ty_ref); |
| | 457 | const decl = mod.declPtr(decl_index); |
| | 458 | const spv_decl_index = try self.resolveDecl(decl_index); |
| | 459 | switch (mod.intern_pool.indexToKey(decl.val.ip_index)) { |
| | 460 | .func => { |
| | 461 | // TODO: Properly lower function pointers. For now we are going to hack around it and |
| | 462 | // just generate an empty pointer. Function pointers are represented by usize for now, |
| | 463 | // though. |
| | 464 | // TODO: Add dependency |
| | 465 | return try self.spv.constInt(ty_ref, 0); |
| | 466 | }, |
| | 467 | .extern_func => unreachable, // TODO |
| | 468 | else => { |
| | 469 | const decl_id = self.spv.declPtr(spv_decl_index).result_id; |
| | 470 | try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); |
| | 471 | |
| | 472 | switch (decl.@"addrspace") { |
| | 473 | .generic => { |
| | 474 | // Pointer should be generic, but is actually placed in CrossWorkgroup. |
| | 475 | const result_id = self.spv.allocId(); |
| | 476 | try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ |
| | 477 | .id_result_type = ty_id, |
| | 478 | .id_result = result_id, |
| | 479 | .pointer = decl_id, |
| | 480 | }); |
| | 481 | return result_id; |
| | 482 | }, |
| | 483 | else => return decl_id, // Variable is already correct, probably. Maybe needs a bitcast? |
| | 484 | } |
| | 485 | }, |
| | 486 | } |
| | 487 | } |
| | 488 | |
| 453 | const IndirectConstantLowering = struct { | 489 | const IndirectConstantLowering = struct { |
| 454 | const undef = 0xAA; | 490 | const undef = 0xAA; |
| 455 | | 491 | |
| ... | @@ -1151,6 +1187,42 @@ pub const DeclGen = struct { | ... | @@ -1151,6 +1187,42 @@ pub const DeclGen = struct { |
| 1151 | const int_ty = ty.intTagType(mod); | 1187 | const int_ty = ty.intTagType(mod); |
| 1152 | return try self.constant(int_ty, int_val, repr); | 1188 | return try self.constant(int_ty, int_val, repr); |
| 1153 | }, | 1189 | }, |
| | 1190 | .ptr => |ptr| { |
| | 1191 | const ptr_ty = switch (ptr.len) { |
| | 1192 | .none => ty, |
| | 1193 | else => ty.slicePtrFieldType(mod), |
| | 1194 | }; |
| | 1195 | const ptr_id = switch (ptr.addr) { |
| | 1196 | .decl => |decl| try self.constructDeclRef(ptr_ty, decl), |
| | 1197 | .mut_decl => |mut_decl| try self.constructDeclRef(ptr_ty, mut_decl.decl), // TODO |
| | 1198 | .int => |int| blk: { |
| | 1199 | const ptr_id = self.spv.allocId(); |
| | 1200 | // TODO: This can probably be an OpSpecConstantOp Bitcast, but |
| | 1201 | // that is not implemented by Mesa yet. Therefore, just generate it |
| | 1202 | // as a runtime operation. |
| | 1203 | try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ |
| | 1204 | .id_result_type = try self.resolveTypeId(ptr_ty), |
| | 1205 | .id_result = ptr_id, |
| | 1206 | .integer_value = try self.constant(Type.usize, int.toValue(), .direct), |
| | 1207 | }); |
| | 1208 | break :blk ptr_id; |
| | 1209 | }, |
| | 1210 | .comptime_field => unreachable, |
| | 1211 | else => |tag| return self.todo("pointer value of type {s}", .{@tagName(tag)}), |
| | 1212 | }; |
| | 1213 | if (ptr.len == .none) { |
| | 1214 | return ptr_id; |
| | 1215 | } |
| | 1216 | |
| | 1217 | const len_id = try self.constant(Type.usize, ptr.len.toValue(), .indirect); |
| | 1218 | const result_id = self.spv.allocId(); |
| | 1219 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ |
| | 1220 | .id_result_type = self.typeId(result_ty_ref), |
| | 1221 | .id_result = result_id, |
| | 1222 | .constituents = &.{ ptr_id, len_id }, |
| | 1223 | }); |
| | 1224 | return result_id; |
| | 1225 | }, |
| 1154 | // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra | 1226 | // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra |
| 1155 | // OpVariable that is not really required. | 1227 | // OpVariable that is not really required. |
| 1156 | else => { | 1228 | else => { |