mt-lang 0.3.8 → 0.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/lib/milk_tea/base.rb +1 -2
  3. data/lib/milk_tea/bindings/bindgen/ast_parser.rb +0 -2
  4. data/lib/milk_tea/bindings/bindgen/declaration.rb +0 -2
  5. data/lib/milk_tea/bindings/bindgen/emitter.rb +0 -2
  6. data/lib/milk_tea/bindings/bindgen/overrides.rb +0 -2
  7. data/lib/milk_tea/bindings/bindgen/type_mapper.rb +51 -53
  8. data/lib/milk_tea/bindings/imported_bindings/generator.rb +7 -9
  9. data/lib/milk_tea/bindings/imported_bindings/method_source.rb +0 -2
  10. data/lib/milk_tea/bindings/imported_bindings/naming.rb +6 -8
  11. data/lib/milk_tea/bindings/imported_bindings.rb +0 -2
  12. data/lib/milk_tea/bindings/opengl_registry.rb +3 -7
  13. data/lib/milk_tea/bindings/steamworks.rb +12 -16
  14. data/lib/milk_tea/bindings/upstream_sources.rb +10 -14
  15. data/lib/milk_tea/bindings/vendored_box2d.rb +10 -12
  16. data/lib/milk_tea/bindings/vendored_cjson.rb +6 -8
  17. data/lib/milk_tea/bindings/vendored_flecs.rb +10 -12
  18. data/lib/milk_tea/bindings/vendored_glfw.rb +11 -13
  19. data/lib/milk_tea/bindings/vendored_libuv.rb +11 -13
  20. data/lib/milk_tea/bindings/vendored_pcre2.rb +11 -13
  21. data/lib/milk_tea/bindings/vendored_raylib.rb +6 -10
  22. data/lib/milk_tea/bindings/vendored_sdl3.rb +11 -13
  23. data/lib/milk_tea/bindings/vendored_steamworks.rb +1 -5
  24. data/lib/milk_tea/core/ast.rb +103 -45
  25. data/lib/milk_tea/core/async_runtime_installer.rb +0 -2
  26. data/lib/milk_tea/core/bindings/attribute_binding.rb +1 -3
  27. data/lib/milk_tea/core/c_backend/aggregate_utils.rb +147 -84
  28. data/lib/milk_tea/core/c_backend/control_flow_emission.rb +394 -396
  29. data/lib/milk_tea/core/c_backend/expressions.rb +489 -476
  30. data/lib/milk_tea/core/c_backend/feature_detection.rb +446 -437
  31. data/lib/milk_tea/core/c_backend/format_helpers.rb +0 -2
  32. data/lib/milk_tea/core/c_backend/reachability.rb +339 -341
  33. data/lib/milk_tea/core/c_backend/reinterpret.rb +231 -217
  34. data/lib/milk_tea/core/c_backend/runtime_helpers.rb +531 -526
  35. data/lib/milk_tea/core/c_backend/statements.rb +528 -530
  36. data/lib/milk_tea/core/c_backend/type_collectors.rb +1344 -1346
  37. data/lib/milk_tea/core/c_backend/type_declaration.rb +215 -213
  38. data/lib/milk_tea/core/c_backend/type_system.rb +347 -349
  39. data/lib/milk_tea/core/c_backend.rb +17 -9
  40. data/lib/milk_tea/core/compatibility_helpers.rb +0 -2
  41. data/lib/milk_tea/core/compile_time/const_eval.rb +7 -12
  42. data/lib/milk_tea/core/compile_time.rb +32 -38
  43. data/lib/milk_tea/core/control_flow/builder.rb +3 -5
  44. data/lib/milk_tea/core/control_flow/constant_propagation.rb +14 -17
  45. data/lib/milk_tea/core/control_flow/definite_assignment.rb +0 -1
  46. data/lib/milk_tea/core/ir.rb +10 -10
  47. data/lib/milk_tea/core/lexer/character_classes.rb +5 -7
  48. data/lib/milk_tea/core/lexer/format_strings.rb +7 -9
  49. data/lib/milk_tea/core/lexer/heredocs.rb +22 -22
  50. data/lib/milk_tea/core/lexer/indentation.rb +0 -2
  51. data/lib/milk_tea/core/lexer/numbers.rb +0 -2
  52. data/lib/milk_tea/core/lexer/recovery.rb +0 -2
  53. data/lib/milk_tea/core/lexer/strings.rb +0 -2
  54. data/lib/milk_tea/core/lexer/symbols.rb +0 -2
  55. data/lib/milk_tea/core/lexer/trivia.rb +0 -2
  56. data/lib/milk_tea/core/lexer.rb +0 -2
  57. data/lib/milk_tea/core/lowering/async/analysis.rb +0 -2
  58. data/lib/milk_tea/core/lowering/async/lowering.rb +1264 -1265
  59. data/lib/milk_tea/core/lowering/async/normalization.rb +0 -2
  60. data/lib/milk_tea/core/lowering/async.rb +627 -630
  61. data/lib/milk_tea/core/lowering/block.rb +413 -416
  62. data/lib/milk_tea/core/lowering/calls.rb +1381 -1384
  63. data/lib/milk_tea/core/lowering/declarations.rb +180 -183
  64. data/lib/milk_tea/core/lowering/dyn.rb +48 -50
  65. data/lib/milk_tea/core/lowering/events.rb +983 -985
  66. data/lib/milk_tea/core/lowering/expressions.rb +1513 -1518
  67. data/lib/milk_tea/core/lowering/foreign_cstr.rb +181 -184
  68. data/lib/milk_tea/core/lowering/functions.rb +185 -188
  69. data/lib/milk_tea/core/lowering/loops.rb +1028 -1031
  70. data/lib/milk_tea/core/lowering/proc.rb +363 -366
  71. data/lib/milk_tea/core/lowering/resolve.rb +2133 -2135
  72. data/lib/milk_tea/core/lowering/scans.rb +179 -181
  73. data/lib/milk_tea/core/lowering/str_buffer.rb +102 -105
  74. data/lib/milk_tea/core/lowering/utils.rb +1040 -1044
  75. data/lib/milk_tea/core/lowering.rb +5 -7
  76. data/lib/milk_tea/core/module_binder.rb +0 -2
  77. data/lib/milk_tea/core/module_loader/errors.rb +4 -2
  78. data/lib/milk_tea/core/module_loader.rb +113 -20
  79. data/lib/milk_tea/core/module_path_resolver.rb +0 -2
  80. data/lib/milk_tea/core/module_roots.rb +6 -8
  81. data/lib/milk_tea/core/parser/attributes.rb +0 -2
  82. data/lib/milk_tea/core/parser/blocks.rb +0 -2
  83. data/lib/milk_tea/core/parser/declarations.rb +0 -2
  84. data/lib/milk_tea/core/parser/expressions.rb +31 -14
  85. data/lib/milk_tea/core/parser/recovery.rb +0 -2
  86. data/lib/milk_tea/core/parser/statements.rb +0 -2
  87. data/lib/milk_tea/core/parser/types.rb +8 -10
  88. data/lib/milk_tea/core/parser.rb +1 -3
  89. data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +31 -33
  90. data/lib/milk_tea/core/pretty_printer/base_formatter.rb +0 -2
  91. data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +0 -2
  92. data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +0 -2
  93. data/lib/milk_tea/core/semantic_analyzer/attributes.rb +14 -16
  94. data/lib/milk_tea/core/semantic_analyzer/calls.rb +0 -2
  95. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1 -14
  96. data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +18 -21
  97. data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +0 -3
  98. data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +12 -15
  99. data/lib/milk_tea/core/semantic_analyzer/generics.rb +57 -59
  100. data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +0 -2
  101. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +5 -9
  102. data/lib/milk_tea/core/semantic_analyzer/nullability.rb +0 -3
  103. data/lib/milk_tea/core/semantic_analyzer/statements.rb +35 -40
  104. data/lib/milk_tea/core/semantic_analyzer/top_level.rb +10 -12
  105. data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +0 -6
  106. data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +102 -105
  107. data/lib/milk_tea/core/semantic_analyzer.rb +17 -8
  108. data/lib/milk_tea/core/types/layout.rb +21 -22
  109. data/lib/milk_tea/core/types/predicates.rb +0 -2
  110. data/lib/milk_tea/core/types/registry.rb +16 -18
  111. data/lib/milk_tea/core/types/visitor.rb +0 -4
  112. data/lib/milk_tea/dap/backends/lldb_dap.rb +0 -2
  113. data/lib/milk_tea/dap/protocol.rb +1 -1
  114. data/lib/milk_tea/dap/server/breakpoints.rb +0 -2
  115. data/lib/milk_tea/dap/server/debug_map.rb +0 -2
  116. data/lib/milk_tea/dap/server/handlers.rb +0 -2
  117. data/lib/milk_tea/dap/server/launch.rb +0 -2
  118. data/lib/milk_tea/dap/server/lldb_backend.rb +8 -10
  119. data/lib/milk_tea/dap/server/pause_diagnostics.rb +14 -16
  120. data/lib/milk_tea/dap/server/utilities.rb +0 -2
  121. data/lib/milk_tea/dap/server/wire.rb +0 -2
  122. data/lib/milk_tea/dap/server.rb +0 -2
  123. data/lib/milk_tea/lsp/diagnostics.rb +16 -16
  124. data/lib/milk_tea/lsp/server/call_hierarchy.rb +11 -12
  125. data/lib/milk_tea/lsp/server/code_actions.rb +355 -357
  126. data/lib/milk_tea/lsp/server/code_lens.rb +23 -25
  127. data/lib/milk_tea/lsp/server/completion.rb +873 -875
  128. data/lib/milk_tea/lsp/server/configuration.rb +129 -131
  129. data/lib/milk_tea/lsp/server/debug_info.rb +0 -2
  130. data/lib/milk_tea/lsp/server/definition.rb +564 -565
  131. data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +191 -193
  132. data/lib/milk_tea/lsp/server/execute_command.rb +0 -2
  133. data/lib/milk_tea/lsp/server/folding_range.rb +0 -4
  134. data/lib/milk_tea/lsp/server/formatting.rb +478 -480
  135. data/lib/milk_tea/lsp/server/hover.rb +1282 -1284
  136. data/lib/milk_tea/lsp/server/inlay_hints.rb +179 -181
  137. data/lib/milk_tea/lsp/server/lifecycle.rb +192 -194
  138. data/lib/milk_tea/lsp/server/linked_editing_range.rb +0 -2
  139. data/lib/milk_tea/lsp/server/on_type_formatting.rb +0 -2
  140. data/lib/milk_tea/lsp/server/progress.rb +0 -2
  141. data/lib/milk_tea/lsp/server/references.rb +316 -318
  142. data/lib/milk_tea/lsp/server/rename.rb +445 -447
  143. data/lib/milk_tea/lsp/server/selection_range.rb +0 -4
  144. data/lib/milk_tea/lsp/server/semantic_tokens.rb +1318 -1320
  145. data/lib/milk_tea/lsp/server/signature_help.rb +146 -148
  146. data/lib/milk_tea/lsp/server/text_documents.rb +99 -101
  147. data/lib/milk_tea/lsp/server/type_hierarchy.rb +2 -4
  148. data/lib/milk_tea/lsp/server/utilities.rb +397 -399
  149. data/lib/milk_tea/lsp/server.rb +0 -3
  150. data/lib/milk_tea/lsp/workspace/analysis.rb +40 -42
  151. data/lib/milk_tea/lsp/workspace/dependency_graph.rb +4 -10
  152. data/lib/milk_tea/lsp/workspace/utilities.rb +19 -19
  153. data/lib/milk_tea/packages/atomic_write.rb +4 -5
  154. data/lib/milk_tea/packages/dependency_solver.rb +15 -15
  155. data/lib/milk_tea/packages/lock.rb +4 -4
  156. data/lib/milk_tea/packages/manager_cli.rb +1 -1
  157. data/lib/milk_tea/packages/manifest.rb +3 -3
  158. data/lib/milk_tea/packages/registry_store.rb +4 -6
  159. data/lib/milk_tea/packages/services.rb +16 -16
  160. data/lib/milk_tea/packages/source_cache.rb +4 -6
  161. data/lib/milk_tea/packages/source_resolver.rb +44 -44
  162. data/lib/milk_tea/packages/version.rb +8 -8
  163. data/lib/milk_tea/tooling/build.rb +3 -7
  164. data/lib/milk_tea/tooling/build_cache.rb +0 -2
  165. data/lib/milk_tea/tooling/debug_info_formatter.rb +31 -33
  166. data/lib/milk_tea/tooling/debug_map.rb +8 -10
  167. data/lib/milk_tea/tooling/docs_app.rb +0 -2
  168. data/lib/milk_tea/tooling/linter/doc_tags.rb +25 -27
  169. data/lib/milk_tea/tooling/linter/fix_engine.rb +87 -24
  170. data/lib/milk_tea/tooling/linter/flow_rules.rb +44 -46
  171. data/lib/milk_tea/tooling/linter/imports_platform.rb +14 -16
  172. data/lib/milk_tea/tooling/linter/release_rules.rb +3 -5
  173. data/lib/milk_tea/tooling/linter/reserved_names.rb +23 -25
  174. data/lib/milk_tea/tooling/linter/rules.rb +87 -89
  175. data/lib/milk_tea/tooling/linter/source_helpers.rb +40 -42
  176. data/lib/milk_tea/tooling/linter/trailing_comma.rb +17 -19
  177. data/lib/milk_tea/tooling/linter/visitors.rb +162 -50
  178. data/lib/milk_tea/tooling/linter.rb +0 -2
  179. data/lib/milk_tea/tooling/project_scaffold.rb +0 -2
  180. data/lib/milk_tea/tooling/run.rb +0 -2
  181. data/lib/milk_tea/tooling/toolchain_cli.rb +0 -2
  182. data/std/cli.mt +13 -32
  183. data/std/color.mt +28 -28
  184. data/std/encoding.mt +4 -4
  185. data/std/graph.mt +1 -2
  186. data/std/hash.mt +14 -14
  187. data/std/http/server.mt +3 -3
  188. data/std/input.mt +1 -1
  189. data/std/json.mt +1 -1
  190. data/std/linear_algebra.mt +6 -6
  191. data/std/net/mux.mt +1 -1
  192. data/std/noise.mt +23 -23
  193. data/std/parse.mt +2 -2
  194. data/std/process.mt +3 -4
  195. data/std/sparse_set.mt +1 -1
  196. data/std/steering.mt +5 -5
  197. data/std/str.mt +1 -1
  198. data/std/tween.mt +4 -4
  199. data/std/utility.mt +3 -3
  200. metadata +2 -2
