@@ -572,12 +572,8 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
572
572
let output_value_type =
573
573
self . index . get_type_information_or_void ( parameter. get_type_name ( ) ) ;
574
574
575
- //Special string handling
576
- if ( assigned_output_type. is_string ( ) && output_value_type. is_string ( ) )
577
- || ( assigned_output_type. is_struct ( ) && output_value_type. is_struct ( ) )
578
- || ( assigned_output_type. is_array ( ) && output_value_type. is_array ( ) )
579
- {
580
- self . generate_string_store (
575
+ if assigned_output_type. is_aggregate ( ) && output_value_type. is_aggregate ( ) {
576
+ self . build_memcpy (
581
577
assigned_output,
582
578
assigned_output_type,
583
579
expression. get_location ( ) ,
@@ -2185,55 +2181,26 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
2185
2181
let right_type =
2186
2182
self . annotations . get_type_or_void ( right_statement, self . index ) . get_type_information ( ) ;
2187
2183
2188
- //Special string handling
2189
- if left_type. is_string ( ) && right_type. is_string ( )
2190
- //string-literals are also generated as global constant variables so we can always assume that
2191
- //we have a pointer-value
2192
- {
2184
+ // redirect aggregate types
2185
+ if left_type. is_aggregate ( ) && right_type. is_aggregate ( ) {
2193
2186
let right =
2194
- self . generate_expression_value ( right_statement) . map ( |expr_value| match expr_value {
2195
- ExpressionValue :: LValue ( ptr) => ptr,
2196
- ExpressionValue :: RValue ( _) => unreachable ! (
2197
- "strings should be lvalues: {:?}, {:?}" ,
2198
- right_statement. get_location( ) ,
2199
- right_statement
2200
- ) ,
2201
- } ) ?;
2202
- self . generate_string_store (
2187
+ self . generate_expression_value ( right_statement) ?. get_basic_value_enum ( ) . into_pointer_value ( ) ;
2188
+ self . build_memcpy (
2203
2189
left,
2204
2190
left_type,
2205
2191
right_statement. get_location ( ) ,
2206
2192
right,
2207
2193
right_type,
2208
2194
right_statement. get_location ( ) ,
2209
2195
) ?;
2210
- } else if ( left_type. is_struct ( ) && right_type. is_struct ( ) )
2211
- || ( left_type. is_array ( ) && right_type. is_array ( ) )
2212
- {
2213
- //memcopy right_statement into left
2214
- let expression =
2215
- self . generate_expression_value ( right_statement) ?. get_basic_value_enum ( ) . into_pointer_value ( ) ;
2216
-
2217
- let size =
2218
- self . llvm_index . get_associated_type ( right_type. get_name ( ) ) ?. size_of ( ) . ok_or_else ( || {
2219
- Diagnostic :: codegen_error (
2220
- format ! ( "Unknown size of type {}." , right_type. get_name( ) ) . as_str ( ) ,
2221
- right_statement. get_location ( ) ,
2222
- )
2223
- } ) ?;
2224
-
2225
- self . llvm
2226
- . builder
2227
- . build_memcpy ( left, 1 , expression, 1 , size)
2228
- . map_err ( |err| Diagnostic :: codegen_error ( err, right_statement. get_location ( ) ) ) ?;
2229
2196
} else {
2230
2197
let expression = self . generate_expression ( right_statement) ?;
2231
2198
self . llvm . builder . build_store ( left, expression) ;
2232
2199
}
2233
2200
Ok ( ( ) )
2234
2201
}
2235
2202
2236
- pub fn generate_string_store (
2203
+ fn build_memcpy (
2237
2204
& self ,
2238
2205
left : inkwell:: values:: PointerValue < ' ink > ,
2239
2206
left_type : & DataTypeInformation ,
@@ -2242,35 +2209,45 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
2242
2209
right_type : & DataTypeInformation ,
2243
2210
right_location : SourceLocation ,
2244
2211
) -> Result < PointerValue < ' ink > , Diagnostic > {
2245
- let target_size = self . get_string_size ( left_type, left_location. clone ( ) ) ?;
2246
- let value_size = self . get_string_size ( right_type, right_location) ?;
2247
- let size = std:: cmp:: min ( target_size - 1 , value_size) ;
2248
- let align_left = left_type. get_string_character_width ( self . index ) . value ( ) ;
2249
- let align_right = right_type. get_string_character_width ( self . index ) . value ( ) ;
2250
- //Multiply by the string alignment to copy enough for widestrings
2251
- //This is done at compile time to avoid generating an extra mul
2252
- let size = self . llvm . context . i32_type ( ) . const_int ( ( size * align_left as i64 ) as u64 , true ) ;
2212
+ let ( size, alignment) = match ( left_type, right_type) {
2213
+ (
2214
+ DataTypeInformation :: String { size : lsize, .. } ,
2215
+ DataTypeInformation :: String { size : rsize, .. } ,
2216
+ ) => {
2217
+ let target_size = lsize
2218
+ . as_int_value ( self . index )
2219
+ . map_err ( |err| Diagnostic :: codegen_error ( err. as_str ( ) , left_location. clone ( ) ) ) ?;
2220
+ let value_size = rsize
2221
+ . as_int_value ( self . index )
2222
+ . map_err ( |err| Diagnostic :: codegen_error ( err. as_str ( ) , right_location) ) ?;
2223
+ let size = std:: cmp:: min ( target_size - 1 , value_size) ;
2224
+ let alignment = left_type. get_string_character_width ( self . index ) . value ( ) ;
2225
+ //Multiply by the string alignment to copy enough for widestrings
2226
+ //This is done at compile time to avoid generating an extra mul
2227
+ let size = self . llvm . context . i32_type ( ) . const_int ( ( size * alignment as i64 ) as u64 , true ) ;
2228
+ ( size, alignment)
2229
+ }
2230
+ ( DataTypeInformation :: Array { .. } , DataTypeInformation :: Array { .. } )
2231
+ | ( DataTypeInformation :: Struct { .. } , DataTypeInformation :: Struct { .. } ) => {
2232
+ let size = self . llvm_index . get_associated_type ( right_type. get_name ( ) ) ?. size_of ( ) . ok_or_else (
2233
+ || {
2234
+ Diagnostic :: codegen_error (
2235
+ format ! ( "Unknown size of type {}." , right_type. get_name( ) ) . as_str ( ) ,
2236
+ right_location,
2237
+ )
2238
+ } ,
2239
+ ) ?;
2240
+ ( size, 1 )
2241
+ }
2242
+ _ => unreachable ! ( "memcpy is not used for non-aggregate types" ) ,
2243
+ } ;
2244
+
2253
2245
self . llvm
2254
2246
. builder
2255
- . build_memcpy ( left, align_left , right, align_right , size)
2247
+ . build_memcpy ( left, alignment , right, alignment , size)
2256
2248
. map_err ( |err| Diagnostic :: codegen_error ( err, left_location) )
2257
2249
}
2258
2250
2259
- fn get_string_size (
2260
- & self ,
2261
- datatype : & DataTypeInformation ,
2262
- location : SourceLocation ,
2263
- ) -> Result < i64 , Diagnostic > {
2264
- if let DataTypeInformation :: String { size, .. } = datatype {
2265
- size. as_int_value ( self . index ) . map_err ( |err| Diagnostic :: codegen_error ( err. as_str ( ) , location) )
2266
- } else {
2267
- Err ( Diagnostic :: codegen_error (
2268
- format ! ( "{} is not a String" , datatype. get_name( ) ) . as_str ( ) ,
2269
- location,
2270
- ) )
2271
- }
2272
- }
2273
-
2274
2251
/// returns an optional name used for a temporary variable when loading a pointer represented by `expression`
2275
2252
fn get_load_name ( & self , expression : & AstNode ) -> Option < String > {
2276
2253
match expression. get_stmt ( ) {
0 commit comments