| ... | @@ -93,6 +93,14 @@ pub const Global = struct { | ... | @@ -93,6 +93,14 @@ pub const Global = struct { |
| 93 | end_inst: u32, | 93 | end_inst: u32, |
| 94 | }; | 94 | }; |
| 95 | | 95 | |
| | 96 | /// This models a kernel entry point. |
| | 97 | pub const EntryPoint = struct { |
| | 98 | /// The declaration that should be exported. |
| | 99 | decl_index: Decl.Index, |
| | 100 | /// The name of the kernel to be exported. |
| | 101 | name: []const u8, |
| | 102 | }; |
| | 103 | |
| 96 | /// A general-purpose allocator which may be used to allocate resources for this module | 104 | /// A general-purpose allocator which may be used to allocate resources for this module |
| 97 | gpa: Allocator, | 105 | gpa: Allocator, |
| 98 | | 106 | |
| ... | @@ -107,8 +115,7 @@ sections: struct { | ... | @@ -107,8 +115,7 @@ sections: struct { |
| 107 | extensions: Section = .{}, | 115 | extensions: Section = .{}, |
| 108 | // OpExtInstImport instructions - skip for now. | 116 | // OpExtInstImport instructions - skip for now. |
| 109 | // memory model defined by target, not required here. | 117 | // memory model defined by target, not required here. |
| 110 | /// OpEntryPoint instructions. | 118 | /// OpEntryPoint instructions - Handled by `self.entry_points`. |
| 111 | entry_points: Section = .{}, | | |
| 112 | /// OpExecutionMode and OpExecutionModeId instructions. | 119 | /// OpExecutionMode and OpExecutionModeId instructions. |
| 113 | execution_modes: Section = .{}, | 120 | execution_modes: Section = .{}, |
| 114 | /// OpString, OpSourcExtension, OpSource, OpSourceContinued. | 121 | /// OpString, OpSourcExtension, OpSource, OpSourceContinued. |
| ... | @@ -143,8 +150,13 @@ type_cache: TypeCache = .{}, | ... | @@ -143,8 +150,13 @@ type_cache: TypeCache = .{}, |
| 143 | /// Set of Decls, referred to by Decl.Index. | 150 | /// Set of Decls, referred to by Decl.Index. |
| 144 | decls: std.ArrayListUnmanaged(Decl) = .{}, | 151 | decls: std.ArrayListUnmanaged(Decl) = .{}, |
| 145 | | 152 | |
| | 153 | /// List of dependencies, per decl. This list holds all the dependencies, sliced by the |
| | 154 | /// begin_dep and end_dep in `self.decls`. |
| 146 | decl_deps: std.ArrayListUnmanaged(Decl.Index) = .{}, | 155 | decl_deps: std.ArrayListUnmanaged(Decl.Index) = .{}, |
| 147 | | 156 | |
| | 157 | /// The list of entry points that should be exported from this module. |
| | 158 | entry_points: std.ArrayListUnmanaged(EntryPoint) = .{}, |
| | 159 | |
| 148 | /// The fields in this structure help to maintain the required order for global variables. | 160 | /// The fields in this structure help to maintain the required order for global variables. |
| 149 | globals: struct { | 161 | globals: struct { |
| 150 | /// Set of globals, referred to by Decl.Index. | 162 | /// Set of globals, referred to by Decl.Index. |
| ... | @@ -166,7 +178,6 @@ pub fn init(gpa: Allocator, arena: Allocator) Module { | ... | @@ -166,7 +178,6 @@ pub fn init(gpa: Allocator, arena: Allocator) Module { |
| 166 | pub fn deinit(self: *Module) void { | 178 | pub fn deinit(self: *Module) void { |
| 167 | self.sections.capabilities.deinit(self.gpa); | 179 | self.sections.capabilities.deinit(self.gpa); |
| 168 | self.sections.extensions.deinit(self.gpa); | 180 | self.sections.extensions.deinit(self.gpa); |
| 169 | self.sections.entry_points.deinit(self.gpa); | | |
| 170 | self.sections.execution_modes.deinit(self.gpa); | 181 | self.sections.execution_modes.deinit(self.gpa); |
| 171 | self.sections.debug_strings.deinit(self.gpa); | 182 | self.sections.debug_strings.deinit(self.gpa); |
| 172 | self.sections.debug_names.deinit(self.gpa); | 183 | self.sections.debug_names.deinit(self.gpa); |
| ... | @@ -180,6 +191,8 @@ pub fn deinit(self: *Module) void { | ... | @@ -180,6 +191,8 @@ pub fn deinit(self: *Module) void { |
| 180 | self.decls.deinit(self.gpa); | 191 | self.decls.deinit(self.gpa); |
| 181 | self.decl_deps.deinit(self.gpa); | 192 | self.decl_deps.deinit(self.gpa); |
| 182 | | 193 | |
| | 194 | self.entry_points.deinit(self.gpa); |
| | 195 | |
| 183 | self.globals.globals.deinit(self.gpa); | 196 | self.globals.globals.deinit(self.gpa); |
| 184 | self.globals.section.deinit(self.gpa); | 197 | self.globals.section.deinit(self.gpa); |
| 185 | | 198 | |
| ... | @@ -202,16 +215,16 @@ pub fn idBound(self: Module) Word { | ... | @@ -202,16 +215,16 @@ pub fn idBound(self: Module) Word { |
| 202 | | 215 | |
| 203 | fn orderGlobalsInto( | 216 | fn orderGlobalsInto( |
| 204 | self: *Module, | 217 | self: *Module, |
| 205 | index: Decl.Index, | 218 | decl_index: Decl.Index, |
| 206 | section: *Section, | 219 | section: *Section, |
| 207 | seen: *std.DynamicBitSetUnmanaged, | 220 | seen: *std.DynamicBitSetUnmanaged, |
| 208 | ) !void { | 221 | ) !void { |
| 209 | const decl = self.declPtr(index); | 222 | const decl = self.declPtr(decl_index); |
| 210 | const deps = self.decl_deps.items[decl.begin_dep..decl.end_dep]; | 223 | const deps = self.decl_deps.items[decl.begin_dep..decl.end_dep]; |
| 211 | const global = self.globalPtr(index).?; | 224 | const global = self.globalPtr(decl_index).?; |
| 212 | const insts = self.globals.section.instructions.items[global.begin_inst..global.end_inst]; | 225 | const insts = self.globals.section.instructions.items[global.begin_inst..global.end_inst]; |
| 213 | | 226 | |
| 214 | seen.set(@enumToInt(index)); | 227 | seen.set(@enumToInt(decl_index)); |
| 215 | | 228 | |
| 216 | for (deps) |dep| { | 229 | for (deps) |dep| { |
| 217 | if (!seen.isSet(@enumToInt(dep))) { | 230 | if (!seen.isSet(@enumToInt(dep))) { |
| ... | @@ -229,6 +242,8 @@ fn orderGlobals(self: *Module) !Section { | ... | @@ -229,6 +242,8 @@ fn orderGlobals(self: *Module) !Section { |
| 229 | defer seen.deinit(self.gpa); | 242 | defer seen.deinit(self.gpa); |
| 230 | | 243 | |
| 231 | var ordered_globals = Section{}; | 244 | var ordered_globals = Section{}; |
| | 245 | errdefer ordered_globals.deinit(self.gpa); |
| | 246 | |
| 232 | for (globals) |decl_index| { | 247 | for (globals) |decl_index| { |
| 233 | if (!seen.isSet(@enumToInt(decl_index))) { | 248 | if (!seen.isSet(@enumToInt(decl_index))) { |
| 234 | try self.orderGlobalsInto(decl_index, &ordered_globals, &seen); | 249 | try self.orderGlobalsInto(decl_index, &ordered_globals, &seen); |
| ... | @@ -238,6 +253,56 @@ fn orderGlobals(self: *Module) !Section { | ... | @@ -238,6 +253,56 @@ fn orderGlobals(self: *Module) !Section { |
| 238 | return ordered_globals; | 253 | return ordered_globals; |
| 239 | } | 254 | } |
| 240 | | 255 | |
| | 256 | fn addEntryPointDeps( |
| | 257 | self: *Module, |
| | 258 | decl_index: Decl.Index, |
| | 259 | seen: *std.DynamicBitSetUnmanaged, |
| | 260 | interface: *std.ArrayList(IdRef), |
| | 261 | ) !void { |
| | 262 | const decl = self.declPtr(decl_index); |
| | 263 | const deps = self.decl_deps.items[decl.begin_dep..decl.end_dep]; |
| | 264 | |
| | 265 | seen.set(@enumToInt(decl_index)); |
| | 266 | |
| | 267 | if (self.globalPtr(decl_index)) |global| { |
| | 268 | try interface.append(global.result_id); |
| | 269 | } |
| | 270 | |
| | 271 | for (deps) |dep| { |
| | 272 | if (!seen.isSet(@enumToInt(dep))) { |
| | 273 | try self.addEntryPointDeps(dep, seen, interface); |
| | 274 | } |
| | 275 | } |
| | 276 | } |
| | 277 | |
| | 278 | fn entryPoints(self: *Module) !Section { |
| | 279 | var entry_points = Section{}; |
| | 280 | errdefer entry_points.deinit(self.gpa); |
| | 281 | |
| | 282 | var interface = std.ArrayList(IdRef).init(self.gpa); |
| | 283 | defer interface.deinit(); |
| | 284 | |
| | 285 | var seen = try std.DynamicBitSetUnmanaged.initEmpty(self.gpa, self.decls.items.len); |
| | 286 | defer seen.deinit(self.gpa); |
| | 287 | |
| | 288 | for (self.entry_points.items) |entry_point| { |
| | 289 | interface.items.len = 0; |
| | 290 | seen.setRangeValue(.{ .start = 0, .end = self.decls.items.len }, false); |
| | 291 | |
| | 292 | try self.addEntryPointDeps(entry_point.decl_index, &seen, &interface); |
| | 293 | |
| | 294 | const entry_point_id = self.declPtr(entry_point.decl_index).result_id; |
| | 295 | try entry_points.emit(self.gpa, .OpEntryPoint, .{ |
| | 296 | .execution_model = .Kernel, |
| | 297 | .entry_point = entry_point_id, |
| | 298 | .name = entry_point.name, |
| | 299 | .interface = interface.items, |
| | 300 | }); |
| | 301 | } |
| | 302 | |
| | 303 | return entry_points; |
| | 304 | } |
| | 305 | |
| 241 | /// Emit this module as a spir-v binary. | 306 | /// Emit this module as a spir-v binary. |
| 242 | pub fn flush(self: *Module, file: std.fs.File) !void { | 307 | pub fn flush(self: *Module, file: std.fs.File) !void { |
| 243 | // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction" | 308 | // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction" |
| ... | @@ -256,12 +321,15 @@ pub fn flush(self: *Module, file: std.fs.File) !void { | ... | @@ -256,12 +321,15 @@ pub fn flush(self: *Module, file: std.fs.File) !void { |
| 256 | var globals = try self.orderGlobals(); | 321 | var globals = try self.orderGlobals(); |
| 257 | defer globals.deinit(self.gpa); | 322 | defer globals.deinit(self.gpa); |
| 258 | | 323 | |
| | 324 | var entry_points = try self.entryPoints(); |
| | 325 | defer entry_points.deinit(self.gpa); |
| | 326 | |
| 259 | // Note: needs to be kept in order according to section 2.3! | 327 | // Note: needs to be kept in order according to section 2.3! |
| 260 | const buffers = &[_][]const Word{ | 328 | const buffers = &[_][]const Word{ |
| 261 | &header, | 329 | &header, |
| 262 | self.sections.capabilities.toWords(), | 330 | self.sections.capabilities.toWords(), |
| 263 | self.sections.extensions.toWords(), | 331 | self.sections.extensions.toWords(), |
| 264 | self.sections.entry_points.toWords(), | 332 | entry_points.toWords(), |
| 265 | self.sections.execution_modes.toWords(), | 333 | self.sections.execution_modes.toWords(), |
| 266 | self.sections.debug_strings.toWords(), | 334 | self.sections.debug_strings.toWords(), |
| 267 | self.sections.debug_names.toWords(), | 335 | self.sections.debug_names.toWords(), |
| ... | @@ -795,3 +863,10 @@ pub fn endGlobal(self: *Module, global_index: Decl.Index, begin_inst: u32) void | ... | @@ -795,3 +863,10 @@ pub fn endGlobal(self: *Module, global_index: Decl.Index, begin_inst: u32) void |
| 795 | global.begin_inst = begin_inst; | 863 | global.begin_inst = begin_inst; |
| 796 | global.end_inst = @intCast(u32, self.globals.section.instructions.items.len); | 864 | global.end_inst = @intCast(u32, self.globals.section.instructions.items.len); |
| 797 | } | 865 | } |
| | 866 | |
| | 867 | pub fn declareEntryPoint(self: *Module, decl_index: Decl.Index, name: []const u8) !void { |
| | 868 | try self.entry_points.append(self.gpa, .{ |
| | 869 | .decl_index = decl_index, |
| | 870 | .name = try self.arena.dupe(u8, name), |
| | 871 | }); |
| | 872 | } |