@@ -2,632 +2,797 @@
2
2
 
3
3
  module MilkTea
4
4
  module LowererEvents
5
- private
6
-
7
- def event_method_kind(receiver_type, member_name)
8
- return unless receiver_type.is_a?(Types::Event)
9
-
10
- case member_name
11
- when "subscribe" then :event_subscribe
12
- when "subscribe_once" then :event_subscribe_once
13
- when "unsubscribe" then :event_unsubscribe
14
- when "emit" then :event_emit
15
- when "wait" then :event_wait
16
- end
5
+ def event_method_kind(receiver_type, member_name)
6
+ return unless receiver_type.is_a?(Types::Event)
7
+
8
+ case member_name
9
+ when "subscribe" then :event_subscribe
10
+ when "subscribe_once" then :event_subscribe_once
11
+ when "unsubscribe" then :event_unsubscribe
12
+ when "emit" then :event_emit
13
+ when "wait" then :event_wait
17
14
  end
18
-
19
- def event_method_type(kind, event_type)
20
- case kind
21
- when :event_subscribe, :event_subscribe_once
22
- Types::Registry.function(
23
- kind.to_s,
24
- params: [Types::Registry.parameter("listener", event_listener_function_type(event_type))],
25
- return_type: event_subscription_result_type,
26
- )
27
- when :event_subscribe_stateful, :event_subscribe_once_stateful
28
- Types::Registry.function(
29
- kind.to_s,
30
- params: [
31
- Types::Registry.parameter("state", pointer_to(@ctx.types.fetch("void"))),
32
- Types::Registry.parameter("listener", event_stateful_listener_function_type(event_type)),
33
- ],
34
- return_type: event_subscription_result_type,
35
- )
36
- when :event_unsubscribe
37
- Types::Registry.function(
38
- kind.to_s,
39
- params: [Types::Registry.parameter("subscription", @ctx.types.fetch("Subscription"))],
40
- return_type: @ctx.types.fetch("bool"),
41
- )
42
- when :event_emit
43
- params = []
44
- params << Types::Registry.parameter("payload", event_type.payload_type) if event_type.payload_type
45
- Types::Registry.function(kind.to_s, params:, return_type: @ctx.types.fetch("void"))
46
- when :event_wait
47
- Types::Registry.function(kind.to_s, params: [], return_type: Types::Registry.task(event_wait_result_type(event_type)))
48
- else
49
- raise LoweringError.new("unsupported event method #{kind}", line: 0, column: 0, path: @ctx.current_analysis_path)
50
- end
15
+ end
16
+
17
+ def event_method_type(kind, event_type)
18
+ case kind
19
+ when :event_subscribe, :event_subscribe_once
20
+ Types::Registry.function(
21
+ kind.to_s,
22
+ params: [Types::Registry.parameter("listener", event_listener_function_type(event_type))],
23
+ return_type: event_subscription_result_type,
24
+ )
25
+ when :event_subscribe_stateful, :event_subscribe_once_stateful
26
+ Types::Registry.function(
27
+ kind.to_s,
28
+ params: [
29
+ Types::Registry.parameter("state", pointer_to(@ctx.types.fetch("void"))),
30
+ Types::Registry.parameter("listener", event_stateful_listener_function_type(event_type)),
31
+ ],
32
+ return_type: event_subscription_result_type,
33
+ )
34
+ when :event_unsubscribe
35
+ Types::Registry.function(
36
+ kind.to_s,
37
+ params: [Types::Registry.parameter("subscription", @ctx.types.fetch("Subscription"))],
38
+ return_type: @ctx.types.fetch("bool"),
39
+ )
40
+ when :event_emit
41
+ params = []
42
+ params << Types::Registry.parameter("payload", event_type.payload_type) if event_type.payload_type
43
+ Types::Registry.function(kind.to_s, params:, return_type: @ctx.types.fetch("void"))
44
+ when :event_wait
45
+ Types::Registry.function(kind.to_s, params: [], return_type: Types::Registry.task(event_wait_result_type(event_type)))
46
+ else
47
+ raise LoweringError.new("unsupported event method #{kind}", line: 0, column: 0, path: @ctx.current_analysis_path)
51
48
  end
52
-
53
- def event_member_from_owner_type(receiver_type, member_name)
54
- owner_type = receiver_type
55
- loop do
56
- case owner_type
57
- when Types::Nullable
58
- owner_type = owner_type.base
59
- when Types::GenericInstance
60
- if %w[ptr const_ptr own ref].include?(owner_type.name) && owner_type.arguments.length == 1
61
- owner_type = owner_type.arguments.first
62
- else
63
- break
64
- end
49
+ end
50
+
51
+ def event_member_from_owner_type(receiver_type, member_name)
52
+ owner_type = receiver_type
53
+ loop do
54
+ case owner_type
55
+ when Types::Nullable
56
+ owner_type = owner_type.base
57
+ when Types::GenericInstance
58
+ if %w[ptr const_ptr own ref].include?(owner_type.name) && owner_type.arguments.length == 1
59
+ owner_type = owner_type.arguments.first
65
60
  else
66
61
  break
67
62
  end
63
+ else
64
+ break
68
65
  end
69
-
70
- return unless owner_type.respond_to?(:event)
71
-
72
- owner_type.event(member_name)
73
- end
74
-
75
- def lower_event_storage_pointer(expression, env:)
76
- event_type = infer_expression_type(expression, env:)
77
- IR::AddressOf.new(
78
- expression: lower_expression(expression, env:, expected_type: event_type),
79
- type: pointer_to(event_type),
80
- )
81
- end
82
-
83
- def event_listener_function_type(event_type)
84
- params = []
85
- params << Types::Registry.parameter("payload", event_type.payload_type) if event_type.payload_type
86
- Types::Registry.function("#{event_type.name}__listener", params:, return_type: @ctx.types.fetch("void"))
87
- end
88
-
89
- def event_stateful_listener_function_type(event_type)
90
- params = [Types::Registry.parameter("state", pointer_to(@ctx.types.fetch("void")))]
91
- params << Types::Registry.parameter("payload", event_type.payload_type) if event_type.payload_type
92
- Types::Registry.function("#{event_type.name}__stateful_listener", params:, return_type: @ctx.types.fetch("void"))
93
66
  end
94
67
 
