Module: MilkTea::CBackend::Reinterpret
- Included in:
- MilkTea::CBackend
- Defined in:
- lib/milk_tea/core/c_backend/reinterpret.rb
Instance Method Summary collapse
- #c_operator(operator) ⇒ Object
- #callable_container_element_type?(type) ⇒ Boolean
- #checked_array_index_helper_name(type) ⇒ Object
- #checked_span_index_helper_name(type) ⇒ Object
- #collect_reinterpret_helpers ⇒ Object
- #collect_reinterpret_helpers_from_expression(expression, helpers, seen) ⇒ Object
- #collect_reinterpret_helpers_from_statements(statements, helpers, seen) ⇒ Object
- #emit_reinterpret_helper(expression) ⇒ Object
- #no_op_cast?(expression) ⇒ Boolean
- #no_op_reinterpret?(target_type, source_type) ⇒ Boolean
- #nullable_array_index_helper_name(type) ⇒ Object
- #nullable_pointer_like_ir_type?(type) ⇒ Boolean
- #nullable_span_index_helper_name(type) ⇒ Object
- #pointer_member_receiver?(expression) ⇒ Boolean
- #reinterpret_helper_name(target_type, source_type) ⇒ Object
- #variant_arm_payload_field_type(member_expr) ⇒ Object
- #void_type ⇒ Object
- #wrap_index_receiver(expression) ⇒ Object
- #wrap_member_receiver(expression) ⇒ Object
- #wrap_pointer_member_receiver(expression) ⇒ Object
Instance Method Details
#c_operator(operator) ⇒ Object
231 232 233 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 231 def c_operator(operator) operator == "and" ? "&&" : operator == "or" ? "||" : operator end |
#callable_container_element_type?(type) ⇒ Boolean
153 154 155 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 153 def callable_container_element_type?(type) type.is_a?(Types::Function) || type.is_a?(Types::Proc) end |
#checked_array_index_helper_name(type) ⇒ Object
129 130 131 132 133 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 129 def checked_array_index_helper_name(type) return "mt_checked_index_array_#{sanitize_identifier(c_declaration(array_element_type(type), 'value'))}_#{array_length(type)}" if array_type?(type) && callable_container_element_type?(array_element_type(type)) "mt_checked_index_#{sanitize_identifier(type.to_s)}" end |
#checked_span_index_helper_name(type) ⇒ Object
135 136 137 138 139 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 135 def checked_span_index_helper_name(type) return "mt_checked_span_index_#{sanitize_identifier(c_declaration(type.element_type, 'value'))}" if callable_container_element_type?(type.element_type) "mt_checked_span_index_#{sanitize_identifier(type.to_s)}" end |
#collect_reinterpret_helpers ⇒ Object
6 7 8 9 10 11 12 13 14 15 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 6 def collect_reinterpret_helpers helpers = [] seen = {} emitted_functions.each do |function| collect_reinterpret_helpers_from_statements(function.body, helpers, seen) end helpers end |
#collect_reinterpret_helpers_from_expression(expression, helpers, seen) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 55 def collect_reinterpret_helpers_from_expression(expression, helpers, seen) case expression when IR::Member collect_reinterpret_helpers_from_expression(expression.receiver, helpers, seen) when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex collect_reinterpret_helpers_from_expression(expression.receiver, helpers, seen) collect_reinterpret_helpers_from_expression(expression.index, helpers, seen) when IR::Call collect_reinterpret_helpers_from_expression(expression.callee, helpers, seen) unless expression.callee.is_a?(String) expression.arguments.each { |argument| collect_reinterpret_helpers_from_expression(argument, helpers, seen) } when IR::Unary collect_reinterpret_helpers_from_expression(expression.operand, helpers, seen) when IR::Binary collect_reinterpret_helpers_from_expression(expression.left, helpers, seen) collect_reinterpret_helpers_from_expression(expression.right, helpers, seen) when IR::Conditional collect_reinterpret_helpers_from_expression(expression.condition, helpers, seen) collect_reinterpret_helpers_from_expression(expression.then_expression, helpers, seen) collect_reinterpret_helpers_from_expression(expression.else_expression, helpers, seen) when IR::ReinterpretExpr return if no_op_reinterpret?(expression.target_type, expression.source_type) key = [expression.target_type, expression.source_type] unless seen[key] helpers << expression seen[key] = true end collect_reinterpret_helpers_from_expression(expression.expression, helpers, seen) when IR::AddressOf collect_reinterpret_helpers_from_expression(expression.expression, helpers, seen) when IR::Cast collect_reinterpret_helpers_from_expression(expression.expression, helpers, seen) when IR::AggregateLiteral expression.fields.each { |field| collect_reinterpret_helpers_from_expression(field.value, helpers, seen) } when IR::ArrayLiteral expression.elements.each { |element| collect_reinterpret_helpers_from_expression(element, helpers, seen) } when IR::VariantLiteral expression.fields.each { |field| collect_reinterpret_helpers_from_expression(field.value, helpers, seen) } when IR::ZeroInit, IR::IntegerLiteral, IR::FloatLiteral, IR::StringLiteral, IR::BooleanLiteral, IR::NullLiteral, IR::Name, IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr nil end end |
#collect_reinterpret_helpers_from_statements(statements, helpers, seen) ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 17 def collect_reinterpret_helpers_from_statements(statements, helpers, seen) statements.each do |statement| case statement when IR::LocalDecl collect_reinterpret_helpers_from_expression(statement.value, helpers, seen) when IR::Assignment collect_reinterpret_helpers_from_expression(statement.target, helpers, seen) collect_reinterpret_helpers_from_expression(statement.value, helpers, seen) when IR::BlockStmt collect_reinterpret_helpers_from_statements(statement.body, helpers, seen) when IR::WhileStmt collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen) collect_reinterpret_helpers_from_statements(statement.body, helpers, seen) when IR::ForStmt collect_reinterpret_helpers_from_statements([statement.init], helpers, seen) collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen) collect_reinterpret_helpers_from_statements(statement.body, helpers, seen) collect_reinterpret_helpers_from_statements([statement.post], helpers, seen) when IR::IfStmt collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen) collect_reinterpret_helpers_from_statements(statement.then_body, helpers, seen) collect_reinterpret_helpers_from_statements(statement.else_body, helpers, seen) if statement.else_body when IR::SwitchStmt collect_reinterpret_helpers_from_expression(statement.expression, helpers, seen) statement.cases.each do |switch_case| collect_reinterpret_helpers_from_statements(switch_case.body, helpers, seen) end when IR::StaticAssert collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen) collect_reinterpret_helpers_from_expression(statement., helpers, seen) when IR::ReturnStmt collect_reinterpret_helpers_from_expression(statement.value, helpers, seen) if statement.value when IR::ExpressionStmt collect_reinterpret_helpers_from_expression(statement.expression, helpers, seen) end end end |
#emit_reinterpret_helper(expression) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 98 def emit_reinterpret_helper(expression) helper_name = reinterpret_helper_name(expression.target_type, expression.source_type) params = c_declaration(expression.source_type, 'value') [ "static inline #{c_function_declaration(expression.target_type, helper_name, params)} {", "#{INDENT}_Static_assert(sizeof(#{layout_type_expression(expression.target_type)}) == sizeof(#{layout_type_expression(expression.source_type)}), \"reinterpret requires equal sizes\");", "#{INDENT}#{c_declaration(expression.target_type, 'result')};", "#{INDENT}memcpy(&result, &value, sizeof(result));", "#{INDENT}return result;", "}", ] end |
#no_op_cast?(expression) ⇒ Boolean
115 116 117 118 119 120 121 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 115 def no_op_cast?(expression) return false if expression.expression.type.is_a?(Types::Null) c_type(expression.target_type) == c_type(expression.expression.type) rescue StandardError false end |
#no_op_reinterpret?(target_type, source_type) ⇒ Boolean
123 124 125 126 127 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 123 def no_op_reinterpret?(target_type, source_type) c_type(target_type) == c_type(source_type) rescue StandardError false end |
#nullable_array_index_helper_name(type) ⇒ Object
141 142 143 144 145 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 141 def nullable_array_index_helper_name(type) return "mt_nullable_index_array_#{sanitize_identifier(c_declaration(array_element_type(type), 'value'))}_#{array_length(type)}" if array_type?(type) && callable_container_element_type?(array_element_type(type)) "mt_nullable_index_#{sanitize_identifier(type.to_s)}" end |
#nullable_pointer_like_ir_type?(type) ⇒ Boolean
199 200 201 202 203 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 199 def nullable_pointer_like_ir_type?(type) return false unless type.is_a?(Types::Nullable) c_backend_pointer_like_type?(type.base) end |
#nullable_span_index_helper_name(type) ⇒ Object
147 148 149 150 151 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 147 def nullable_span_index_helper_name(type) return "mt_nullable_span_index_#{sanitize_identifier(c_declaration(type.element_type, 'value'))}" if callable_container_element_type?(type.element_type) "mt_nullable_span_index_#{sanitize_identifier(type.to_s)}" end |
#pointer_member_receiver?(expression) ⇒ Boolean
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 174 def pointer_member_receiver?(expression) return true if checked_index_alias(expression) return pointer_member_receiver?(expression.operand) if expression.is_a?(IR::Unary) && expression.operator == "*" if expression.is_a?(IR::Member) field_type = variant_arm_payload_field_type(expression) if field_type && expression.receiver.type.is_a?(Types::VariantArmPayload) parent_c = named_type_c_name(expression.receiver.type.variant_type) return true if aggregate_field_creates_cycle?(field_type, parent_c) end end (expression.is_a?(IR::Name) && expression.pointer) || (expression.respond_to?(:type) && (raw_pointer_type?(expression.type) || ref_type?(expression.type) || nullable_pointer_like_ir_type?(expression.type))) end |
#reinterpret_helper_name(target_type, source_type) ⇒ Object
111 112 113 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 111 def reinterpret_helper_name(target_type, source_type) "mt_reinterpret_#{sanitize_identifier(target_type.to_s)}_from_#{sanitize_identifier(source_type.to_s)}" end |
#variant_arm_payload_field_type(member_expr) ⇒ Object
190 191 192 193 194 195 196 197 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 190 def variant_arm_payload_field_type(member_expr) receiver_type = member_expr.receiver.type return nil unless receiver_type.is_a?(Types::VariantArmPayload) arm_name = receiver_type.arm_name variant_type = receiver_type.variant_type variant_type.arm(arm_name)&.fetch(member_expr.member) end |
#void_type ⇒ Object
235 236 237 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 235 def void_type @void_type ||= Types::Registry.primitive("void") end |
#wrap_index_receiver(expression) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 216 def wrap_index_receiver(expression) case expression when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex if (alias_name = checked_index_alias(expression)) "(*#{alias_name})" else emit_expression(expression) end when IR::Name, IR::Member, IR::Index, IR::Call emit_expression(expression) else "(#{emit_expression(expression)})" end end |
#wrap_member_receiver(expression) ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 157 def wrap_member_receiver(expression) case expression when IR::Unary if expression.operator == "*" wrap_pointer_member_receiver(expression.operand) else "(#{emit_expression(expression)})" end when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex checked_index_alias(expression) || emit_expression(expression) when IR::Name, IR::Member, IR::Index emit_expression(expression) else "(#{emit_expression(expression)})" end end |
#wrap_pointer_member_receiver(expression) ⇒ Object
205 206 207 208 209 210 211 212 213 214 |
# File 'lib/milk_tea/core/c_backend/reinterpret.rb', line 205 def wrap_pointer_member_receiver(expression) case expression when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex checked_index_alias(expression) || emit_expression(expression) when IR::Name, IR::Member, IR::Index, IR::Call emit_expression(expression) else "(#{emit_expression(expression)})" end end |