@@ -28,7 +28,7 @@ use rustc_codegen_ssa::back::archive::{ArArchiveBuilder, ArchiveBuilder, Archive
2828use rustc_codegen_ssa:: {
2929 CompiledModule , CompiledModules , CrateInfo , ModuleKind , traits:: CodegenBackend ,
3030} ;
31- use std:: collections:: HashMap ;
31+ use std:: collections:: { HashMap , HashSet } ;
3232
3333use rustc_data_structures:: fx:: FxIndexMap ;
3434use rustc_hir:: { QPath , TyKind as HirTyKind } ;
@@ -123,6 +123,124 @@ fn lower_closure_to_oomir<'tcx>(
123123 oomir_module. merge_data_types ( & data_types) ;
124124}
125125
126+ fn placeholder_operand_for_constructor_field ( ty : & Type ) -> Operand {
127+ let constant = match ty {
128+ Type :: Boolean => oomir:: Constant :: Boolean ( false ) ,
129+ Type :: Char => oomir:: Constant :: Char ( '\0' ) ,
130+ Type :: I8 => oomir:: Constant :: I8 ( 0 ) ,
131+ Type :: I16 => oomir:: Constant :: I16 ( 0 ) ,
132+ Type :: I32 => oomir:: Constant :: I32 ( 0 ) ,
133+ Type :: I64 => oomir:: Constant :: I64 ( 0 ) ,
134+ Type :: F32 => oomir:: Constant :: F32 ( 0.0 ) ,
135+ Type :: F64 => oomir:: Constant :: F64 ( 0.0 ) ,
136+ Type :: String
137+ | Type :: Class ( _)
138+ | Type :: Interface ( _)
139+ | Type :: Array ( _)
140+ | Type :: MutableReference ( _)
141+ | Type :: Reference ( _) => oomir:: Constant :: Null ( ty. clone ( ) ) ,
142+ Type :: Void => panic ! ( "unexpected Void field type in constructor placeholder" ) ,
143+ } ;
144+ Operand :: Constant ( constant)
145+ }
146+
147+ fn constructor_args_from_fields (
148+ fields : & [ ( String , Type ) ] ,
149+ values : & [ ( & str , Operand ) ] ,
150+ ) -> Vec < ( Operand , Type ) > {
151+ fields
152+ . iter ( )
153+ . map ( |( field_name, field_ty) | {
154+ let operand = values
155+ . iter ( )
156+ . find_map ( |( name, operand) | ( * name == field_name) . then ( || operand. clone ( ) ) )
157+ . unwrap_or_else ( || {
158+ breadcrumbs:: log!(
159+ breadcrumbs:: LogLevel :: Info ,
160+ "shim" ,
161+ format!(
162+ "Info: Using constructor placeholder for missing shim field '{}' ({:?})" ,
163+ field_name, field_ty
164+ )
165+ ) ;
166+ placeholder_operand_for_constructor_field ( field_ty)
167+ } ) ;
168+ ( operand, field_ty. clone ( ) )
169+ } )
170+ . collect ( )
171+ }
172+
173+ fn pad_construct_object_args_in_function (
174+ function : & mut oomir:: Function ,
175+ class_fields : & HashMap < String , Vec < ( String , Type ) > > ,
176+ ) {
177+ for block in function. body . basic_blocks . values_mut ( ) {
178+ for instruction in & mut block. instructions {
179+ let oomir:: Instruction :: ConstructObject {
180+ class_name, args, ..
181+ } = instruction
182+ else {
183+ continue ;
184+ } ;
185+
186+ let Some ( fields) = class_fields. get ( class_name) else {
187+ continue ;
188+ } ;
189+
190+ if args. len ( ) >= fields. len ( ) {
191+ continue ;
192+ }
193+
194+ for ( field_name, field_ty) in fields. iter ( ) . skip ( args. len ( ) ) {
195+ breadcrumbs:: log!(
196+ breadcrumbs:: LogLevel :: Info ,
197+ "shim" ,
198+ format!(
199+ "Info: Padding constructor for '{}' with placeholder field '{}' ({:?})" ,
200+ class_name, field_name, field_ty
201+ )
202+ ) ;
203+ args. push ( (
204+ placeholder_operand_for_constructor_field ( field_ty) ,
205+ field_ty. clone ( ) ,
206+ ) ) ;
207+ }
208+ }
209+ }
210+ }
211+
212+ fn pad_construct_object_args_for_field_constructors ( oomir_module : & mut oomir:: Module ) {
213+ let class_fields: HashMap < String , Vec < ( String , Type ) > > = oomir_module
214+ . data_types
215+ . iter ( )
216+ . filter_map ( |( class_name, data_type) | match data_type {
217+ oomir:: DataType :: Class { fields, .. } => {
218+ let mut fields = fields. clone ( ) ;
219+ let mut seen_fields = HashSet :: new ( ) ;
220+ fields. retain ( |( name, _) | seen_fields. insert ( name. clone ( ) ) ) ;
221+ Some ( ( class_name. clone ( ) , fields) )
222+ }
223+ oomir:: DataType :: Interface { .. } => None ,
224+ } )
225+ . collect ( ) ;
226+
227+ for function in oomir_module. functions . values_mut ( ) {
228+ pad_construct_object_args_in_function ( function, & class_fields) ;
229+ }
230+
231+ for data_type in oomir_module. data_types . values_mut ( ) {
232+ let oomir:: DataType :: Class { methods, .. } = data_type else {
233+ continue ;
234+ } ;
235+
236+ for method in methods. values_mut ( ) {
237+ if let oomir:: DataTypeMethod :: Function ( function) = method {
238+ pad_construct_object_args_in_function ( function, & class_fields) ;
239+ }
240+ }
241+ }
242+ }
243+
126244fn install_fmt_arguments_shim ( oomir_module : & mut oomir:: Module ) {
127245 let class_name = "Arguments__" . to_string ( ) ;
128246 let Some ( oomir:: DataType :: Class {
@@ -154,23 +272,24 @@ fn install_fmt_arguments_shim(oomir_module: &mut oomir::Module) {
154272 ty
155273 } ) ;
156274
275+ let from_str_fields = fields. clone ( ) ;
157276 methods. entry ( "from_str" . to_string ( ) ) . or_insert_with ( || {
158277 let block = oomir:: BasicBlock {
159278 label : "bb0" . to_string ( ) ,
160279 instructions : vec ! [
161280 oomir:: Instruction :: ConstructObject {
162281 dest: "_args" . to_string( ) ,
163282 class_name: class_name. clone( ) ,
164- } ,
165- oomir :: Instruction :: SetField {
166- object : "_args" . to_string ( ) ,
167- field_name : "message" . to_string ( ) ,
168- value : Operand :: Variable {
169- name: "_1" . to_string( ) ,
170- ty: Type :: String ,
171- } ,
172- field_ty : Type :: String ,
173- owner_class : class_name . clone ( ) ,
283+ args : constructor_args_from_fields (
284+ & from_str_fields ,
285+ & [ (
286+ "message" ,
287+ Operand :: Variable {
288+ name: "_1" . to_string( ) ,
289+ ty: Type :: String ,
290+ } ,
291+ ) ] ,
292+ ) ,
174293 } ,
175294 oomir:: Instruction :: Return {
176295 operand: Some ( Operand :: Variable {
@@ -194,6 +313,7 @@ fn install_fmt_arguments_shim(oomir_module: &mut oomir::Module) {
194313 } )
195314 } ) ;
196315
316+ let new_fields = fields. clone ( ) ;
197317 methods. entry ( "new" . to_string ( ) ) . or_insert_with ( || {
198318 let argument_class = "core_fmt_rt_Argument__" . to_string ( ) ;
199319 let block = oomir:: BasicBlock {
@@ -228,16 +348,32 @@ fn install_fmt_arguments_shim(oomir_module: &mut oomir::Module) {
228348 oomir:: Instruction :: ConstructObject {
229349 dest: "_args" . to_string( ) ,
230350 class_name: class_name. clone( ) ,
231- } ,
232- oomir:: Instruction :: SetField {
233- object: "_args" . to_string( ) ,
234- field_name: "message" . to_string( ) ,
235- value: Operand :: Variable {
236- name: "_message" . to_string( ) ,
237- ty: Type :: String ,
238- } ,
239- field_ty: Type :: String ,
240- owner_class: class_name. clone( ) ,
351+ args: constructor_args_from_fields(
352+ & new_fields,
353+ & [
354+ (
355+ "message" ,
356+ Operand :: Variable {
357+ name: "_message" . to_string( ) ,
358+ ty: Type :: String ,
359+ } ,
360+ ) ,
361+ (
362+ "template" ,
363+ Operand :: Variable {
364+ name: "_1" . to_string( ) ,
365+ ty: Type :: Array ( Box :: new( Type :: I16 ) ) ,
366+ } ,
367+ ) ,
368+ (
369+ "args" ,
370+ Operand :: Variable {
371+ name: "_2" . to_string( ) ,
372+ ty: Type :: Array ( Box :: new( Type :: Class ( argument_class. clone( ) ) ) ) ,
373+ } ,
374+ ) ,
375+ ] ,
376+ ) ,
241377 } ,
242378 oomir:: Instruction :: Return {
243379 operand: Some ( Operand :: Variable {
@@ -371,14 +507,11 @@ fn install_fmt_argument_shim(oomir_module: &mut oomir::Module) {
371507 fields. push ( ( "value" . to_string ( ) , Type :: String ) ) ;
372508 }
373509
510+ let argument_fields = fields. clone ( ) ;
374511 methods. entry ( "new_display" . to_string ( ) ) . or_insert_with ( || {
375512 let block = oomir:: BasicBlock {
376513 label : "bb0" . to_string ( ) ,
377514 instructions : vec ! [
378- oomir:: Instruction :: ConstructObject {
379- dest: "_arg" . to_string( ) ,
380- class_name: class_name. clone( ) ,
381- } ,
382515 oomir:: Instruction :: InvokeStatic {
383516 dest: Some ( "_value" . to_string( ) ) ,
384517 class_name: "java/lang/String" . to_string( ) ,
@@ -393,15 +526,19 @@ fn install_fmt_argument_shim(oomir_module: &mut oomir::Module) {
393526 ty: Type :: I32 ,
394527 } ] ,
395528 } ,
396- oomir:: Instruction :: SetField {
397- object: "_arg" . to_string( ) ,
398- field_name: "value" . to_string( ) ,
399- value: Operand :: Variable {
400- name: "_value" . to_string( ) ,
401- ty: Type :: String ,
402- } ,
403- field_ty: Type :: String ,
404- owner_class: class_name. clone( ) ,
529+ oomir:: Instruction :: ConstructObject {
530+ dest: "_arg" . to_string( ) ,
531+ class_name: class_name. clone( ) ,
532+ args: constructor_args_from_fields(
533+ & argument_fields,
534+ & [ (
535+ "value" ,
536+ Operand :: Variable {
537+ name: "_value" . to_string( ) ,
538+ ty: Type :: String ,
539+ } ,
540+ ) ] ,
541+ ) ,
405542 } ,
406543 oomir:: Instruction :: Return {
407544 operand: Some ( Operand :: Variable {
@@ -1265,6 +1402,7 @@ impl CodegenBackend for MyBackend {
12651402
12661403 install_fmt_argument_shim ( & mut oomir_module) ;
12671404 install_fmt_arguments_shim ( & mut oomir_module) ;
1405+ pad_construct_object_args_for_field_constructors ( & mut oomir_module) ;
12681406
12691407 breadcrumbs:: log!(
12701408 breadcrumbs:: LogLevel :: Info ,
0 commit comments