95
- def array_of(type, length)
96
- Types::Registry.generic_instance("array", [type, Types::LiteralTypeArg.new(length)])
97
- end
98
-
99
- def ensure_subscription_runtime
100
- return if @artifacts.subscription_runtime_emitted
101
-
102
- subscription_type = @ctx.types.fetch("Subscription")
103
- @artifacts.synthetic_structs << IR::StructDecl.new(
104
- name: subscription_type.name,
105
- linkage_name: subscription_type.linkage_name,
106
- fields: [
107
- IR::Field.new(name: "slot", type: @ctx.types.fetch("ptr_uint")),
108
- IR::Field.new(name: "generation", type: @ctx.types.fetch("ptr_uint")),
109
- ],
110
- packed: false,
111
- alignment: nil,
112
- )
113
- @artifacts.subscription_runtime_emitted = true
114
- end
115
-
116
- def ensure_event_error_enum
117
- return if @artifacts.event_error_enum_emitted
118
-
119
- event_error_type = @ctx.types.fetch("EventError")
120
- @artifacts.synthetic_enums << IR::EnumDecl.new(
121
- name: event_error_type.name,
122
- linkage_name: c_type_name(event_error_type),
123
- backing_type: event_error_type.backing_type,
124
- members: [
125
- IR::EnumMember.new(
126
- name: "full",
127
- linkage_name: enum_member_c_name(event_error_type, "full"),
128
- value: IR::IntegerLiteral.new(value: 0, type: event_error_type.backing_type),
68
+ return unless owner_type.respond_to?(:event)
69
+
70
+ owner_type.event(member_name)
71
+ end
72
+
73
+ def lower_event_storage_pointer(expression, env:)
74
+ event_type = infer_expression_type(expression, env:)
75
+ IR::AddressOf.new(
76
+ expression: lower_expression(expression, env:, expected_type: event_type),
77
+ type: pointer_to(event_type),
78
+ )
79
+ end
80
+
81
+ def event_listener_function_type(event_type)
82
+ params = []
83
+ params << Types::Registry.parameter("payload", event_type.payload_type) if event_type.payload_type
84
+ Types::Registry.function("#{event_type.name}__listener", params:, return_type: @ctx.types.fetch("void"))
85
+ end
86
+
87
+ def event_stateful_listener_function_type(event_type)
88
+ params = [Types::Registry.parameter("state", pointer_to(@ctx.types.fetch("void")))]
89
+ params << Types::Registry.parameter("payload", event_type.payload_type) if event_type.payload_type
90
+ Types::Registry.function("#{event_type.name}__stateful_listener", params:, return_type: @ctx.types.fetch("void"))
91
+ end
92
+
93
+ def array_of(type, length)
94
+ Types::Registry.generic_instance("array", [type, Types::LiteralTypeArg.new(length)])
95
+ end
96
+
97
+ def ensure_subscription_runtime
98
+ return if @artifacts.subscription_runtime_emitted
99
+
100
+ subscription_type = @ctx.types.fetch("Subscription")
101
+ @artifacts.synthetic_structs << IR::StructDecl.new(
102
+ name: subscription_type.name,
103
+ linkage_name: subscription_type.linkage_name,
104
+ fields: [
105
+ IR::Field.new(name: "slot", type: @ctx.types.fetch("ptr_uint")),
106
+ IR::Field.new(name: "generation", type: @ctx.types.fetch("ptr_uint")),
107
+ ],
108
+ packed: false,
109
+ alignment: nil,
110
+ )
111
+ @artifacts.subscription_runtime_emitted = true
112
+ end
113
+
114
+ def ensure_event_error_enum
115
+ return if @artifacts.event_error_enum_emitted
116
+
117
+ event_error_type = @ctx.types.fetch("EventError")
118
+ @artifacts.synthetic_enums << IR::EnumDecl.new(
119
+ name: event_error_type.name,
120
+ linkage_name: c_type_name(event_error_type),
121
+ backing_type: event_error_type.backing_type,
122
+ members: [
123
+ IR::EnumMember.new(
124
+ name: "full",
125
+ linkage_name: enum_member_c_name(event_error_type, "full"),
126
+ value: IR::IntegerLiteral.new(value: 0, type: event_error_type.backing_type),
127
+ ),
128
+ ],
129
+ flags: false,
130
+ )
131
+ @artifacts.event_error_enum_emitted = true
132
+ end
133
+
134
+ def ensure_event_runtime(event_type)
135
+ return @artifacts.event_runtime_infos.fetch(event_type) if @artifacts.event_runtime_infos.key?(event_type)
136
+
137
+ ensure_subscription_runtime
138
+ ensure_event_error_enum
139
+
140
+ void_ptr = pointer_to(@ctx.types.fetch("void"))
141
+ listener_type = event_listener_function_type(event_type)
142
+ subscription_result_type = event_subscription_result_type
143
+ wait_result_type = event_wait_result_type(event_type)
144
+ task_type = Types::Registry.task(wait_result_type)
145
+ wake_type = task_type.field("ready").params.fetch(0).type == void_ptr ? task_type.field("set_waiter").params.fetch(2).type : Types::Registry.function(nil, params: [Types::Registry.parameter("frame", void_ptr)], return_type: @ctx.types.fetch("void"))
146
+ slot_type = Types::Struct.new("#{event_type.linkage_name}__slot").define_fields(
147
+ "active" => @ctx.types.fetch("bool"),
148
+ "once" => @ctx.types.fetch("bool"),
149
+ "generation" => @ctx.types.fetch("ptr_uint"),
150
+ "state" => void_ptr,
151
+ "listener" => void_ptr,
152
+ "wait_frame" => void_ptr,
153
+ )
154
+ snapshot_type = Types::Struct.new("#{event_type.linkage_name}__snapshot").define_fields(
155
+ "slot" => @ctx.types.fetch("ptr_uint"),
156
+ "generation" => @ctx.types.fetch("ptr_uint"),
157
+ "once" => @ctx.types.fetch("bool"),
158
+ "wait_slot" => @ctx.types.fetch("bool"),
159
+ "stateful" => @ctx.types.fetch("bool"),
160
+ "state" => void_ptr,
161
+ "listener" => void_ptr,
162
+ )
163
+ wait_frame_type = Types::Struct.new("#{event_type.linkage_name}__wait_frame").define_fields(
164
+ "ready" => @ctx.types.fetch("bool"),
165
+ "waiter_frame" => void_ptr,
166
+ "waiter" => wake_type,
167
+ "event" => void_ptr,
168
+ "subscription" => @ctx.types.fetch("Subscription"),
169
+ "result" => wait_result_type,
170
+ )
171
+ slots_type = array_of(slot_type, event_type.capacity)
172
+ snapshots_type = array_of(snapshot_type, event_type.capacity)
173
+
174
+ @artifacts.synthetic_structs << IR::StructDecl.new(
175
+ name: slot_type.name,
176
+ linkage_name: slot_type.name,
177
+ fields: [
178
+ IR::Field.new(name: "active", type: @ctx.types.fetch("bool")),
179
+ IR::Field.new(name: "once", type: @ctx.types.fetch("bool")),
180
+ IR::Field.new(name: "generation", type: @ctx.types.fetch("ptr_uint")),
181
+ IR::Field.new(name: "state", type: void_ptr),
182
+ IR::Field.new(name: "listener", type: void_ptr),
183
+ IR::Field.new(name: "wait_frame", type: void_ptr),
184
+ ],
185
+ packed: false,
186
+ alignment: nil,
187
+ )
188
+ @artifacts.synthetic_structs << IR::StructDecl.new(
189
+ name: snapshot_type.name,
190
+ linkage_name: snapshot_type.name,
191
+ fields: [
192
+ IR::Field.new(name: "slot", type: @ctx.types.fetch("ptr_uint")),
193
+ IR::Field.new(name: "generation", type: @ctx.types.fetch("ptr_uint")),
194
+ IR::Field.new(name: "once", type: @ctx.types.fetch("bool")),
195
+ IR::Field.new(name: "wait_slot", type: @ctx.types.fetch("bool")),
196
+ IR::Field.new(name: "stateful", type: @ctx.types.fetch("bool")),
197
+ IR::Field.new(name: "state", type: void_ptr),
198
+ IR::Field.new(name: "listener", type: void_ptr),
199
+ ],
200
+ packed: false,
201
+ alignment: nil,
202
+ )
203
+ @artifacts.synthetic_structs << IR::StructDecl.new(
204
+ name: wait_frame_type.name,
205
+ linkage_name: wait_frame_type.name,
206
+ fields: [
207
+ IR::Field.new(name: "ready", type: @ctx.types.fetch("bool")),
208
+ IR::Field.new(name: "waiter_frame", type: void_ptr),
209
+ IR::Field.new(name: "waiter", type: wake_type),
210
+ IR::Field.new(name: "event", type: void_ptr),
211
+ IR::Field.new(name: "subscription", type: @ctx.types.fetch("Subscription")),
212
+ IR::Field.new(name: "result", type: wait_result_type),
213
+ ],
214
+ packed: false,
215
+ alignment: nil,
216
+ )
217
+ @artifacts.synthetic_structs << IR::StructDecl.new(
218
+ name: event_type.name,
219
+ linkage_name: event_type.linkage_name,
220
+ fields: [IR::Field.new(name: "slots", type: slots_type)],
221
+ packed: false,
222
+ alignment: nil,
223
+ )
224
+
225
+ runtime = {
226
+ event_type:,
227
+ event_pointer_type: pointer_to(event_type),
228
+ listener_type:,
229
+ stateful_listener_type: event_stateful_listener_function_type(event_type),
230
+ slot_type:,
231
+ slot_pointer_type: pointer_to(slot_type),
232
+ slots_type:,
233
+ snapshot_type:,
234
+ snapshots_type:,
235
+ wait_frame_type:,
236
+ wait_frame_pointer_type: pointer_to(wait_frame_type),
237
+ void_ptr:,
238
+ wake_type:,
239
+ subscription_result_type:,
240
+ wait_result_type:,
241
+ task_type:,
242
+ subscribe_linkage_name: "#{event_type.linkage_name}__subscribe",
243
+ subscribe_once_linkage_name: "#{event_type.linkage_name}__subscribe_once",
244
+ subscribe_stateful_linkage_name: "#{event_type.linkage_name}__subscribe_stateful",
245
+ subscribe_once_stateful_linkage_name: "#{event_type.linkage_name}__subscribe_once_stateful",
246
+ unsubscribe_linkage_name: "#{event_type.linkage_name}__unsubscribe",
247
+ emit_linkage_name: "#{event_type.linkage_name}__emit",
248
+ wait_linkage_name: "#{event_type.linkage_name}__wait",
249
+ wait_ready_linkage_name: "#{event_type.linkage_name}__wait__ready",
250
+ wait_set_waiter_linkage_name: "#{event_type.linkage_name}__wait__set_waiter",
251
+ wait_release_linkage_name: "#{event_type.linkage_name}__wait__release",
252
+ wait_take_result_linkage_name: "#{event_type.linkage_name}__wait__take_result",
253
+ }
254
+
255
+ @artifacts.synthetic_functions << build_event_subscribe_function(runtime, once: false)
256
+ @artifacts.synthetic_functions << build_event_subscribe_function(runtime, once: true)
257
+ @artifacts.synthetic_functions << build_event_subscribe_stateful_function(runtime, once: false)
258
+ @artifacts.synthetic_functions << build_event_subscribe_stateful_function(runtime, once: true)
259
+ @artifacts.synthetic_functions << build_event_unsubscribe_function(runtime)
260
+ @artifacts.synthetic_functions << build_event_emit_function(runtime)
261
+ @artifacts.synthetic_functions << build_event_wait_ready_function(runtime)
262
+ @artifacts.synthetic_functions << build_event_wait_set_waiter_function(runtime)
263
+ @artifacts.synthetic_functions << build_event_wait_release_function(runtime)
264
+ @artifacts.synthetic_functions << build_event_wait_take_result_function(runtime)
265
+ @artifacts.synthetic_functions << build_event_wait_function(runtime)
266
+
267
+ @artifacts.event_runtime_infos[event_type] = runtime
268
+ end
269
+
270
+ def build_event_subscribe_function(runtime, once:)
271
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
272
+ listener_expr = IR::Name.new(name: "listener", type: runtime.fetch(:listener_type), pointer: false)
273
+ slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
274
+ generation_expr = IR::Name.new(name: "__mt_generation", type: @ctx.types.fetch("ptr_uint"), pointer: false)
275
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
276
+
277
+ body = [
278
+ IR::ForStmt.new(
279
+ init: IR::LocalDecl.new(
280
+ name: "__mt_slot_index",
281
+ linkage_name: "__mt_slot_index",
282
+ type: @ctx.types.fetch("ptr_uint"),
283
+ value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint")),
284
+ ),
285
+ condition: IR::Binary.new(
286
+ operator: "<",
287
+ left: slot_index_expr,
288
+ right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")),
289
+ type: @ctx.types.fetch("bool"),
290
+ ),
291
+ post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
292
+ body: [
293
+ event_slot_local_decl(event_expr, slot_index_expr, runtime),
294
+ active_event_slot_continue_guard(slot_pointer_expr),
295
+ IR::LocalDecl.new(
296
+ name: "__mt_generation",
297
+ linkage_name: "__mt_generation",
298
+ type: @ctx.types.fetch("ptr_uint"),
299
+ value: event_next_generation_expression(slot_pointer_expr),
129
300
  ),
301
+ *event_slot_activate_statements(
302
+ slot_pointer_expr,
303
+ runtime,
304
+ generation_expr: generation_expr,
305
+ once: once,
306
+ wait_frame_expr: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
307
+ listener_expr: IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: listener_expr, type: runtime.fetch(:void_ptr)),
308
+ ),
309
+ IR::ReturnStmt.new(value: event_subscription_success_literal(runtime.fetch(:subscription_result_type), slot_index_expr, generation_expr)),
130
310
  ],
131
- flags: false,
132
- )
133
- @artifacts.event_error_enum_emitted = true
134
- end
135
-
136
- def ensure_event_runtime(event_type)
137
- return @artifacts.event_runtime_infos.fetch(event_type) if @artifacts.event_runtime_infos.key?(event_type)
138
-
139
- ensure_subscription_runtime
140
- ensure_event_error_enum
141
-
142
- void_ptr = pointer_to(@ctx.types.fetch("void"))
143
- listener_type = event_listener_function_type(event_type)
144
- subscription_result_type = event_subscription_result_type
145
- wait_result_type = event_wait_result_type(event_type)
146
- task_type = Types::Registry.task(wait_result_type)
147
- wake_type = task_type.field("ready").params.fetch(0).type == void_ptr ? task_type.field("set_waiter").params.fetch(2).type : Types::Registry.function(nil, params: [Types::Registry.parameter("frame", void_ptr)], return_type: @ctx.types.fetch("void"))
148
- slot_type = Types::Struct.new("#{event_type.linkage_name}__slot").define_fields(
149
- "active" => @ctx.types.fetch("bool"),
150
- "once" => @ctx.types.fetch("bool"),
151
- "generation" => @ctx.types.fetch("ptr_uint"),
152
- "state" => void_ptr,
153
- "listener" => void_ptr,
154
- "wait_frame" => void_ptr,
155
- )
156
- snapshot_type = Types::Struct.new("#{event_type.linkage_name}__snapshot").define_fields(
157
- "slot" => @ctx.types.fetch("ptr_uint"),
158
- "generation" => @ctx.types.fetch("ptr_uint"),
159
- "once" => @ctx.types.fetch("bool"),
160
- "wait_slot" => @ctx.types.fetch("bool"),
161
- "stateful" => @ctx.types.fetch("bool"),
162
- "state" => void_ptr,
163
- "listener" => void_ptr,
164
- )
165
- wait_frame_type = Types::Struct.new("#{event_type.linkage_name}__wait_frame").define_fields(
166
- "ready" => @ctx.types.fetch("bool"),
167
- "waiter_frame" => void_ptr,
168
- "waiter" => wake_type,
169
- "event" => void_ptr,
170
- "subscription" => @ctx.types.fetch("Subscription"),
171
- "result" => wait_result_type,
172
- )
173
- slots_type = array_of(slot_type, event_type.capacity)
174
- snapshots_type = array_of(snapshot_type, event_type.capacity)
175
-
176
- @artifacts.synthetic_structs << IR::StructDecl.new(
177
- name: slot_type.name,
178
- linkage_name: slot_type.name,
179
- fields: [
180
- IR::Field.new(name: "active", type: @ctx.types.fetch("bool")),
181
- IR::Field.new(name: "once", type: @ctx.types.fetch("bool")),
182
- IR::Field.new(name: "generation", type: @ctx.types.fetch("ptr_uint")),
183
- IR::Field.new(name: "state", type: void_ptr),
184
- IR::Field.new(name: "listener", type: void_ptr),
185
- IR::Field.new(name: "wait_frame", type: void_ptr),
186
- ],
187
- packed: false,
188
- alignment: nil,
189
- )
190
- @artifacts.synthetic_structs << IR::StructDecl.new(
191
- name: snapshot_type.name,
192
- linkage_name: snapshot_type.name,
193
- fields: [
194
- IR::Field.new(name: "slot", type: @ctx.types.fetch("ptr_uint")),
195
- IR::Field.new(name: "generation", type: @ctx.types.fetch("ptr_uint")),
196
- IR::Field.new(name: "once", type: @ctx.types.fetch("bool")),
197
- IR::Field.new(name: "wait_slot", type: @ctx.types.fetch("bool")),
198
- IR::Field.new(name: "stateful", type: @ctx.types.fetch("bool")),
199
- IR::Field.new(name: "state", type: void_ptr),
200
- IR::Field.new(name: "listener", type: void_ptr),
201
- ],
202
- packed: false,
203
- alignment: nil,
204
- )
205
- @artifacts.synthetic_structs << IR::StructDecl.new(
206
- name: wait_frame_type.name,
207
- linkage_name: wait_frame_type.name,
208
- fields: [
209
- IR::Field.new(name: "ready", type: @ctx.types.fetch("bool")),
210
- IR::Field.new(name: "waiter_frame", type: void_ptr),
211
- IR::Field.new(name: "waiter", type: wake_type),
212
- IR::Field.new(name: "event", type: void_ptr),
213
- IR::Field.new(name: "subscription", type: @ctx.types.fetch("Subscription")),
214
- IR::Field.new(name: "result", type: wait_result_type),
215
- ],
216
- packed: false,
217
- alignment: nil,
218
- )
219
- @artifacts.synthetic_structs << IR::StructDecl.new(
220
- name: event_type.name,
221
- linkage_name: event_type.linkage_name,
222
- fields: [IR::Field.new(name: "slots", type: slots_type)],
223
- packed: false,
224
- alignment: nil,
225
- )
226
-
227
- runtime = {
228
- event_type:,
229
- event_pointer_type: pointer_to(event_type),
230
- listener_type:,
231
- stateful_listener_type: event_stateful_listener_function_type(event_type),
232
- slot_type:,
233
- slot_pointer_type: pointer_to(slot_type),
234
- slots_type:,
235
- snapshot_type:,
236
- snapshots_type:,
237
- wait_frame_type:,
238
- wait_frame_pointer_type: pointer_to(wait_frame_type),
239
- void_ptr:,
240
- wake_type:,
241
- subscription_result_type:,
242
- wait_result_type:,
243
- task_type:,
244
- subscribe_linkage_name: "#{event_type.linkage_name}__subscribe",
245
- subscribe_once_linkage_name: "#{event_type.linkage_name}__subscribe_once",
246
- subscribe_stateful_linkage_name: "#{event_type.linkage_name}__subscribe_stateful",
247
- subscribe_once_stateful_linkage_name: "#{event_type.linkage_name}__subscribe_once_stateful",
248
- unsubscribe_linkage_name: "#{event_type.linkage_name}__unsubscribe",
249
- emit_linkage_name: "#{event_type.linkage_name}__emit",
250
- wait_linkage_name: "#{event_type.linkage_name}__wait",
251
- wait_ready_linkage_name: "#{event_type.linkage_name}__wait__ready",
252
- wait_set_waiter_linkage_name: "#{event_type.linkage_name}__wait__set_waiter",
253
- wait_release_linkage_name: "#{event_type.linkage_name}__wait__release",
254
- wait_take_result_linkage_name: "#{event_type.linkage_name}__wait__take_result",
255
- }
256
-
257
- @artifacts.synthetic_functions << build_event_subscribe_function(runtime, once: false)
258
- @artifacts.synthetic_functions << build_event_subscribe_function(runtime, once: true)
259
- @artifacts.synthetic_functions << build_event_subscribe_stateful_function(runtime, once: false)
260
- @artifacts.synthetic_functions << build_event_subscribe_stateful_function(runtime, once: true)
261
- @artifacts.synthetic_functions << build_event_unsubscribe_function(runtime)
262
- @artifacts.synthetic_functions << build_event_emit_function(runtime)
263
- @artifacts.synthetic_functions << build_event_wait_ready_function(runtime)
264
- @artifacts.synthetic_functions << build_event_wait_set_waiter_function(runtime)
265
- @artifacts.synthetic_functions << build_event_wait_release_function(runtime)
266
- @artifacts.synthetic_functions << build_event_wait_take_result_function(runtime)
267
- @artifacts.synthetic_functions << build_event_wait_function(runtime)
268
-
269
- @artifacts.event_runtime_infos[event_type] = runtime
270
- end
271
-
272
- def build_event_subscribe_function(runtime, once:)
273
- event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
274
- listener_expr = IR::Name.new(name: "listener", type: runtime.fetch(:listener_type), pointer: false)
275
- slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
276
- generation_expr = IR::Name.new(name: "__mt_generation", type: @ctx.types.fetch("ptr_uint"), pointer: false)
277
- slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
278
-
279
- body = [
280
- IR::ForStmt.new(
281
- init: IR::LocalDecl.new(
282
- name: "__mt_slot_index",
283
- linkage_name: "__mt_slot_index",
311
+ ),
312
+ IR::ReturnStmt.new(value: event_failure_literal(runtime.fetch(:subscription_result_type))),
313
+ ]
314
+
315
+ IR::Function.new(
316
+ name: once ? "#{runtime.fetch(:subscribe_once_linkage_name)}_fn" : "#{runtime.fetch(:subscribe_linkage_name)}_fn",
317
+ linkage_name: once ? runtime.fetch(:subscribe_once_linkage_name) : runtime.fetch(:subscribe_linkage_name),
318
+ params: [
319
+ IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false),
320
+ IR::Param.new(name: "listener", linkage_name: "listener", type: runtime.fetch(:listener_type), pointer: false),
321
+ ],
322
+ return_type: runtime.fetch(:subscription_result_type),
323
+ body:,
324
+ entry_point: false,
325
+ )
326
+ end
327
+
328
+ def build_event_subscribe_stateful_function(runtime, once:)
329
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
330
+ state_expr = IR::Name.new(name: "state", type: runtime.fetch(:void_ptr), pointer: false)
331
+ listener_expr = IR::Name.new(name: "listener", type: runtime.fetch(:void_ptr), pointer: false)
332
+ slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
333
+ generation_expr = IR::Name.new(name: "__mt_generation", type: @ctx.types.fetch("ptr_uint"), pointer: false)
334
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
335
+
336
+ body = [
337
+ IR::ForStmt.new(
338
+ init: IR::LocalDecl.new(
339
+ name: "__mt_slot_index",
340
+ linkage_name: "__mt_slot_index",
341
+ type: @ctx.types.fetch("ptr_uint"),
342
+ value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint")),
343
+ ),
344
+ condition: IR::Binary.new(
345
+ operator: "<",
346
+ left: slot_index_expr,
347
+ right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")),
348
+ type: @ctx.types.fetch("bool"),
349
+ ),
350
+ post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
351
+ body: [
352
+ event_slot_local_decl(event_expr, slot_index_expr, runtime),
353
+ active_event_slot_continue_guard(slot_pointer_expr),
354
+ IR::LocalDecl.new(
355
+ name: "__mt_generation",
356
+ linkage_name: "__mt_generation",
284
357
  type: @ctx.types.fetch("ptr_uint"),
285
- value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint")),
358
+ value: event_next_generation_expression(slot_pointer_expr),
286
359
  ),
287
- condition: IR::Binary.new(
288
- operator: "<",
289
- left: slot_index_expr,
290
- right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")),
291
- type: @ctx.types.fetch("bool"),
360
+ *event_slot_activate_stateful_statements(
361
+ slot_pointer_expr,
362
+ runtime,
363
+ generation_expr: generation_expr,
364
+ once: once,
365
+ state_expr: state_expr,
366
+ wait_frame_expr: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
367
+ listener_expr: listener_expr,
292
368
  ),
293
- post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
294
- body: [
295
- event_slot_local_decl(event_expr, slot_index_expr, runtime),
296
- active_event_slot_continue_guard(slot_pointer_expr),
297
- IR::LocalDecl.new(
298
- name: "__mt_generation",
299
- linkage_name: "__mt_generation",
300
- type: @ctx.types.fetch("ptr_uint"),
301
- value: event_next_generation_expression(slot_pointer_expr),
302
- ),
303
- *event_slot_activate_statements(
304
- slot_pointer_expr,
305
- runtime,
306
- generation_expr: generation_expr,
307
- once: once,
308
- wait_frame_expr: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
309
- listener_expr: IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: listener_expr, type: runtime.fetch(:void_ptr)),
310
- ),
311
- IR::ReturnStmt.new(value: event_subscription_success_literal(runtime.fetch(:subscription_result_type), slot_index_expr, generation_expr)),
312
- ],
369
+ IR::ReturnStmt.new(value: event_subscription_success_literal(runtime.fetch(:subscription_result_type), slot_index_expr, generation_expr)),
370
+ ],
371
+ ),
372
+ IR::ReturnStmt.new(value: event_failure_literal(runtime.fetch(:subscription_result_type))),
373
+ ]
374
+
375
+ linkage_name = once ? runtime.fetch(:subscribe_once_stateful_linkage_name) : runtime.fetch(:subscribe_stateful_linkage_name)
376
+ IR::Function.new(
377
+ name: "#{linkage_name}_fn",
378
+ linkage_name:,
379
+ params: [
380
+ IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false),
381
+ IR::Param.new(name: "state", linkage_name: "state", type: runtime.fetch(:void_ptr), pointer: false),
382
+ IR::Param.new(name: "listener", linkage_name: "listener", type: runtime.fetch(:void_ptr), pointer: false),
383
+ ],
384
+ return_type: runtime.fetch(:subscription_result_type),
385
+ body:,
386
+ entry_point: false,
387
+ )
388
+ end
389
+
390
+ def build_event_unsubscribe_function(runtime)
391
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
392
+ subscription_expr = IR::Name.new(name: "subscription", type: @ctx.types.fetch("Subscription"), pointer: false)
393
+ slot_index_expr = subscription_field_expression(subscription_expr, "slot", @ctx.types.fetch("ptr_uint"))
394
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
395
+
396
+ false_value = IR::BooleanLiteral.new(value: false, type: @ctx.types.fetch("bool"))
397
+ true_value = IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))
398
+ body = [
399
+ IR::IfStmt.new(
400
+ condition: IR::Binary.new(
401
+ operator: ">=",
402
+ left: slot_index_expr,
403
+ right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")),
404
+ type: @ctx.types.fetch("bool"),
405
+ ),
406
+ then_body: [IR::ReturnStmt.new(value: false_value)],
407
+ else_body: nil,
408
+ ),
409
+ IR::LocalDecl.new(
410
+ name: "__mt_slot",
411
+ linkage_name: "__mt_slot",
412
+ type: runtime.fetch(:slot_pointer_type),
413
+ value: event_slot_pointer_expression(event_expr, slot_index_expr, runtime),
414
+ ),
415
+ IR::IfStmt.new(
416
+ condition: IR::Unary.new(operator: "not", operand: event_slot_active_expression(slot_pointer_expr), type: @ctx.types.fetch("bool")),
417
+ then_body: [IR::ReturnStmt.new(value: false_value)],
418
+ else_body: nil,
419
+ ),
420
+ IR::IfStmt.new(
421
+ condition: IR::Binary.new(
422
+ operator: "!=",
423
+ left: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")),
424
+ right: subscription_field_expression(subscription_expr, "generation", @ctx.types.fetch("ptr_uint")),
425
+ type: @ctx.types.fetch("bool"),
313
426
  ),
314
- IR::ReturnStmt.new(value: event_failure_literal(runtime.fetch(:subscription_result_type))),
315
- ]
427
+ then_body: [IR::ReturnStmt.new(value: false_value)],
428
+ else_body: nil,
429
+ ),
430
+ *event_slot_clear_statements(slot_pointer_expr, runtime),
431
+ IR::ReturnStmt.new(value: true_value),
432
+ ]
433
+
434
+ IR::Function.new(
435
+ name: "#{runtime.fetch(:unsubscribe_linkage_name)}_fn",
436
+ linkage_name: runtime.fetch(:unsubscribe_linkage_name),
437
+ params: [
438
+ IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false),
439
+ IR::Param.new(name: "subscription", linkage_name: "subscription", type: @ctx.types.fetch("Subscription"), pointer: false),
440
+ ],
441
+ return_type: @ctx.types.fetch("bool"),
442
+ body:,
443
+ entry_point: false,
444
+ )
445
+ end
446
+
447
+ def build_event_emit_function(runtime)
448
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
449
+ payload_expr = runtime.fetch(:event_type).payload_type ? IR::Name.new(name: "payload", type: runtime.fetch(:event_type).payload_type, pointer: false) : nil
450
+ snapshots_expr = IR::Name.new(name: "__mt_snapshots", type: runtime.fetch(:snapshots_type), pointer: false)
451
+ snapshot_count_expr = IR::Name.new(name: "__mt_snapshot_count", type: @ctx.types.fetch("ptr_uint"), pointer: false)
452
+ slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
453
+ dispatch_index_expr = IR::Name.new(name: "__mt_dispatch_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
454
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
455
+ frame_pointer_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
456
+
457
+ collect_body = [
458
+ event_slot_local_decl(event_expr, slot_index_expr, runtime),
459
+ inactive_event_slot_continue_guard(slot_pointer_expr),
460
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "slot", @ctx.types.fetch("ptr_uint")), operator: "=", value: slot_index_expr),
461
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "generation", @ctx.types.fetch("ptr_uint")), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint"))),
462
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "once", @ctx.types.fetch("bool")), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool"))),
463
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "wait_slot", @ctx.types.fetch("bool")),
464
+ operator: "=",
465
+ value: IR::Binary.new(
466
+ operator: "!=",
467
+ left: event_slot_wait_frame_expression(slot_pointer_expr, runtime),
468
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
469
+ type: @ctx.types.fetch("bool"),
470
+ ),
471
+ ),
472
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "stateful", @ctx.types.fetch("bool")), operator: "=", value: IR::Binary.new(operator: "!=", left: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr)), right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)), type: @ctx.types.fetch("bool"))),
473
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "state", runtime.fetch(:void_ptr)), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr))),
474
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "listener", runtime.fetch(:void_ptr)), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "listener", runtime.fetch(:void_ptr))),
475
+ IR::Assignment.new(target: snapshot_count_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
476
+ ]
477
+
478
+ snapshot_subscription_expr = event_subscription_literal(
479
+ snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "slot", @ctx.types.fetch("ptr_uint")),
480
+ snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "generation", @ctx.types.fetch("ptr_uint")),
481
+ )
482
+ current_slot_active = event_slot_active_expression(slot_pointer_expr)
483
+ current_slot_generation = event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint"))
484
+ current_wait_frame = event_slot_wait_frame_expression(slot_pointer_expr, runtime)
485
+ wait_slot_condition = IR::Binary.new(
486
+ operator: "and",
487
+ left: current_slot_active,
488
+ right: IR::Binary.new(
489
+ operator: "and",
490
+ left: IR::Binary.new(
491
+ operator: "==",
492
+ left: current_slot_generation,
493
+ right: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "generation", @ctx.types.fetch("ptr_uint")),
494
+ type: @ctx.types.fetch("bool"),
495
+ ),
496
+ right: IR::Binary.new(
497
+ operator: "!=",
498
+ left: current_wait_frame,
499
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
500
+ type: @ctx.types.fetch("bool"),
501
+ ),
502
+ type: @ctx.types.fetch("bool"),
503
+ ),
504
+ type: @ctx.types.fetch("bool"),
505
+ )
316
506
 
317
- IR::Function.new(
318
- name: once ? "#{runtime.fetch(:subscribe_once_linkage_name)}_fn" : "#{runtime.fetch(:subscribe_linkage_name)}_fn",
319
- linkage_name: once ? runtime.fetch(:subscribe_once_linkage_name) : runtime.fetch(:subscribe_linkage_name),
320
- params: [
321
- IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false),
322
- IR::Param.new(name: "listener", linkage_name: "listener", type: runtime.fetch(:listener_type), pointer: false),
323
- ],
324
- return_type: runtime.fetch(:subscription_result_type),
325
- body:,
326
- entry_point: false,
327
- )
328
- end
507
+ wait_result_value = event_wait_success_literal(runtime.fetch(:wait_result_type), payload_expr)
508
+ waiter_frame_expr = wait_frame_field_expression(frame_pointer_expr, "waiter_frame", runtime.fetch(:void_ptr))
329
509
 
330
- def build_event_subscribe_stateful_function(runtime, once:)
331
- event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
332
- state_expr = IR::Name.new(name: "state", type: runtime.fetch(:void_ptr), pointer: false)
333
- listener_expr = IR::Name.new(name: "listener", type: runtime.fetch(:void_ptr), pointer: false)
334
- slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
335
- generation_expr = IR::Name.new(name: "__mt_generation", type: @ctx.types.fetch("ptr_uint"), pointer: false)
336
- slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
337
-
338
- body = [
339
- IR::ForStmt.new(
340
- init: IR::LocalDecl.new(
341
- name: "__mt_slot_index",
342
- linkage_name: "__mt_slot_index",
343
- type: @ctx.types.fetch("ptr_uint"),
344
- value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint")),
345
- ),
346
- condition: IR::Binary.new(
347
- operator: "<",
348
- left: slot_index_expr,
349
- right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")),
350
- type: @ctx.types.fetch("bool"),
351
- ),
352
- post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
353
- body: [
354
- event_slot_local_decl(event_expr, slot_index_expr, runtime),
355
- active_event_slot_continue_guard(slot_pointer_expr),
356
- IR::LocalDecl.new(
357
- name: "__mt_generation",
358
- linkage_name: "__mt_generation",
359
- type: @ctx.types.fetch("ptr_uint"),
360
- value: event_next_generation_expression(slot_pointer_expr),
361
- ),
362
- *event_slot_activate_stateful_statements(
363
- slot_pointer_expr,
510
+ dispatch_body = [
511
+ IR::IfStmt.new(
512
+ condition: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "wait_slot", @ctx.types.fetch("bool")),
513
+ then_body: [
514
+ IR::LocalDecl.new(
515
+ name: "__mt_slot",
516
+ linkage_name: "__mt_slot",
517
+ type: runtime.fetch(:slot_pointer_type),
518
+ value: event_slot_pointer_expression(
519
+ event_expr,
520
+ snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "slot", @ctx.types.fetch("ptr_uint")),
364
521
  runtime,
365
- generation_expr: generation_expr,
366
- once: once,
367
- state_expr: state_expr,
368
- wait_frame_expr: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
369
- listener_expr: listener_expr,
370
522
  ),
371
- IR::ReturnStmt.new(value: event_subscription_success_literal(runtime.fetch(:subscription_result_type), slot_index_expr, generation_expr)),
372
- ],
373
- ),
374
- IR::ReturnStmt.new(value: event_failure_literal(runtime.fetch(:subscription_result_type))),
375
- ]
376
-
377
- linkage_name = once ? runtime.fetch(:subscribe_once_stateful_linkage_name) : runtime.fetch(:subscribe_stateful_linkage_name)
378
- IR::Function.new(
379
- name: "#{linkage_name}_fn",
380
- linkage_name:,
381
- params: [
382
- IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false),
383
- IR::Param.new(name: "state", linkage_name: "state", type: runtime.fetch(:void_ptr), pointer: false),
384
- IR::Param.new(name: "listener", linkage_name: "listener", type: runtime.fetch(:void_ptr), pointer: false),
523
+ ),
524
+ IR::IfStmt.new(
525
+ condition: wait_slot_condition,
526
+ then_body: [
527
+ IR::LocalDecl.new(
528
+ name: "__mt_wait_frame",
529
+ linkage_name: "__mt_wait_frame",
530
+ type: runtime.fetch(:wait_frame_pointer_type),
531
+ value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: current_wait_frame, type: runtime.fetch(:wait_frame_pointer_type)),
532
+ ),
533
+ IR::ExpressionStmt.new(expression: event_unsubscribe_call(runtime, event_expr, snapshot_subscription_expr)),
534
+ IR::Assignment.new(target: wait_frame_field_expression(frame_pointer_expr, "result", runtime.fetch(:wait_result_type)), operator: "=", value: wait_result_value),
535
+ IR::Assignment.new(target: wait_frame_field_expression(frame_pointer_expr, "ready", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))),
536
+ IR::IfStmt.new(
537
+ condition: IR::Binary.new(
538
+ operator: "!=",
539
+ left: waiter_frame_expr,
540
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
541
+ type: @ctx.types.fetch("bool"),
542
+ ),
543
+ then_body: [
544
+ IR::LocalDecl.new(name: "__mt_waiter_frame", linkage_name: "__mt_waiter_frame", type: runtime.fetch(:void_ptr), value: waiter_frame_expr),
545
+ IR::Assignment.new(target: waiter_frame_expr, operator: "=", value: IR::NullLiteral.new(type: runtime.fetch(:void_ptr))),
546
+ IR::ExpressionStmt.new(
547
+ expression: IR::Call.new(
548
+ callee: wait_frame_field_expression(frame_pointer_expr, "waiter", runtime.fetch(:wake_type)),
549
+ arguments: [IR::Name.new(name: "__mt_waiter_frame", type: runtime.fetch(:void_ptr), pointer: false)],
550
+ type: @ctx.types.fetch("void"),
551
+ ),
552
+ ),
553
+ ],
554
+ else_body: nil,
555
+ ),
556
+ ],
557
+ else_body: nil,
558
+ ),
385
559
  ],
386
- return_type: runtime.fetch(:subscription_result_type),
387
- body:,
388
- entry_point: false,
389
- )
390
- end
391
-
392
- def build_event_unsubscribe_function(runtime)
393
- event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
394
- subscription_expr = IR::Name.new(name: "subscription", type: @ctx.types.fetch("Subscription"), pointer: false)
395
- slot_index_expr = subscription_field_expression(subscription_expr, "slot", @ctx.types.fetch("ptr_uint"))
396
- slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
397
-
398
- false_value = IR::BooleanLiteral.new(value: false, type: @ctx.types.fetch("bool"))
399
- true_value = IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))
400
- body = [
560
+ else_body: [
561
+ IR::IfStmt.new(
562
+ condition: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "once", @ctx.types.fetch("bool")),
563
+ then_body: [IR::ExpressionStmt.new(expression: event_unsubscribe_call(runtime, event_expr, snapshot_subscription_expr))],
564
+ else_body: nil,
565
+ ),
566
+ IR::IfStmt.new(
567
+ condition: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "stateful", @ctx.types.fetch("bool")),
568
+ then_body: [
569
+ IR::ExpressionStmt.new(expression: event_stateful_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)),
570
+ ],
571
+ else_body: [
572
+ IR::ExpressionStmt.new(expression: event_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)),
573
+ ],
574
+ ),
575
+ ],
576
+ ),
577
+ ]
578
+
579
+ body = [
580
+ IR::LocalDecl.new(name: "__mt_snapshots", linkage_name: "__mt_snapshots", type: runtime.fetch(:snapshots_type), value: IR::ZeroInit.new(type: runtime.fetch(:snapshots_type))),
581
+ IR::LocalDecl.new(name: "__mt_snapshot_count", linkage_name: "__mt_snapshot_count", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
582
+ IR::ForStmt.new(
583
+ init: IR::LocalDecl.new(name: "__mt_slot_index", linkage_name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
584
+ condition: IR::Binary.new(operator: "<", left: slot_index_expr, right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")), type: @ctx.types.fetch("bool")),
585
+ post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
586
+ body: collect_body,
587
+ ),
588
+ IR::ForStmt.new(
589
+ init: IR::LocalDecl.new(name: "__mt_dispatch_index", linkage_name: "__mt_dispatch_index", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
590
+ condition: IR::Binary.new(operator: "<", left: dispatch_index_expr, right: snapshot_count_expr, type: @ctx.types.fetch("bool")),
591
+ post: IR::Assignment.new(target: dispatch_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
592
+ body: dispatch_body,
593
+ ),
594
+ IR::ReturnStmt.new(value: nil),
595
+ ]
596
+
597
+ params = [IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)]
598
+ params << IR::Param.new(name: "payload", linkage_name: "payload", type: runtime.fetch(:event_type).payload_type, pointer: false) if runtime.fetch(:event_type).payload_type
599
+
600
+ IR::Function.new(
601
+ name: "#{runtime.fetch(:emit_linkage_name)}_fn",
602
+ linkage_name: runtime.fetch(:emit_linkage_name),
603
+ params:,
604
+ return_type: @ctx.types.fetch("void"),
605
+ body:,
606
+ entry_point: false,
607
+ )
608
+ end
609
+
610
+ def build_event_wait_ready_function(runtime)
611
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
612
+ raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
613
+
614
+ IR::Function.new(
615
+ name: "#{runtime.fetch(:wait_ready_linkage_name)}_fn",
616
+ linkage_name: runtime.fetch(:wait_ready_linkage_name),
617
+ params: [IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false)],
618
+ return_type: @ctx.types.fetch("bool"),
619
+ body: [
401
620
  IR::IfStmt.new(
402
621
  condition: IR::Binary.new(
403
- operator: ">=",
404
- left: slot_index_expr,
405
- right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")),
622
+ operator: "==",
623
+ left: raw_frame_expr,
624
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
406
625
  type: @ctx.types.fetch("bool"),
407
626
  ),
408
- then_body: [IR::ReturnStmt.new(value: false_value)],
627
+ then_body: [IR::ReturnStmt.new(value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool")))],
409
628
  else_body: nil,
410
629
  ),
411
630
  IR::LocalDecl.new(
412
- name: "__mt_slot",
413
- linkage_name: "__mt_slot",
414
- type: runtime.fetch(:slot_pointer_type),
415
- value: event_slot_pointer_expression(event_expr, slot_index_expr, runtime),
416
- ),
417
- IR::IfStmt.new(
418
- condition: IR::Unary.new(operator: "not", operand: event_slot_active_expression(slot_pointer_expr), type: @ctx.types.fetch("bool")),
419
- then_body: [IR::ReturnStmt.new(value: false_value)],
420
- else_body: nil,
631
+ name: "__mt_wait_frame",
632
+ linkage_name: "__mt_wait_frame",
633
+ type: runtime.fetch(:wait_frame_pointer_type),
634
+ value: IR::Cast.new(
635
+ target_type: runtime.fetch(:wait_frame_pointer_type),
636
+ expression: IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false),
637
+ type: runtime.fetch(:wait_frame_pointer_type),
638
+ ),
421
639
  ),
640
+ IR::ReturnStmt.new(value: wait_frame_field_expression(frame_expr, "ready", @ctx.types.fetch("bool"))),
641
+ ],
642
+ entry_point: false,
643
+ )
644
+ end
645
+
646
+ def build_event_wait_set_waiter_function(runtime)
647
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
648
+ raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
649
+ waiter_frame_expr = IR::Name.new(name: "waiter_frame", type: runtime.fetch(:void_ptr), pointer: false)
650
+ waiter_expr = IR::Name.new(name: "waiter", type: runtime.fetch(:wake_type), pointer: false)
651
+
652
+ IR::Function.new(
653
+ name: "#{runtime.fetch(:wait_set_waiter_linkage_name)}_fn",
654
+ linkage_name: runtime.fetch(:wait_set_waiter_linkage_name),
655
+ params: [
656
+ IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false),
657
+ IR::Param.new(name: "waiter_frame", linkage_name: "waiter_frame", type: runtime.fetch(:void_ptr), pointer: false),
658
+ IR::Param.new(name: "waiter", linkage_name: "waiter", type: runtime.fetch(:wake_type), pointer: false),
659
+ ],
660
+ return_type: @ctx.types.fetch("void"),
661
+ body: [
422
662
  IR::IfStmt.new(
423
663
  condition: IR::Binary.new(
424
- operator: "!=",
425
- left: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")),
426
- right: subscription_field_expression(subscription_expr, "generation", @ctx.types.fetch("ptr_uint")),
664
+ operator: "==",
665
+ left: raw_frame_expr,
666
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
427
667
  type: @ctx.types.fetch("bool"),
428
668
  ),
429
- then_body: [IR::ReturnStmt.new(value: false_value)],
669
+ then_body: [
670
+ IR::ExpressionStmt.new(expression: IR::Call.new(callee: waiter_expr, arguments: [waiter_frame_expr], type: @ctx.types.fetch("void"))),
671
+ IR::ReturnStmt.new(value: nil),
672
+ ],
430
673
  else_body: nil,
431
674
  ),
432
- *event_slot_clear_statements(slot_pointer_expr, runtime),
433
- IR::ReturnStmt.new(value: true_value),
434
- ]
435
-
436
- IR::Function.new(
437
- name: "#{runtime.fetch(:unsubscribe_linkage_name)}_fn",
438
- linkage_name: runtime.fetch(:unsubscribe_linkage_name),
439
- params: [
440
- IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false),
441
- IR::Param.new(name: "subscription", linkage_name: "subscription", type: @ctx.types.fetch("Subscription"), pointer: false),
442
- ],
443
- return_type: @ctx.types.fetch("bool"),
444
- body:,
445
- entry_point: false,
446
- )
447
- end
448
-
449
- def build_event_emit_function(runtime)
450
- event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
451
- payload_expr = runtime.fetch(:event_type).payload_type ? IR::Name.new(name: "payload", type: runtime.fetch(:event_type).payload_type, pointer: false) : nil
452
- snapshots_expr = IR::Name.new(name: "__mt_snapshots", type: runtime.fetch(:snapshots_type), pointer: false)
453
- snapshot_count_expr = IR::Name.new(name: "__mt_snapshot_count", type: @ctx.types.fetch("ptr_uint"), pointer: false)
454
- slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
455
- dispatch_index_expr = IR::Name.new(name: "__mt_dispatch_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
456
- slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
457
- frame_pointer_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
458
-
459
- collect_body = [
460
- event_slot_local_decl(event_expr, slot_index_expr, runtime),
461
- inactive_event_slot_continue_guard(slot_pointer_expr),
462
- IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "slot", @ctx.types.fetch("ptr_uint")), operator: "=", value: slot_index_expr),
463
- IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "generation", @ctx.types.fetch("ptr_uint")), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint"))),
464
- IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "once", @ctx.types.fetch("bool")), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool"))),
465
- IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "wait_slot", @ctx.types.fetch("bool")),
466
- operator: "=",
467
- value: IR::Binary.new(
468
- operator: "!=",
469
- left: event_slot_wait_frame_expression(slot_pointer_expr, runtime),
470
- right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
471
- type: @ctx.types.fetch("bool"),
472
- ),
675
+ IR::LocalDecl.new(
676
+ name: "__mt_wait_frame",
677
+ linkage_name: "__mt_wait_frame",
678
+ type: runtime.fetch(:wait_frame_pointer_type),
679
+ value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false), type: runtime.fetch(:wait_frame_pointer_type)),
473
680
  ),
474
- IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "stateful", @ctx.types.fetch("bool")), operator: "=", value: IR::Binary.new(operator: "!=", left: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr)), right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)), type: @ctx.types.fetch("bool"))),
475
- IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "state", runtime.fetch(:void_ptr)), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr))),
476
- IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "listener", runtime.fetch(:void_ptr)), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "listener", runtime.fetch(:void_ptr))),
477
- IR::Assignment.new(target: snapshot_count_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
478
- ]
479
-
480
- snapshot_subscription_expr = event_subscription_literal(
481
- snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "slot", @ctx.types.fetch("ptr_uint")),
482
- snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "generation", @ctx.types.fetch("ptr_uint")),
483
- )
484
- current_slot_active = event_slot_active_expression(slot_pointer_expr)
485
- current_slot_generation = event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint"))
486
- current_wait_frame = event_slot_wait_frame_expression(slot_pointer_expr, runtime)
487
- wait_slot_condition = IR::Binary.new(
488
- operator: "and",
489
- left: current_slot_active,
490
- right: IR::Binary.new(
491
- operator: "and",
492
- left: IR::Binary.new(
681
+ IR::IfStmt.new(
682
+ condition: wait_frame_field_expression(frame_expr, "ready", @ctx.types.fetch("bool")),
683
+ then_body: [
684
+ IR::ExpressionStmt.new(expression: IR::Call.new(callee: waiter_expr, arguments: [waiter_frame_expr], type: @ctx.types.fetch("void"))),
685
+ IR::ReturnStmt.new(value: nil),
686
+ ],
687
+ else_body: nil,
688
+ ),
689
+ IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "waiter_frame", runtime.fetch(:void_ptr)), operator: "=", value: waiter_frame_expr),
690
+ IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "waiter", runtime.fetch(:wake_type)), operator: "=", value: waiter_expr),
691
+ IR::ReturnStmt.new(value: nil),
692
+ ],
693
+ entry_point: false,
694
+ )
695
+ end
696
+
697
+ def build_event_wait_release_function(runtime)
698
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
699
+ raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
700
+
701
+ IR::Function.new(
702
+ name: "#{runtime.fetch(:wait_release_linkage_name)}_fn",
703
+ linkage_name: runtime.fetch(:wait_release_linkage_name),
704
+ params: [IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false)],
705
+ return_type: @ctx.types.fetch("void"),
706
+ body: [
707
+ IR::IfStmt.new(
708
+ condition: IR::Binary.new(
493
709
  operator: "==",
494
- left: current_slot_generation,
495
- right: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "generation", @ctx.types.fetch("ptr_uint")),
496
- type: @ctx.types.fetch("bool"),
497
- ),
498
- right: IR::Binary.new(
499
- operator: "!=",
500
- left: current_wait_frame,
710
+ left: raw_frame_expr,
501
711
  right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
502
712
  type: @ctx.types.fetch("bool"),
503
713
  ),
504
- type: @ctx.types.fetch("bool"),
714
+ then_body: [IR::ReturnStmt.new(value: nil)],
715
+ else_body: nil,
716
+ ),
717
+ IR::LocalDecl.new(
718
+ name: "__mt_wait_frame",
719
+ linkage_name: "__mt_wait_frame",
720
+ type: runtime.fetch(:wait_frame_pointer_type),
721
+ value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: raw_frame_expr, type: runtime.fetch(:wait_frame_pointer_type)),
505
722
  ),
506
- type: @ctx.types.fetch("bool"),
507
- )
508
-
509
- wait_result_value = event_wait_success_literal(runtime.fetch(:wait_result_type), payload_expr)
510
- waiter_frame_expr = wait_frame_field_expression(frame_pointer_expr, "waiter_frame", runtime.fetch(:void_ptr))
511
-
512
- dispatch_body = [
513
723
  IR::IfStmt.new(
514
- condition: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "wait_slot", @ctx.types.fetch("bool")),
724
+ condition: IR::Unary.new(operator: "not", operand: wait_frame_field_expression(frame_expr, "ready", @ctx.types.fetch("bool")), type: @ctx.types.fetch("bool")),
515
725
  then_body: [
516
- IR::LocalDecl.new(
517
- name: "__mt_slot",
518
- linkage_name: "__mt_slot",
519
- type: runtime.fetch(:slot_pointer_type),
520
- value: event_slot_pointer_expression(
521
- event_expr,
522
- snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "slot", @ctx.types.fetch("ptr_uint")),
726
+ IR::ExpressionStmt.new(
727
+ expression: event_unsubscribe_call(
523
728
  runtime,
729
+ IR::Cast.new(target_type: runtime.fetch(:event_pointer_type), expression: wait_frame_field_expression(frame_expr, "event", runtime.fetch(:void_ptr)), type: runtime.fetch(:event_pointer_type)),
730
+ wait_frame_field_expression(frame_expr, "subscription", @ctx.types.fetch("Subscription")),
524
731
  ),
525
732
  ),
526
- IR::IfStmt.new(
527
- condition: wait_slot_condition,
528
- then_body: [
529
- IR::LocalDecl.new(
530
- name: "__mt_wait_frame",
531
- linkage_name: "__mt_wait_frame",
532
- type: runtime.fetch(:wait_frame_pointer_type),
533
- value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: current_wait_frame, type: runtime.fetch(:wait_frame_pointer_type)),
534
- ),
535
- IR::ExpressionStmt.new(expression: event_unsubscribe_call(runtime, event_expr, snapshot_subscription_expr)),
536
- IR::Assignment.new(target: wait_frame_field_expression(frame_pointer_expr, "result", runtime.fetch(:wait_result_type)), operator: "=", value: wait_result_value),
537
- IR::Assignment.new(target: wait_frame_field_expression(frame_pointer_expr, "ready", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))),
538
- IR::IfStmt.new(
539
- condition: IR::Binary.new(
540
- operator: "!=",
541
- left: waiter_frame_expr,
542
- right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
543
- type: @ctx.types.fetch("bool"),
544
- ),
545
- then_body: [
546
- IR::LocalDecl.new(name: "__mt_waiter_frame", linkage_name: "__mt_waiter_frame", type: runtime.fetch(:void_ptr), value: waiter_frame_expr),
547
- IR::Assignment.new(target: waiter_frame_expr, operator: "=", value: IR::NullLiteral.new(type: runtime.fetch(:void_ptr))),
548
- IR::ExpressionStmt.new(
549
- expression: IR::Call.new(
550
- callee: wait_frame_field_expression(frame_pointer_expr, "waiter", runtime.fetch(:wake_type)),
551
- arguments: [IR::Name.new(name: "__mt_waiter_frame", type: runtime.fetch(:void_ptr), pointer: false)],
552
- type: @ctx.types.fetch("void"),
553
- ),
554
- ),
555
- ],
556
- else_body: nil,
557
- ),
558
- ],
559
- else_body: nil,
560
- ),
561
- ],
562
- else_body: [
563
- IR::IfStmt.new(
564
- condition: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "once", @ctx.types.fetch("bool")),
565
- then_body: [IR::ExpressionStmt.new(expression: event_unsubscribe_call(runtime, event_expr, snapshot_subscription_expr))],
566
- else_body: nil,
567
- ),
568
- IR::IfStmt.new(
569
- condition: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "stateful", @ctx.types.fetch("bool")),
570
- then_body: [
571
- IR::ExpressionStmt.new(expression: event_stateful_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)),
572
- ],
573
- else_body: [
574
- IR::ExpressionStmt.new(expression: event_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)),
575
- ],
576
- ),
577
733
  ],
734
+ else_body: nil,
578
735
  ),
579
- ]
580
-
581
- body = [
582
- IR::LocalDecl.new(name: "__mt_snapshots", linkage_name: "__mt_snapshots", type: runtime.fetch(:snapshots_type), value: IR::ZeroInit.new(type: runtime.fetch(:snapshots_type))),
583
- IR::LocalDecl.new(name: "__mt_snapshot_count", linkage_name: "__mt_snapshot_count", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
584
- IR::ForStmt.new(
585
- init: IR::LocalDecl.new(name: "__mt_slot_index", linkage_name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
586
- condition: IR::Binary.new(operator: "<", left: slot_index_expr, right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")), type: @ctx.types.fetch("bool")),
587
- post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
588
- body: collect_body,
736
+ IR::ExpressionStmt.new(expression: IR::Call.new(callee: "mt_async_free", arguments: [raw_frame_expr], type: @ctx.types.fetch("void"))),
737
+ IR::ReturnStmt.new(value: nil),
738
+ ],
739
+ entry_point: false,
740
+ )
741
+ end
742
+
743
+ def build_event_wait_take_result_function(runtime)
744
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
745
+ raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
746
+
747
+ IR::Function.new(
748
+ name: "#{runtime.fetch(:wait_take_result_linkage_name)}_fn",
749
+ linkage_name: runtime.fetch(:wait_take_result_linkage_name),
750
+ params: [IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false)],
751
+ return_type: runtime.fetch(:wait_result_type),
752
+ body: [
753
+ IR::IfStmt.new(
754
+ condition: IR::Binary.new(
755
+ operator: "==",
756
+ left: raw_frame_expr,
757
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
758
+ type: @ctx.types.fetch("bool"),
759
+ ),
760
+ then_body: [IR::ReturnStmt.new(value: event_failure_literal(runtime.fetch(:wait_result_type)))],
761
+ else_body: nil,
589
762
  ),
590
- IR::ForStmt.new(
591
- init: IR::LocalDecl.new(name: "__mt_dispatch_index", linkage_name: "__mt_dispatch_index", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
592
- condition: IR::Binary.new(operator: "<", left: dispatch_index_expr, right: snapshot_count_expr, type: @ctx.types.fetch("bool")),
593
- post: IR::Assignment.new(target: dispatch_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
594
- body: dispatch_body,
763
+ IR::LocalDecl.new(
764
+ name: "__mt_wait_frame",
765
+ linkage_name: "__mt_wait_frame",
766
+ type: runtime.fetch(:wait_frame_pointer_type),
767
+ value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false), type: runtime.fetch(:wait_frame_pointer_type)),
595
768
  ),
596
- IR::ReturnStmt.new(value: nil),
597
- ]
598
-
599
- params = [IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)]
600
- params << IR::Param.new(name: "payload", linkage_name: "payload", type: runtime.fetch(:event_type).payload_type, pointer: false) if runtime.fetch(:event_type).payload_type
601
-
602
- IR::Function.new(
603
- name: "#{runtime.fetch(:emit_linkage_name)}_fn",
604
- linkage_name: runtime.fetch(:emit_linkage_name),
605
- params:,
606
- return_type: @ctx.types.fetch("void"),
607
- body:,
608
- entry_point: false,
609
- )
610
- end
611
-
612
- def build_event_wait_ready_function(runtime)
613
- frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
614
- raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
615
-
616
- IR::Function.new(
617
- name: "#{runtime.fetch(:wait_ready_linkage_name)}_fn",
618
- linkage_name: runtime.fetch(:wait_ready_linkage_name),
619
- params: [IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false)],
620
- return_type: @ctx.types.fetch("bool"),
769
+ IR::ReturnStmt.new(value: wait_frame_field_expression(frame_expr, "result", runtime.fetch(:wait_result_type))),
770
+ ],
771
+ entry_point: false,
772
+ )
773
+ end
774
+
775
+ def build_event_wait_function(runtime)
776
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
777
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
778
+ raw_frame_expr = IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: frame_expr, type: runtime.fetch(:void_ptr))
779
+ slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
780
+ generation_expr = IR::Name.new(name: "__mt_generation", type: @ctx.types.fetch("ptr_uint"), pointer: false)
781
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
782
+
783
+ body = [
784
+ IR::ForStmt.new(
785
+ init: IR::LocalDecl.new(name: "__mt_slot_index", linkage_name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
786
+ condition: IR::Binary.new(operator: "<", left: slot_index_expr, right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")), type: @ctx.types.fetch("bool")),
787
+ post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
621
788
  body: [
622
- IR::IfStmt.new(
623
- condition: IR::Binary.new(
624
- operator: "==",
625
- left: raw_frame_expr,
626
- right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
627
- type: @ctx.types.fetch("bool"),
628
- ),
629
- then_body: [IR::ReturnStmt.new(value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool")))],
630
- else_body: nil,
789
+ IR::LocalDecl.new(name: "__mt_slot", linkage_name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), value: event_slot_pointer_expression(event_expr, slot_index_expr, runtime)),
790
+ active_event_slot_continue_guard(slot_pointer_expr),
791
+ IR::LocalDecl.new(
792
+ name: "__mt_generation",
793
+ linkage_name: "__mt_generation",
794
+ type: @ctx.types.fetch("ptr_uint"),
795
+ value: event_next_generation_expression(slot_pointer_expr),
631
796
  ),
632
797
  IR::LocalDecl.new(
633
798
  name: "__mt_wait_frame",
@@ -635,420 +800,253 @@ module MilkTea
635
800
  type: runtime.fetch(:wait_frame_pointer_type),
636
801
  value: IR::Cast.new(
637
802
  target_type: runtime.fetch(:wait_frame_pointer_type),
638
- expression: IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false),
803
+ expression: IR::Call.new(callee: "mt_async_alloc", arguments: [IR::SizeofExpr.new(target_type: runtime.fetch(:wait_frame_type), type: @ctx.types.fetch("ptr_uint"))], type: runtime.fetch(:void_ptr)),
639
804
  type: runtime.fetch(:wait_frame_pointer_type),
640
805
  ),
641
806
  ),
642
- IR::ReturnStmt.new(value: wait_frame_field_expression(frame_expr, "ready", @ctx.types.fetch("bool"))),
643
- ],
644
- entry_point: false,
645
- )
646
- end
647
-
648
- def build_event_wait_set_waiter_function(runtime)
649
- frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
650
- raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
651
- waiter_frame_expr = IR::Name.new(name: "waiter_frame", type: runtime.fetch(:void_ptr), pointer: false)
652
- waiter_expr = IR::Name.new(name: "waiter", type: runtime.fetch(:wake_type), pointer: false)
653
-
654
- IR::Function.new(
655
- name: "#{runtime.fetch(:wait_set_waiter_linkage_name)}_fn",
656
- linkage_name: runtime.fetch(:wait_set_waiter_linkage_name),
657
- params: [
658
- IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false),
659
- IR::Param.new(name: "waiter_frame", linkage_name: "waiter_frame", type: runtime.fetch(:void_ptr), pointer: false),
660
- IR::Param.new(name: "waiter", linkage_name: "waiter", type: runtime.fetch(:wake_type), pointer: false),
661
- ],
662
- return_type: @ctx.types.fetch("void"),
663
- body: [
664
- IR::IfStmt.new(
665
- condition: IR::Binary.new(
666
- operator: "==",
667
- left: raw_frame_expr,
668
- right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
669
- type: @ctx.types.fetch("bool"),
670
- ),
671
- then_body: [
672
- IR::ExpressionStmt.new(expression: IR::Call.new(callee: waiter_expr, arguments: [waiter_frame_expr], type: @ctx.types.fetch("void"))),
673
- IR::ReturnStmt.new(value: nil),
674
- ],
675
- else_body: nil,
676
- ),
677
- IR::LocalDecl.new(
678
- name: "__mt_wait_frame",
679
- linkage_name: "__mt_wait_frame",
680
- type: runtime.fetch(:wait_frame_pointer_type),
681
- value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false), type: runtime.fetch(:wait_frame_pointer_type)),
682
- ),
683
- IR::IfStmt.new(
684
- condition: wait_frame_field_expression(frame_expr, "ready", @ctx.types.fetch("bool")),
685
- then_body: [
686
- IR::ExpressionStmt.new(expression: IR::Call.new(callee: waiter_expr, arguments: [waiter_frame_expr], type: @ctx.types.fetch("void"))),
687
- IR::ReturnStmt.new(value: nil),
688
- ],
689
- else_body: nil,
690
- ),
691
- IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "waiter_frame", runtime.fetch(:void_ptr)), operator: "=", value: waiter_frame_expr),
692
- IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "waiter", runtime.fetch(:wake_type)), operator: "=", value: waiter_expr),
693
- IR::ReturnStmt.new(value: nil),
694
- ],
695
- entry_point: false,
696
- )
697
- end
698
-
699
- def build_event_wait_release_function(runtime)
700
- frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
701
- raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
702
-
703
- IR::Function.new(
704
- name: "#{runtime.fetch(:wait_release_linkage_name)}_fn",
705
- linkage_name: runtime.fetch(:wait_release_linkage_name),
706
- params: [IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false)],
707
- return_type: @ctx.types.fetch("void"),
708
- body: [
709
- IR::IfStmt.new(
710
- condition: IR::Binary.new(
711
- operator: "==",
712
- left: raw_frame_expr,
713
- right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
714
- type: @ctx.types.fetch("bool"),
715
- ),
716
- then_body: [IR::ReturnStmt.new(value: nil)],
717
- else_body: nil,
718
- ),
719
- IR::LocalDecl.new(
720
- name: "__mt_wait_frame",
721
- linkage_name: "__mt_wait_frame",
722
- type: runtime.fetch(:wait_frame_pointer_type),
723
- value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: raw_frame_expr, type: runtime.fetch(:wait_frame_pointer_type)),
807
+ IR::Assignment.new(
808
+ target: IR::Unary.new(operator: "*", operand: frame_expr, type: runtime.fetch(:wait_frame_type)),
809
+ operator: "=",
810
+ value: IR::ZeroInit.new(type: runtime.fetch(:wait_frame_type)),
724
811
  ),
725
- IR::IfStmt.new(
726
- condition: IR::Unary.new(operator: "not", operand: wait_frame_field_expression(frame_expr, "ready", @ctx.types.fetch("bool")), type: @ctx.types.fetch("bool")),
727
- then_body: [
728
- IR::ExpressionStmt.new(
729
- expression: event_unsubscribe_call(
730
- runtime,
731
- IR::Cast.new(target_type: runtime.fetch(:event_pointer_type), expression: wait_frame_field_expression(frame_expr, "event", runtime.fetch(:void_ptr)), type: runtime.fetch(:event_pointer_type)),
732
- wait_frame_field_expression(frame_expr, "subscription", @ctx.types.fetch("Subscription")),
733
- ),
734
- ),
735
- ],
736
- else_body: nil,
737
- ),
738
- IR::ExpressionStmt.new(expression: IR::Call.new(callee: "mt_async_free", arguments: [raw_frame_expr], type: @ctx.types.fetch("void"))),
739
- IR::ReturnStmt.new(value: nil),
740
- ],
741
- entry_point: false,
742
- )
743
- end
744
-
745
- def build_event_wait_take_result_function(runtime)
746
- frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
747
- raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
748
-
749
- IR::Function.new(
750
- name: "#{runtime.fetch(:wait_take_result_linkage_name)}_fn",
751
- linkage_name: runtime.fetch(:wait_take_result_linkage_name),
752
- params: [IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false)],
753
- return_type: runtime.fetch(:wait_result_type),
754
- body: [
755
- IR::IfStmt.new(
756
- condition: IR::Binary.new(
757
- operator: "==",
758
- left: raw_frame_expr,
759
- right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
760
- type: @ctx.types.fetch("bool"),
761
- ),
762
- then_body: [IR::ReturnStmt.new(value: event_failure_literal(runtime.fetch(:wait_result_type)))],
763
- else_body: nil,
764
- ),
765
- IR::LocalDecl.new(
766
- name: "__mt_wait_frame",
767
- linkage_name: "__mt_wait_frame",
768
- type: runtime.fetch(:wait_frame_pointer_type),
769
- value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false), type: runtime.fetch(:wait_frame_pointer_type)),
812
+ IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "event", runtime.fetch(:void_ptr)), operator: "=", value: IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: event_expr, type: runtime.fetch(:void_ptr))),
813
+ *event_slot_activate_statements(
814
+ slot_pointer_expr,
815
+ runtime,
816
+ generation_expr: generation_expr,
817
+ once: true,
818
+ wait_frame_expr: raw_frame_expr,
770
819
  ),
771
- IR::ReturnStmt.new(value: wait_frame_field_expression(frame_expr, "result", runtime.fetch(:wait_result_type))),
820
+ IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "subscription", @ctx.types.fetch("Subscription")), operator: "=", value: event_subscription_literal(slot_index_expr, generation_expr)),
821
+ IR::ReturnStmt.new(value: event_task_literal(runtime, frame_expr)),
772
822
  ],
773
- entry_point: false,
774
- )
775
- end
776
-
777
- def build_event_wait_function(runtime)
778
- event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
779
- frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
780
- raw_frame_expr = IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: frame_expr, type: runtime.fetch(:void_ptr))
781
- slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
782
- generation_expr = IR::Name.new(name: "__mt_generation", type: @ctx.types.fetch("ptr_uint"), pointer: false)
783
- slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
784
-
785
- body = [
786
- IR::ForStmt.new(
787
- init: IR::LocalDecl.new(name: "__mt_slot_index", linkage_name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
788
- condition: IR::Binary.new(operator: "<", left: slot_index_expr, right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")), type: @ctx.types.fetch("bool")),
789
- post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
790
- body: [
791
- IR::LocalDecl.new(name: "__mt_slot", linkage_name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), value: event_slot_pointer_expression(event_expr, slot_index_expr, runtime)),
792
- active_event_slot_continue_guard(slot_pointer_expr),
793
- IR::LocalDecl.new(
794
- name: "__mt_generation",
795
- linkage_name: "__mt_generation",
796
- type: @ctx.types.fetch("ptr_uint"),
797
- value: event_next_generation_expression(slot_pointer_expr),
798
- ),
799
- IR::LocalDecl.new(
800
- name: "__mt_wait_frame",
801
- linkage_name: "__mt_wait_frame",
802
- type: runtime.fetch(:wait_frame_pointer_type),
803
- value: IR::Cast.new(
804
- target_type: runtime.fetch(:wait_frame_pointer_type),
805
- expression: IR::Call.new(callee: "mt_async_alloc", arguments: [IR::SizeofExpr.new(target_type: runtime.fetch(:wait_frame_type), type: @ctx.types.fetch("ptr_uint"))], type: runtime.fetch(:void_ptr)),
806
- type: runtime.fetch(:wait_frame_pointer_type),
807
- ),
808
- ),
809
- IR::Assignment.new(
810
- target: IR::Unary.new(operator: "*", operand: frame_expr, type: runtime.fetch(:wait_frame_type)),
811
- operator: "=",
812
- value: IR::ZeroInit.new(type: runtime.fetch(:wait_frame_type)),
813
- ),
814
- IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "event", runtime.fetch(:void_ptr)), operator: "=", value: IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: event_expr, type: runtime.fetch(:void_ptr))),
815
- *event_slot_activate_statements(
816
- slot_pointer_expr,
817
- runtime,
818
- generation_expr: generation_expr,
819
- once: true,
820
- wait_frame_expr: raw_frame_expr,
821
- ),
822
- IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "subscription", @ctx.types.fetch("Subscription")), operator: "=", value: event_subscription_literal(slot_index_expr, generation_expr)),
823
- IR::ReturnStmt.new(value: event_task_literal(runtime, frame_expr)),
824
- ],
825
- ),
826
- IR::ReturnStmt.new(value: event_immediate_failure_task_literal(runtime)),
827
- ]
828
-
829
- IR::Function.new(
830
- name: "#{runtime.fetch(:wait_linkage_name)}_fn",
831
- linkage_name: runtime.fetch(:wait_linkage_name),
832
- params: [IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)],
833
- return_type: runtime.fetch(:task_type),
834
- body:,
835
- entry_point: false,
836
- )
837
- end
838
-
839
- def event_slot_pointer_expression(event_expr, slot_index_expr, runtime)
840
- IR::AddressOf.new(
841
- expression: IR::Index.new(
842
- receiver: IR::Member.new(receiver: event_expr, member: "slots", type: runtime.fetch(:slots_type)),
843
- index: slot_index_expr,
844
- type: runtime.fetch(:slot_type),
823
+ ),
824
+ IR::ReturnStmt.new(value: event_immediate_failure_task_literal(runtime)),
825
+ ]
826
+
827
+ IR::Function.new(
828
+ name: "#{runtime.fetch(:wait_linkage_name)}_fn",
829
+ linkage_name: runtime.fetch(:wait_linkage_name),
830
+ params: [IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)],
831
+ return_type: runtime.fetch(:task_type),
832
+ body:,
833
+ entry_point: false,
834
+ )
835
+ end
836
+
837
+ def event_slot_pointer_expression(event_expr, slot_index_expr, runtime)
838
+ IR::AddressOf.new(
839
+ expression: IR::Index.new(
840
+ receiver: IR::Member.new(receiver: event_expr, member: "slots", type: runtime.fetch(:slots_type)),
841
+ index: slot_index_expr,
842
+ type: runtime.fetch(:slot_type),
843
+ ),
844
+ type: runtime.fetch(:slot_pointer_type),
845
+ )
846
+ end
847
+
848
+ def event_slot_local_decl(event_expr, slot_index_expr, runtime, local_name: "__mt_slot")
849
+ IR::LocalDecl.new(
850
+ name: local_name,
851
+ linkage_name: local_name,
852
+ type: runtime.fetch(:slot_pointer_type),
853
+ value: event_slot_pointer_expression(event_expr, slot_index_expr, runtime),
854
+ )
855
+ end
856
+
857
+ def event_slot_active_expression(slot_pointer_expr)
858
+ event_slot_field_expression(slot_pointer_expr, "active", @ctx.types.fetch("bool"))
859
+ end
860
+
861
+ def event_slot_wait_frame_expression(slot_pointer_expr, runtime)
862
+ event_slot_field_expression(slot_pointer_expr, "wait_frame", runtime.fetch(:void_ptr))
863
+ end
864
+
865
+ def active_event_slot_continue_guard(slot_pointer_expr)
866
+ IR::IfStmt.new(
867
+ condition: event_slot_active_expression(slot_pointer_expr),
868
+ then_body: [IR::ContinueStmt.new],
869
+ else_body: nil,
870
+ )
871
+ end
872
+
873
+ def inactive_event_slot_continue_guard(slot_pointer_expr)
874
+ IR::IfStmt.new(
875
+ condition: IR::Unary.new(operator: "not", operand: event_slot_active_expression(slot_pointer_expr), type: @ctx.types.fetch("bool")),
876
+ then_body: [IR::ContinueStmt.new],
877
+ else_body: nil,
878
+ )
879
+ end
880
+
881
+ def event_next_generation_expression(slot_pointer_expr)
882
+ IR::Binary.new(
883
+ operator: "+",
884
+ left: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")),
885
+ right: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint")),
886
+ type: @ctx.types.fetch("ptr_uint"),
887
+ )
888
+ end
889
+
890
+ def event_slot_activate_statements(slot_pointer_expr, runtime, generation_expr:, once:, wait_frame_expr:, listener_expr: nil)
891
+ statements = [
892
+ IR::Assignment.new(target: event_slot_active_expression(slot_pointer_expr), operator: "=", value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))),
893
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: once, type: @ctx.types.fetch("bool"))),
894
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")), operator: "=", value: generation_expr),
895
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr)), operator: "=", value: IR::NullLiteral.new(type: runtime.fetch(:void_ptr))),
896
+ ]
897
+ statements << IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "listener", runtime.fetch(:listener_type)), operator: "=", value: listener_expr) if listener_expr
898
+ statements << IR::Assignment.new(target: event_slot_wait_frame_expression(slot_pointer_expr, runtime), operator: "=", value: wait_frame_expr)
899
+ statements
900
+ end
901
+
902
+ def event_slot_activate_stateful_statements(slot_pointer_expr, runtime, generation_expr:, once:, state_expr:, wait_frame_expr:, listener_expr: nil)
903
+ statements = [
904
+ IR::Assignment.new(target: event_slot_active_expression(slot_pointer_expr), operator: "=", value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))),
905
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: once, type: @ctx.types.fetch("bool"))),
906
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")), operator: "=", value: generation_expr),
907
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr)), operator: "=", value: state_expr),
908
+ ]
909
+ statements << IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "listener", runtime.fetch(:listener_type)), operator: "=", value: listener_expr) if listener_expr
910
+ statements << IR::Assignment.new(target: event_slot_wait_frame_expression(slot_pointer_expr, runtime), operator: "=", value: wait_frame_expr)
911
+ statements
912
+ end
913
+
914
+ def event_slot_clear_statements(slot_pointer_expr, runtime)
915
+ [
916
+ IR::Assignment.new(target: event_slot_active_expression(slot_pointer_expr), operator: "=", value: IR::BooleanLiteral.new(value: false, type: @ctx.types.fetch("bool"))),
917
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: false, type: @ctx.types.fetch("bool"))),
918
+ IR::Assignment.new(target: event_slot_wait_frame_expression(slot_pointer_expr, runtime), operator: "=", value: IR::NullLiteral.new(type: runtime.fetch(:void_ptr))),
919
+ ]
920
+ end
921
+
922
+ def event_slot_field_expression(slot_pointer_expr, field_name, field_type)
923
+ IR::Member.new(receiver: slot_pointer_expr, member: field_name, type: field_type)
924
+ end
925
+
926
+ def snapshot_field_expression(snapshots_expr, index_expr, runtime, field_name, field_type)
927
+ IR::Member.new(
928
+ receiver: IR::Index.new(receiver: snapshots_expr, index: index_expr, type: runtime.fetch(:snapshot_type)),
929
+ member: field_name,
930
+ type: field_type,
931
+ )
932
+ end
933
+
934
+ def subscription_field_expression(subscription_expr, field_name, field_type)
935
+ IR::Member.new(receiver: subscription_expr, member: field_name, type: field_type)
936
+ end
937
+
938
+ def wait_frame_field_expression(frame_expr, field_name, field_type)
939
+ IR::Member.new(receiver: frame_expr, member: field_name, type: field_type)
940
+ end
941
+
942
+ def event_subscription_literal(slot_expr, generation_expr)
943
+ IR::AggregateLiteral.new(
944
+ type: @ctx.types.fetch("Subscription"),
945
+ fields: [
946
+ IR::AggregateField.new(name: "slot", value: slot_expr),
947
+ IR::AggregateField.new(name: "generation", value: generation_expr),
948
+ ],
949
+ )
950
+ end
951
+
952
+ def event_subscription_success_literal(result_type, slot_expr, generation_expr)
953
+ IR::VariantLiteral.new(
954
+ type: result_type,
955
+ arm_name: "success",
956
+ fields: [IR::AggregateField.new(name: "value", value: event_subscription_literal(slot_expr, generation_expr))],
957
+ )
958
+ end
959
+
960
+ def event_wait_success_literal(result_type, payload_expr)
961
+ IR::VariantLiteral.new(
962
+ type: result_type,
963
+ arm_name: "success",
964
+ fields: [IR::AggregateField.new(name: "value", value: payload_expr || void_value_expression)],
965
+ )
966
+ end
967
+
968
+ def event_failure_literal(result_type)
969
+ IR::VariantLiteral.new(
970
+ type: result_type,
971
+ arm_name: "failure",
972
+ fields: [
973
+ IR::AggregateField.new(
974
+ name: "error",
975
+ value: IR::Name.new(name: enum_member_c_name(@ctx.types.fetch("EventError"), "full"), type: @ctx.types.fetch("EventError"), pointer: false),
845
976
  ),
846
- type: runtime.fetch(:slot_pointer_type),
847
- )
848
- end
849
-
850
- def event_slot_local_decl(event_expr, slot_index_expr, runtime, local_name: "__mt_slot")
851
- IR::LocalDecl.new(
852
- name: local_name,
853
- linkage_name: local_name,
854
- type: runtime.fetch(:slot_pointer_type),
855
- value: event_slot_pointer_expression(event_expr, slot_index_expr, runtime),
856
- )
857
- end
858
-
859
- def event_slot_active_expression(slot_pointer_expr)
860
- event_slot_field_expression(slot_pointer_expr, "active", @ctx.types.fetch("bool"))
861
- end
862
-
863
- def event_slot_wait_frame_expression(slot_pointer_expr, runtime)
864
- event_slot_field_expression(slot_pointer_expr, "wait_frame", runtime.fetch(:void_ptr))
865
- end
866
-
867
- def active_event_slot_continue_guard(slot_pointer_expr)
868
- IR::IfStmt.new(
869
- condition: event_slot_active_expression(slot_pointer_expr),
870
- then_body: [IR::ContinueStmt.new],
871
- else_body: nil,
872
- )
873
- end
874
-
875
- def inactive_event_slot_continue_guard(slot_pointer_expr)
876
- IR::IfStmt.new(
877
- condition: IR::Unary.new(operator: "not", operand: event_slot_active_expression(slot_pointer_expr), type: @ctx.types.fetch("bool")),
878
- then_body: [IR::ContinueStmt.new],
879
- else_body: nil,
880
- )
881
- end
882
-
883
- def event_next_generation_expression(slot_pointer_expr)
884
- IR::Binary.new(
885
- operator: "+",
886
- left: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")),
887
- right: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint")),
888
- type: @ctx.types.fetch("ptr_uint"),
889
- )
890
- end
891
-
892
- def event_slot_activate_statements(slot_pointer_expr, runtime, generation_expr:, once:, wait_frame_expr:, listener_expr: nil)
893
- statements = [
894
- IR::Assignment.new(target: event_slot_active_expression(slot_pointer_expr), operator: "=", value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))),
895
- IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: once, type: @ctx.types.fetch("bool"))),
896
- IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")), operator: "=", value: generation_expr),
897
- IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr)), operator: "=", value: IR::NullLiteral.new(type: runtime.fetch(:void_ptr))),
898
- ]
899
- statements << IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "listener", runtime.fetch(:listener_type)), operator: "=", value: listener_expr) if listener_expr
900
- statements << IR::Assignment.new(target: event_slot_wait_frame_expression(slot_pointer_expr, runtime), operator: "=", value: wait_frame_expr)
901
- statements
902
- end
903
-
904
- def event_slot_activate_stateful_statements(slot_pointer_expr, runtime, generation_expr:, once:, state_expr:, wait_frame_expr:, listener_expr: nil)
905
- statements = [
906
- IR::Assignment.new(target: event_slot_active_expression(slot_pointer_expr), operator: "=", value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))),
907
- IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: once, type: @ctx.types.fetch("bool"))),
908
- IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")), operator: "=", value: generation_expr),
909
- IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr)), operator: "=", value: state_expr),
910
- ]
911
- statements << IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "listener", runtime.fetch(:listener_type)), operator: "=", value: listener_expr) if listener_expr
912
- statements << IR::Assignment.new(target: event_slot_wait_frame_expression(slot_pointer_expr, runtime), operator: "=", value: wait_frame_expr)
913
- statements
914
- end
915
-
916
- def event_slot_clear_statements(slot_pointer_expr, runtime)
917
- [
918
- IR::Assignment.new(target: event_slot_active_expression(slot_pointer_expr), operator: "=", value: IR::BooleanLiteral.new(value: false, type: @ctx.types.fetch("bool"))),
919
- IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: false, type: @ctx.types.fetch("bool"))),
920
- IR::Assignment.new(target: event_slot_wait_frame_expression(slot_pointer_expr, runtime), operator: "=", value: IR::NullLiteral.new(type: runtime.fetch(:void_ptr))),
921
- ]
922
- end
923
-
924
- def event_slot_field_expression(slot_pointer_expr, field_name, field_type)
925
- IR::Member.new(receiver: slot_pointer_expr, member: field_name, type: field_type)
926
- end
927
-
928
- def snapshot_field_expression(snapshots_expr, index_expr, runtime, field_name, field_type)
929
- IR::Member.new(
930
- receiver: IR::Index.new(receiver: snapshots_expr, index: index_expr, type: runtime.fetch(:snapshot_type)),
931
- member: field_name,
932
- type: field_type,
933
- )
934
- end
935
-
936
- def subscription_field_expression(subscription_expr, field_name, field_type)
937
- IR::Member.new(receiver: subscription_expr, member: field_name, type: field_type)
938
- end
939
-
940
- def wait_frame_field_expression(frame_expr, field_name, field_type)
941
- IR::Member.new(receiver: frame_expr, member: field_name, type: field_type)
942
- end
943
-
944
- def event_subscription_literal(slot_expr, generation_expr)
945
- IR::AggregateLiteral.new(
946
- type: @ctx.types.fetch("Subscription"),
947
- fields: [
948
- IR::AggregateField.new(name: "slot", value: slot_expr),
949
- IR::AggregateField.new(name: "generation", value: generation_expr),
950
- ],
951
- )
952
- end
953
-
954
- def event_subscription_success_literal(result_type, slot_expr, generation_expr)
955
- IR::VariantLiteral.new(
956
- type: result_type,
957
- arm_name: "success",
958
- fields: [IR::AggregateField.new(name: "value", value: event_subscription_literal(slot_expr, generation_expr))],
959
- )
960
- end
961
-
962
- def event_wait_success_literal(result_type, payload_expr)
963
- IR::VariantLiteral.new(
964
- type: result_type,
965
- arm_name: "success",
966
- fields: [IR::AggregateField.new(name: "value", value: payload_expr || void_value_expression)],
967
- )
968
- end
969
-
970
- def event_failure_literal(result_type)
971
- IR::VariantLiteral.new(
972
- type: result_type,
973
- arm_name: "failure",
974
- fields: [
975
- IR::AggregateField.new(
976
- name: "error",
977
- value: IR::Name.new(name: enum_member_c_name(@ctx.types.fetch("EventError"), "full"), type: @ctx.types.fetch("EventError"), pointer: false),
978
- ),
979
- ],
980
- )
981
- end
982
-
983
- def void_value_expression
984
- IR::Cast.new(
985
- target_type: @ctx.types.fetch("void"),
986
- expression: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("int")),
987
- type: @ctx.types.fetch("void"),
988
- )
989
- end
990
-
991
- def event_unsubscribe_call(runtime, event_expr, subscription_expr)
992
- IR::Call.new(
993
- callee: runtime.fetch(:unsubscribe_linkage_name),
994
- arguments: [event_expr, subscription_expr],
995
- type: @ctx.types.fetch("void"),
996
- )
997
- end
998
-
999
- def event_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)
1000
- listener_type = runtime.fetch(:listener_type)
1001
- listener_expr = IR::Cast.new(
1002
- target_type: listener_type,
1003
- expression: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "listener", runtime.fetch(:void_ptr)),
1004
- type: listener_type,
1005
- )
1006
- arguments = []
1007
- arguments << payload_expr if runtime.fetch(:event_type).payload_type
1008
- IR::Call.new(
1009
- callee: listener_expr,
1010
- arguments:,
1011
- type: @ctx.types.fetch("void"),
1012
- )
1013
- end
1014
-
1015
- def event_stateful_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)
1016
- listener_type = runtime.fetch(:stateful_listener_type)
1017
- listener_expr = IR::Cast.new(
1018
- target_type: listener_type,
1019
- expression: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "listener", runtime.fetch(:void_ptr)),
1020
- type: listener_type,
1021
- )
1022
- state_expr = snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "state", runtime.fetch(:void_ptr))
1023
- arguments = [state_expr]
1024
- arguments << payload_expr if runtime.fetch(:event_type).payload_type
1025
- IR::Call.new(
1026
- callee: listener_expr,
1027
- arguments:,
1028
- type: @ctx.types.fetch("void"),
1029
- )
1030
- end
1031
-
1032
- def event_task_literal(runtime, frame_expr)
1033
- raw_frame_expr = IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: frame_expr, type: runtime.fetch(:void_ptr))
1034
- event_task_literal_from_raw_frame(runtime, raw_frame_expr)
1035
- end
1036
-
1037
- def event_immediate_failure_task_literal(runtime)
1038
- event_task_literal_from_raw_frame(runtime, IR::NullLiteral.new(type: runtime.fetch(:void_ptr)))
1039
- end
1040
-
1041
- def event_task_literal_from_raw_frame(runtime, raw_frame_expr)
1042
- IR::AggregateLiteral.new(
1043
- type: runtime.fetch(:task_type),
1044
- fields: [
1045
- IR::AggregateField.new(name: "frame", value: raw_frame_expr),
1046
- IR::AggregateField.new(name: "ready", value: IR::Name.new(name: runtime.fetch(:wait_ready_linkage_name), type: runtime.fetch(:task_type).field("ready"), pointer: false)),
1047
- IR::AggregateField.new(name: "set_waiter", value: IR::Name.new(name: runtime.fetch(:wait_set_waiter_linkage_name), type: runtime.fetch(:task_type).field("set_waiter"), pointer: false)),
1048
- IR::AggregateField.new(name: "release", value: IR::Name.new(name: runtime.fetch(:wait_release_linkage_name), type: runtime.fetch(:task_type).field("release"), pointer: false)),
1049
- IR::AggregateField.new(name: "take_result", value: IR::Name.new(name: runtime.fetch(:wait_take_result_linkage_name), type: runtime.fetch(:task_type).field("take_result"), pointer: false)),
1050
- ],
1051
- )
1052
- end
977
+ ],
978
+ )
979
+ end
980
+
981
+ def void_value_expression
982
+ IR::Cast.new(
983
+ target_type: @ctx.types.fetch("void"),
984
+ expression: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("int")),
985
+ type: @ctx.types.fetch("void"),
986
+ )
987
+ end
988
+
989
+ def event_unsubscribe_call(runtime, event_expr, subscription_expr)
990
+ IR::Call.new(
991
+ callee: runtime.fetch(:unsubscribe_linkage_name),
992
+ arguments: [event_expr, subscription_expr],
993
+ type: @ctx.types.fetch("void"),
994
+ )
995
+ end
996
+
997
+ def event_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)
998
+ listener_type = runtime.fetch(:listener_type)
999
+ listener_expr = IR::Cast.new(
1000
+ target_type: listener_type,
1001
+ expression: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "listener", runtime.fetch(:void_ptr)),
1002
+ type: listener_type,
1003
+ )
1004
+ arguments = []
1005
+ arguments << payload_expr if runtime.fetch(:event_type).payload_type
1006
+ IR::Call.new(
1007
+ callee: listener_expr,
1008
+ arguments:,
1009
+ type: @ctx.types.fetch("void"),
1010
+ )
1011
+ end
1012
+
1013
+ def event_stateful_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)
1014
+ listener_type = runtime.fetch(:stateful_listener_type)
1015
+ listener_expr = IR::Cast.new(
1016
+ target_type: listener_type,
1017
+ expression: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "listener", runtime.fetch(:void_ptr)),
1018
+ type: listener_type,
1019
+ )
1020
+ state_expr = snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "state", runtime.fetch(:void_ptr))
1021
+ arguments = [state_expr]
1022
+ arguments << payload_expr if runtime.fetch(:event_type).payload_type
1023
+ IR::Call.new(
1024
+ callee: listener_expr,
1025
+ arguments:,
1026
+ type: @ctx.types.fetch("void"),
1027
+ )
1028
+ end
1029
+
1030
+ def event_task_literal(runtime, frame_expr)
1031
+ raw_frame_expr = IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: frame_expr, type: runtime.fetch(:void_ptr))
1032
+ event_task_literal_from_raw_frame(runtime, raw_frame_expr)
1033
+ end
1034
+
1035
+ def event_immediate_failure_task_literal(runtime)
1036
+ event_task_literal_from_raw_frame(runtime, IR::NullLiteral.new(type: runtime.fetch(:void_ptr)))
1037
+ end
1038
+
1039
+ def event_task_literal_from_raw_frame(runtime, raw_frame_expr)
1040
+ IR::AggregateLiteral.new(
1041
+ type: runtime.fetch(:task_type),
1042
+ fields: [
1043
+ IR::AggregateField.new(name: "frame", value: raw_frame_expr),
1044
+ IR::AggregateField.new(name: "ready", value: IR::Name.new(name: runtime.fetch(:wait_ready_linkage_name), type: runtime.fetch(:task_type).field("ready"), pointer: false)),
1045
+ IR::AggregateField.new(name: "set_waiter", value: IR::Name.new(name: runtime.fetch(:wait_set_waiter_linkage_name), type: runtime.fetch(:task_type).field("set_waiter"), pointer: false)),
1046
+ IR::AggregateField.new(name: "release", value: IR::Name.new(name: runtime.fetch(:wait_release_linkage_name), type: runtime.fetch(:task_type).field("release"), pointer: false)),
1047
+ IR::AggregateField.new(name: "take_result", value: IR::Name.new(name: runtime.fetch(:wait_take_result_linkage_name), type: runtime.fetch(:task_type).field("take_result"), pointer: false)),
1048
+ ],
1049
+ )
1050
+ end
1053
1051
  end
1054
1052
  end