From ac8f1f9210ac2f57c743eee5c61e72a91c8e22d3 Mon Sep 17 00:00:00 2001 From: Kouji Matsui Date: Sun, 5 Jan 2025 01:00:32 +0900 Subject: [PATCH] Improved archiver. --- .../ArchiverTests.Update.verified.txt | 1449 +++++++---------- chibiar/chibiar.core.Tests/ArchiverTests.cs | 87 +- chibiar/chibiar.core/Archiver.cs | 328 +--- .../Generating/ArchivedObjectInputFragment.cs | 2 +- chibild/chibild.core/Internal/Utilities.cs | 13 - .../Archiving/ArchiveObjectStream.cs | 62 - toolchain.common/Archiving/ArchiveReader.cs | 77 + .../Archiving/ArchiverUtilities.cs | 414 ++++- toolchain.common/IO/LittleEndianReader.cs | 116 ++ toolchain.common/IO/LittleEndianWriter.cs | 72 + toolchain.common/IO/NullStream.cs | 52 + toolchain.common/IO/RangeStream.cs | 86 + toolchain.common/IO/StreamUtilities.cs | 7 +- toolchain.common/Internal/CommonUtilities.cs | 16 + 14 files changed, 1440 insertions(+), 1341 deletions(-) delete mode 100644 toolchain.common/Archiving/ArchiveObjectStream.cs create mode 100644 toolchain.common/Archiving/ArchiveReader.cs create mode 100644 toolchain.common/IO/LittleEndianReader.cs create mode 100644 toolchain.common/IO/LittleEndianWriter.cs create mode 100644 toolchain.common/IO/NullStream.cs create mode 100644 toolchain.common/IO/RangeStream.cs diff --git a/chibiar/chibiar.core.Tests/ArchiverTests.Update.verified.txt b/chibiar/chibiar.core.Tests/ArchiverTests.Update.verified.txt index e472d36..be6e214 100644 --- a/chibiar/chibiar.core.Tests/ArchiverTests.Update.verified.txt +++ b/chibiar/chibiar.core.Tests/ArchiverTests.Update.verified.txt @@ -1632,826 +1632,531 @@ structure public Type 22 structure public Obj 21 .object codegen.o - global file _const_$_L928$__file__d___s__c_ - global file _L928$__file__d___s__c_ - global file _const_$_L925$_codegen - global file _L925$_codegen - global file _const_$_L924$_codegen - global file _L924$_codegen - global file _const_$_L923$___ret - global file _L923$___ret - global file _const_$_L922$__L_return_ - global file _L922$__L_return_ - global file _const_$_L921$____local__s - global file _L921$____local__s - global file _const_$_L920$____local__s__s - global file _L920$____local__s__s - global file _const_$_L917$____s - global file _L917$____s - global file _const_$_L916$_C_type___va_arglist - global file _L916$_C_type___va_arglist - global file _const_$_L915$__ - global file _L915$__ - global file _const_$_L914$___s__s - global file _L914$___s__s - global file _const_$_L913$__s__s - global file _L913$__s__s - global file _const_$_L910$___s_ - global file _L910$___s_ - global file _const_$_L909$__function_public - global file _L909$__function_public - global file _const_$_L908$__function_file - global file _L908$__function_file - global file _const_$_L905$_emit_text - global file _L905$_emit_text - global file _const_$_L904$_emit_text - global file _L904$_emit_text - global file _const_$_L903$___ret - global file _L903$___ret - global file _const_$_L902$__initializer_interna - global file _L902$__initializer_interna - global file _const_$_L901$___ret - global file _L901$___ret - global file _const_$_L900$__initializer_file - global file _L900$__initializer_file - global file _const_$_L899$__global_public__s___ - global file _L899$__global_public__s___ - global file _const_$_L898$__global_file__s___s - global file _L898$__global_file__s___s - global file _const_$_L897$__global_public___tls - global file _L897$__global_public___tls - global file _const_$_L896$__global_file___tls_s - global file _L896$__global_file___tls_s - global file _const_$_L895$___ - global file _L895$___ - global file _const_$_L894$__0x_hhx - global file _L894$__0x_hhx - global file _const_$_L891$__global_internal__s_ - global file _L891$__global_internal__s_ - global file _const_$_L890$__global_file__s__con - global file _L890$__global_file__s__con - global file _const_$_L887$_emit_data - global file _L887$_emit_data - global file _const_$_L886$_emit_data - global file _L886$_emit_data - global file _const_$_L885$___ret - global file _L885$___ret - global file _const_$_L884$___stobj__s - global file _L884$___stobj__s - global file _const_$_L883$___ldobj__s - global file _L883$___ldobj__s - global file _const_$_L882$___ldsflda__const___s - global file _L882$___ldsflda__const___s - global file _const_$_L881$___call___get_tls_val - global file _L881$___call___get_tls_val - global file _const_$_L880$___ldsfld___tls__s__ - global file _L880$___ldsfld___tls__s__ - global file _const_$_L879$__function_internal_v - global file _L879$__function_internal_v - global file _const_$_L878$__function_file_void_ - global file _L878$__function_file_void_ - global file _const_$_L877$_emit_tls_data_init - global file _L877$_emit_tls_data_init - global file _const_$_L876$_emit_tls_data_init - global file _L876$_emit_tls_data_init - global file _const_$_L875$___stobj__s - global file _L875$___stobj__s - global file _const_$_L874$___ldobj__s - global file _L874$___ldobj__s - global file _const_$_L873$___ldsflda__const___s - global file _L873$___ldsflda__const___s - global file _const_$_L872$___ldsfld__s - global file _L872$___ldsfld__s - global file _const_$_L871$_emit_non_tls_data_in - global file _L871$_emit_non_tls_data_in - global file _const_$_L870$_emit_non_tls_data_in - global file _L870$_emit_non_tls_data_in - global file _const_$_L869$__L_alloc__d_ - global file _L869$__L_alloc__d_ - global file _const_$_L868$___stsfld__s - global file _L868$___stsfld__s - global file _const_$_L867$___call_calloc - global file _L867$___call_calloc - global file _const_$_L866$___conv_u - global file _L866$___conv_u - global file _const_$_L865$___ldc_i8__ld - global file _L865$___ldc_i8__ld - global file _const_$_L864$___conv_u - global file _L864$___conv_u - global file _const_$_L863$___ldc_i4_1 - global file _L863$___ldc_i4_1 - global file _const_$_L862$___stsfld___tls__s__ - global file _L862$___stsfld___tls__s__ - global file _const_$_L861$___call___alloc_tls_s - global file _L861$___call___alloc_tls_s - global file _const_$_L860$___ldftn___tls_init__ - global file _L860$___ldftn___tls_init__ - global file _const_$_L859$___conv_u - global file _L859$___conv_u - global file _const_$_L858$___ldc_i8__ld - global file _L858$___ldc_i8__ld - global file _const_$_L857$___brfalse_s__L_alloc - global file _L857$___brfalse_s__L_alloc - global file _const_$_L856$___ceq - global file _L856$___ceq - global file _const_$_L855$___conv_u - global file _L855$___conv_u - global file _const_$_L854$___ldc_i4_0 - global file _L854$___ldc_i4_0 - global file _const_$_L853$___ldsfld__s - global file _L853$___ldsfld__s - global file _const_$_L852$___ldsfld___tls__s__ - global file _L852$___ldsfld___tls__s__ - global file _const_$_L851$_emit_data_alloc - global file _L851$_emit_data_alloc - global file _const_$_L850$_emit_data_alloc - global file _L850$_emit_data_alloc - global file _const_$_L843$_assign_lvar_offsets - global file _L843$_assign_lvar_offsets - global file _const_$_L842$_assign_lvar_offsets - global file _L842$_assign_lvar_offsets - global file _const_$_L841$___internal_uint8__ld - global file _L841$___internal_uint8__ld - global file _const_$_L840$_Could_not_adjust_on_ - global file _L840$_Could_not_adjust_on_ - global file _const_$_L839$___public__s__s_0 - global file _L839$___public__s__s_0 - global file _const_$_L836$__structure__s__s_exp - global file _L836$__structure__s__s_exp - global file _const_$_L834$_codegen_c - global file _L834$_codegen_c - global file _const_$_L833$_internal_error_at__s - global file _L833$_internal_error_at__s - global file _const_$_L832$___internal_uint8__ld - global file _L832$___internal_uint8__ld - global file _const_$_L831$_Could_not_adjust_on_ - global file _L831$_Could_not_adjust_on_ - global file _const_$_L830$_codegen_c - global file _L830$_codegen_c - global file _const_$_L829$_internal_error_at__s - global file _L829$_internal_error_at__s - global file _const_$_L828$___public__s__s - global file _L828$___public__s__s - global file _const_$_L827$___internal_uint8__ld - global file _L827$___internal_uint8__ld - global file _const_$_L826$_Could_not_adjust_on_ - global file _L826$_Could_not_adjust_on_ - global file _const_$_L825$___public__s__s - global file _L825$___public__s__s - global file _const_$_L824$___public_uint8___bit - global file _L824$___public_uint8___bit - global file _const_$_L823$___public_uint8___bit - global file _L823$___public_uint8___bit - global file _const_$_L818$__structure__s__s - global file _L818$__structure__s__s - global file _const_$_L816$____s__d - global file _L816$____s__d - global file _const_$_L813$__enumeration__s_int3 - global file _L813$__enumeration__s_int3 - global file _const_$_L810$_file - global file _L810$_file - global file _const_$_L809$_public - global file _L809$_public - global file _const_$_L806$_emit_type - global file _L806$_emit_type - global file _const_$_L805$_emit_type - global file _L805$_emit_type - global file _const_$_L804$___member_d - global file _L804$___member_d - global file _const_$_L803$_get_member_name - global file _L803$_get_member_name - global file _const_$_L802$_get_member_name - global file _L802$_get_member_name - global file _const_$_L801$_get_var_interior - global file _L801$_get_var_interior - global file _const_$_L800$_get_var_interior - global file _L800$_get_var_interior - global file _const_$_L798$_void - global file _L798$_void - global file _const_$_L796$__s_ - global file _L796$__s_ - global file _const_$_L793$_safe_to_cil_typename - global file _L793$_safe_to_cil_typename - global file _const_$_L792$_safe_to_cil_typename - global file _L792$_safe_to_cil_typename - global file _const_$_L785$_aggregate_types - global file _L785$_aggregate_types - global file _const_$_L784$_aggregate_types - global file _L784$_aggregate_types - global file _const_$_L783$_invalid_statement - global file _L783$_invalid_statement - global file _const_$_L782$____s - global file _L782$____s - global file _const_$_L779$___br__L_return - global file _L779$___br__L_return - global file _const_$_L777$__s_ - global file _L777$__s_ - global file _const_$_L775$___br__s - global file _L775$___br__s - global file _const_$_L770$__s_ - global file _L770$__s_ - global file _const_$_L768$__s_ - global file _L768$__s_ - global file _const_$_L767$___br__s - global file _L767$___br__s - global file _const_$_L766$___br__s - global file _L766$___br__s - global file _const_$_L765$___beq__s - global file _L765$___beq__s - global file _const_$_L764$___ldc_i4__d - global file _L764$___ldc_i4__d - global file _const_$_L762$___conv_i - global file _L762$___conv_i - global file _const_$_L761$___ldc_i8__ld - global file _L761$___ldc_i8__ld - global file _const_$_L759$___ldc_i8__ld - global file _L759$___ldc_i8__ld - global file _const_$_L753$__s_ - global file _L753$__s_ - global file _const_$_L752$___brfalse__L_begin__ - global file _L752$___brfalse__L_begin__ - global file _const_$_L751$__s_ - global file _L751$__s_ - global file _const_$_L750$__L_begin__d_ - global file _L750$__L_begin__d_ - global file _const_$_L748$__s_ - global file _L748$__s_ - global file _const_$_L747$___br__L_begin__d - global file _L747$___br__L_begin__d - global file _const_$_L746$__s_ - global file _L746$__s_ - global file _const_$_L745$___brtrue__s - global file _L745$___brtrue__s - global file _const_$_L744$__L_begin__d_ - global file _L744$__L_begin__d_ - global file _const_$_L743$_codegen_c - global file _L743$_codegen_c - global file _const_$_L742$_internal_error_at__s - global file _L742$_internal_error_at__s - global file _const_$_L740$__L_end__d_ - global file _L740$__L_end__d_ - global file _const_$_L739$__L_else__d_ - global file _L739$__L_else__d_ - global file _const_$_L738$___br__L_end__d - global file _L738$___br__L_end__d - global file _const_$_L737$___brtrue__L_else__d - global file _L737$___brtrue__L_else__d - global file _const_$_L734$_gen_stmt - global file _L734$_gen_stmt - global file _const_$_L733$_gen_stmt - global file _L733$_gen_stmt - global file _const_$_L732$_codegen_c - global file _L732$_codegen_c - global file _const_$_L731$_internal_error_at__s - global file _L731$_internal_error_at__s - global file _const_$_L730$___ldobj__s - global file _L730$___ldobj__s - global file _const_$_L729$___localloc - global file _L729$___localloc - global file _const_$_L728$___sizeof__s - global file _L728$___sizeof__s - global file _const_$_L724$___conv_i - global file _L724$___conv_i - global file _const_$_L723$___ldc_i4_0 - global file _L723$___ldc_i4_0 - global file _const_$_L718$___conv_r8 - global file _L718$___conv_r8 - global file _const_$_L717$___ldc_i4_0 - global file _L717$___ldc_i4_0 - global file _const_$_L715$___conv_r4 - global file _L715$___conv_r4 - global file _const_$_L714$___ldc_i4_0 - global file _L714$___ldc_i4_0 - global file _const_$_L712$___conv_i8 - global file _L712$___conv_i8 - global file _const_$_L711$___ldc_i4_0 - global file _L711$___ldc_i4_0 - global file _const_$_L709$___ldc_i4_0 - global file _L709$___ldc_i4_0 - global file _const_$_L702$_gen_dummy_value - global file _L702$_gen_dummy_value - global file _const_$_L701$_gen_dummy_value - global file _L701$_gen_dummy_value - global file _const_$_L700$_invalid_expression - global file _L700$_invalid_expression - global file _const_$_L699$___shr - global file _L699$___shr - global file _const_$_L698$___shr_un - global file _L698$___shr_un - global file _const_$_L696$___shl - global file _L696$___shl - global file _const_$_L694$___ceq - global file _L694$___ceq - global file _const_$_L693$___ldc_i4_0 - global file _L693$___ldc_i4_0 - global file _const_$_L692$___cgt - global file _L692$___cgt - global file _const_$_L691$___cgt_un - global file _L691$___cgt_un - global file _const_$_L689$___clt - global file _L689$___clt - global file _const_$_L688$___clt_un - global file _L688$___clt_un - global file _const_$_L686$___ceq - global file _L686$___ceq - global file _const_$_L685$___ldc_i4_0 - global file _L685$___ldc_i4_0 - global file _const_$_L684$___ceq - global file _L684$___ceq - global file _const_$_L682$___ceq - global file _L682$___ceq - global file _const_$_L680$___xor - global file _L680$___xor - global file _const_$_L678$___or - global file _L678$___or - global file _const_$_L676$___and - global file _L676$___and - global file _const_$_L674$___rem - global file _L674$___rem - global file _const_$_L673$___rem_un - global file _L673$___rem_un - global file _const_$_L671$___div - global file _L671$___div - global file _const_$_L670$___div_un - global file _L670$___div_un - global file _const_$_L668$___mul - global file _L668$___mul - global file _const_$_L666$___sub - global file _L666$___sub - global file _const_$_L664$___add - global file _L664$___add - global file _const_$_L660$__L_end__d_ - global file _L660$__L_end__d_ - global file _const_$_L659$___brfalse__L_end__d - global file _L659$___brfalse__L_end__d - global file _const_$_L658$__L_end__d_ - global file _L658$__L_end__d_ - global file _const_$_L657$___ldc_i4_1 - global file _L657$___ldc_i4_1 - global file _const_$_L656$__L_true__d_ - global file _L656$__L_true__d_ - global file _const_$_L655$___br_s__L_end__d - global file _L655$___br_s__L_end__d - global file _const_$_L654$___ldc_i4_0 - global file _L654$___ldc_i4_0 - global file _const_$_L653$___brfalse_s__L_true_ - global file _L653$___brfalse_s__L_true_ - global file _const_$_L652$___brfalse__L_true__d - global file _L652$___brfalse__L_true__d - global file _const_$_L650$__L_end__d_ - global file _L650$__L_end__d_ - global file _const_$_L649$___brtrue__L_end__d - global file _L649$___brtrue__L_end__d - global file _const_$_L648$__L_end__d_ - global file _L648$__L_end__d_ - global file _const_$_L647$___ldc_i4_0 - global file _L647$___ldc_i4_0 - global file _const_$_L646$__L_false__d_ - global file _L646$__L_false__d_ - global file _const_$_L645$___br_s__L_end__d - global file _L645$___br_s__L_end__d - global file _const_$_L644$___ldc_i4_1 - global file _L644$___ldc_i4_1 - global file _const_$_L643$___brtrue_s__L_false_ - global file _L643$___brtrue_s__L_false_ - global file _const_$_L642$___brtrue__L_false__d - global file _L642$___brtrue__L_false__d - global file _const_$_L640$___not - global file _L640$___not - global file _const_$_L637$__L_end__d_ - global file _L637$__L_end__d_ - global file _const_$_L636$__L_else__d_ - global file _L636$__L_else__d_ - global file _const_$_L635$___br__L_end__d - global file _L635$___br__L_end__d - global file _const_$_L634$___brtrue__L_else__d - global file _L634$___brtrue__L_else__d - global file _const_$_L632$___initobj__s - global file _L632$___initobj__s - global file _const_$_L625$___dup - global file _L625$___dup - global file _const_$_L624$___ldarg__d - global file _L624$___ldarg__d - global file _const_$_L623$___starg__d - global file _L623$___starg__d - global file _const_$_L621$___ldloc__d - global file _L621$___ldloc__d - global file _const_$_L620$___stloc__d - global file _L620$___stloc__d - global file _const_$_L612$___ldloc__s - global file _L612$___ldloc__s - global file _const_$_L611$___or - global file _L611$___or - global file _const_$_L610$___shl - global file _L610$___shl - global file _const_$_L609$___and - global file _L609$___and - global file _const_$_L608$___ldloc__s - global file _L608$___ldloc__s - global file _const_$_L607$___stloc__s - global file _L607$___stloc__s - global file _const_$_L606$___conv_i8 - global file _L606$___conv_i8 - global file _const_$_L605$___and - global file _L605$___and - global file _const_$_L604$___not - global file _L604$___not - global file _const_$_L603$___shl - global file _L603$___shl - global file _const_$_L602$___dup - global file _L602$___dup - global file _const_$_L597$___shr - global file _L597$___shr - global file _const_$_L596$___shr_un - global file _L596$___shr_un - global file _const_$_L595$___shl - global file _L595$___shl - global file _const_$_L594$___sub - global file _L594$___sub - global file _const_$_L592$___ldarg__d - global file _L592$___ldarg__d - global file _const_$_L590$___ldloc__d - global file _L590$___ldloc__d - global file _const_$_L581$___neg - global file _L581$___neg - global file _const_$_L579$_codegen_c - global file _L579$_codegen_c - global file _const_$_L578$_internal_error_at__s - global file _L578$_internal_error_at__s - global file _const_$_L577$___ldc_r8__f - global file _L577$___ldc_r8__f - global file _const_$_L575$___ldc_r4__f - global file _L575$___ldc_r4__f - global file _const_$_L561$_gen_expr - global file _L561$_gen_expr - global file _const_$_L560$_gen_expr - global file _L560$_gen_expr - global file _const_$_L559$____location__d__d__d - global file _L559$____location__d__d__d - global file _const_$_L558$_gen_location - global file _L558$_gen_location - global file _const_$_L557$_gen_location - global file _L557$_gen_location - global file _const_$_L556$_codegen_c - global file _L556$_codegen_c - global file _const_$_L555$_internal_error_at__s - global file _L555$_internal_error_at__s - global file _const_$_L554$___conv_i - global file _L554$___conv_i - global file _const_$_L553$___ldc_i4__ld - global file _L553$___ldc_i4__ld - global file _const_$_L552$___ldc_i4_m1 - global file _L552$___ldc_i4_m1 - global file _const_$_L551$___ldc_i4_s__ld - global file _L551$___ldc_i4_s__ld - global file _const_$_L550$___ldc_i4__ld - global file _L550$___ldc_i4__ld - global file _const_$_L549$___ldc_i8__ld - global file _L549$___ldc_i8__ld - global file _const_$_L546$___conv_i8 - global file _L546$___conv_i8 - global file _const_$_L545$___ldc_i4__ld - global file _L545$___ldc_i4__ld - global file _const_$_L544$___conv_i8 - global file _L544$___conv_i8 - global file _const_$_L543$___ldc_i4_m1 - global file _L543$___ldc_i4_m1 - global file _const_$_L542$___conv_i8 - global file _L542$___conv_i8 - global file _const_$_L541$___ldc_i4_s__ld - global file _L541$___ldc_i4_s__ld - global file _const_$_L540$___conv_i8 - global file _L540$___conv_i8 - global file _const_$_L539$___ldc_i4__ld - global file _L539$___ldc_i4__ld - global file _const_$_L538$___ldc_i8__ld - global file _L538$___ldc_i8__ld - global file _const_$_L536$___ldc_i4__d - global file _L536$___ldc_i4__d - global file _const_$_L535$___ldc_i4_m1 - global file _L535$___ldc_i4_m1 - global file _const_$_L534$___ldc_i4_s__d - global file _L534$___ldc_i4_s__d - global file _const_$_L533$___ldc_i4__d - global file _L533$___ldc_i4__d - global file _const_$_L528$___ldc_i4__d - global file _L528$___ldc_i4__d - global file _const_$_L525$_gen_const_integer - global file _L525$_gen_const_integer - global file _const_$_L524$_gen_const_integer - global file _L524$_gen_const_integer - global file _const_$_L523$___conv_u - global file _L523$___conv_u - global file _const_$_L522$___sizeof__s - global file _L522$___sizeof__s - global file _const_$_L521$_codegen_c - global file _L521$_codegen_c - global file _const_$_L520$_internal_error_at__s - global file _L520$_internal_error_at__s - global file _const_$_L519$___conv_u - global file _L519$___conv_u - global file _const_$_L518$___ldc_i4_0 - global file _L518$___ldc_i4_0 - global file _const_$_L514$_gen_sizeof - global file _L514$_gen_sizeof - global file _const_$_L513$_gen_sizeof - global file _L513$_gen_sizeof - global file _const_$_L512$___conv_r8 - global file _L512$___conv_r8 - global file _const_$_L510$___conv_r4 - global file _L510$___conv_r4 - global file _const_$_L508$___conv_i - global file _L508$___conv_i - global file _const_$_L507$___conv_u - global file _L507$___conv_u - global file _const_$_L504$___conv_i2 - global file _L504$___conv_i2 - global file _const_$_L503$___conv_u2 - global file _L503$___conv_u2 - global file _const_$_L501$___conv_i1 - global file _L501$___conv_i1 - global file _const_$_L500$___conv_u1 - global file _L500$___conv_u1 - global file _const_$_L498$___ceq - global file _L498$___ceq - global file _const_$_L497$___ldc_i4_0 - global file _L497$___ldc_i4_0 - global file _const_$_L496$___ceq - global file _L496$___ceq - global file _const_$_L495$___ldc_i4_0 - global file _L495$___ldc_i4_0 - global file _const_$_L494$___conv_u1 - global file _L494$___conv_u1 - global file _const_$_L491$___pop - global file _L491$___pop - global file _const_$_L490$___calli__s - global file _L490$___calli__s - global file _const_$_L489$___call__s - global file _L489$___call__s - global file _const_$_L486$___call___va_arglist_ - global file _L486$___call___va_arglist_ - global file _const_$_L485$___box__s - global file _L485$___box__s - global file _const_$_L484$___box_nint - global file _L484$___box_nint - global file _const_$_L483$___dup - global file _L483$___dup - global file _const_$_L480$___call___va_arglist_ - global file _L480$___call___va_arglist_ - global file _const_$_L479$___ldc_i4__d - global file _L479$___ldc_i4__d - global file _const_$_L472$___call___va_copy - global file _L472$___call___va_copy - global file _const_$_L471$_invalid_argument - global file _L471$_invalid_argument - global file _const_$_L470$___builtin_va_copy - global file _L470$___builtin_va_copy - global file _const_$_L469$___call___va_arg - global file _L469$___call___va_arg - global file _const_$_L468$_invalid_argument - global file _L468$_invalid_argument - global file _const_$_L467$_invalid_argument - global file _L467$_invalid_argument - global file _const_$_L466$_invalid_argument - global file _L466$_invalid_argument - global file _const_$_L465$_invalid_argument - global file _L465$_invalid_argument - global file _const_$_L464$___builtin_va_arg - global file _L464$___builtin_va_arg - global file _const_$_L463$___call___va_start - global file _L463$___call___va_start - global file _const_$_L462$___ldarg_s__d - global file _L462$___ldarg_s__d - global file _const_$_L461$_invalid_argument - global file _L461$_invalid_argument - global file _const_$_L460$___builtin_va_start - global file _L460$___builtin_va_start - global file _const_$_L459$___break - global file _L459$___break - global file _const_$_L458$_invalid_argument - global file _L458$_invalid_argument - global file _const_$_L457$___builtin_trap - global file _L457$___builtin_trap - global file _const_$_L456$___localloc - global file _L456$___localloc - global file _const_$_L455$_could_not_use_alloca - global file _L455$_could_not_use_alloca - global file _const_$_L454$_invalid_argument - global file _L454$_invalid_argument - global file _const_$_L453$_alloca - global file _L453$_alloca - global file _const_$_L452$_gen_funcall - global file _L452$_gen_funcall - global file _const_$_L451$_gen_funcall - global file _L451$_gen_funcall - global file _const_$_L450$___conv_r8 - global file _L450$___conv_r8 - global file _const_$_L449$____s - global file _L449$____s - global file _const_$_L448$___ceq - global file _L448$___ceq - global file _const_$_L447$___ldc_i4_0 - global file _L447$___ldc_i4_0 - global file _const_$_L446$_cast - global file _L446$_cast - global file _const_$_L445$_cast - global file _L445$_cast - global file cast_table - global file convr8 - global file convr4 - global file convrun - global file convnuint - global file convnint - global file convu8 - global file convi8 - global file convu4 - global file convi4 - global file convu2 - global file convi2 - global file convu1 - global file convi1 - global file _const_$_L433$_getTypeId - global file _L433$_getTypeId - global file _const_$_L432$_getTypeId - global file _L432$_getTypeId - global file _const_$_L431$___ceq - global file _L431$___ceq - global file _const_$_L430$___conv_r8 - global file _L430$___conv_r8 - global file _const_$_L428$___conv_r4 - global file _L428$___conv_r4 - global file _const_$_L426$___conv_i - global file _L426$___conv_i - global file _const_$_L423$___conv_i8 - global file _L423$___conv_i8 - global file _const_$_L420$___ldc_i4_0 - global file _L420$___ldc_i4_0 - global file _const_$_L419$_cmp_zero - global file _L419$_cmp_zero - global file _const_$_L418$_cmp_zero - global file _L418$_cmp_zero - global file _const_$_L417$_codegen_c - global file _L417$_codegen_c - global file _const_$_L416$_internal_error_at__s - global file _L416$_internal_error_at__s - global file _const_$_L415$___stind_r8 - global file _L415$___stind_r8 - global file _const_$_L413$___stind_r4 - global file _L413$___stind_r4 - global file _const_$_L411$___stind_i8 - global file _L411$___stind_i8 - global file _const_$_L409$___stind_i4 - global file _L409$___stind_i4 - global file _const_$_L406$___stind_i2 - global file _L406$___stind_i2 - global file _const_$_L404$___stind_i1 - global file _L404$___stind_i1 - global file _const_$_L401$___stind_i - global file _L401$___stind_i - global file _const_$_L398$___stobj__s - global file _L398$___stobj__s - global file _const_$_L393$_store - global file _L393$_store - global file _const_$_L392$_store - global file _L392$_store - global file _const_$_L391$_codegen_c - global file _L391$_codegen_c - global file _const_$_L390$_internal_error_at__s - global file _L390$_internal_error_at__s - global file _const_$_L389$___ldind__s4 - global file _L389$___ldind__s4 - global file _const_$_L387$___ldind__s2 - global file _L387$___ldind__s2 - global file _const_$_L385$___ldind__s1 - global file _L385$___ldind__s1 - global file _const_$_L382$_i - global file _L382$_i - global file _const_$_L381$_u - global file _L381$_u - global file _const_$_L380$___ldind_r8 - global file _L380$___ldind_r8 - global file _const_$_L378$___ldind_r4 - global file _L378$___ldind_r4 - global file _const_$_L376$___ldind_i - global file _L376$___ldind_i - global file _const_$_L373$___ldind_i8 - global file _L373$___ldind_i8 - global file _const_$_L371$___ldind_i4 - global file _L371$___ldind_i4 - global file _const_$_L369$___ldind_u1 - global file _L369$___ldind_u1 - global file _const_$_L367$___ldobj__s - global file _L367$___ldobj__s - global file _const_$_L360$_load - global file _L360$_load - global file _const_$_L359$_load - global file _L359$_load - global file _const_$_L358$___ldloc___ptr_d_ - global file _L358$___ldloc___ptr_d_ - global file _const_$_L357$___stloc___ptr_d_ - global file _L357$___stloc___ptr_d_ - global file _const_$_L356$____local__s____ptr_d - global file _L356$____local__s____ptr_d - global file _const_$_L355$_gen_make_ptr - global file _L355$_gen_make_ptr - global file _const_$_L354$_gen_make_ptr - global file _L354$_gen_make_ptr - global file _const_$_L353$_not_an_lvalue - global file _L353$_not_an_lvalue - global file _const_$_L352$___ldloca___retval_d_ - global file _L352$___ldloca___retval_d_ - global file _const_$_L351$___stloc___retval_d_ - global file _L351$___stloc___retval_d_ - global file _const_$_L350$____local__s___retval - global file _L350$____local__s___retval - global file _const_$_L348$___add - global file _L348$___add - global file _const_$_L344$_codegen_c - global file _L344$_codegen_c - global file _const_$_L343$_internal_error_at__s - global file _L343$_internal_error_at__s - global file _const_$_L342$___ldarga__d - global file _L342$___ldarga__d - global file _const_$_L340$___ldloca__d - global file _L340$___ldloca__d - global file _const_$_L338$___ldsfld__s - global file _L338$___ldsfld__s - global file _const_$_L337$___call___get_tls_val - global file _L337$___call___get_tls_val - global file _const_$_L336$___ldsfld___tls__s__ - global file _L336$___ldsfld___tls__s__ - global file _const_$_L333$___ldftn__s - global file _L333$___ldftn__s - global file _const_$_L328$_gen_addr - global file _L328$_gen_addr - global file _const_$_L327$_gen_addr - global file _L327$_gen_addr - global file _const_$_L326$____local__s__s - global file _L326$____local__s__s - global file _const_$_L325$___temp_d_ - global file _L325$___temp_d_ - global file _const_$_L324$_gen_make_temp - global file _L324$_gen_make_temp - global file _const_$_L323$_gen_make_temp - global file _L323$_gen_make_temp - global file _const_$_L322$__s__s_ - global file _L322$__s__s_ - global file _const_$_L321$__s_C_type___va_argli - global file _L321$__s_C_type___va_argli - global file _const_$_L320$_C_type___va_arglist - global file _L320$_C_type___va_arglist - global file _const_$_L319$__s__s - global file _L319$__s__s - global file _const_$_L316$_ - global file _L316$_ - global file _const_$_L315$_get_cil_callsite - global file _L315$_get_cil_callsite - global file _const_$_L314$_get_cil_callsite - global file _L314$_get_cil_callsite - global file _const_$_L313$_make_public_type - global file _L313$_make_public_type - global file _const_$_L312$_make_public_type - global file _L312$_make_public_type - global file _const_$_L301$_make_public_type_rec - global file _L301$_make_public_type_rec - global file _const_$_L300$_make_public_type_rec - global file _L300$_make_public_type_rec - global file _const_$_L299$_aggregate_type - global file _L299$_aggregate_type - global file _const_$_L298$_aggregate_type - global file _L298$_aggregate_type - global file _const_$_L286$_aggregate_type_recur - global file _L286$_aggregate_type_recur - global file _const_$_L285$_aggregate_type_recur - global file _L285$_aggregate_type_recur - global file _const_$_L282$_add_using_type - global file _L282$_add_using_type - global file _const_$_L281$_add_using_type - global file _L281$_add_using_type - global file _L280$_slvar - global file _const_$_L279$_count - global file _L279$_count - global file _const_$_L278$_count - global file _L278$_count - global file _const_$_L277$_print - global file _L277$_print - global file _const_$_L276$_print - global file _L276$_print - global file _const_$_L275$__ - global file _L275$__ - global file _const_$_L274$_println - global file _L274$_println - global file _const_$_L273$_println - global file _L273$_println - global file lvar_offset - global file using_type + global file _L590$_slvar + global file _const_$_L589$____ + global file _L589$____ + global file _const_$_L588$_tokenize_file + global file _L588$_tokenize_file + global file _const_$_L587$_tokenize_file + global file _L587$_tokenize_file + global file _const_$_L586$__U + global file _L586$__U + global file _const_$_L585$__u + global file _L585$__u + global file _const_$_L582$_convert_universal_ch + global file _L582$_convert_universal_ch + global file _const_$_L581$_convert_universal_ch + global file _L581$_convert_universal_ch + global file _const_$_L578$_read_universal_char + global file _L578$_read_universal_char + global file _const_$_L577$_read_universal_char + global file _L577$_read_universal_char + global file _const_$_L570$_remove_backslash_new + global file _L570$_remove_backslash_new + global file _const_$_L569$_remove_backslash_new + global file _L569$_remove_backslash_new + global file _const_$_L566$_canonicalize_newline + global file _L566$_canonicalize_newline + global file _const_$_L565$_canonicalize_newline + global file _L565$_canonicalize_newline + global file _const_$_L564$_new_file + global file _L564$_new_file + global file _const_$_L563$_new_file + global file _L563$_new_file + global file _const_$_L562$_get_input_files + global file _L562$_get_input_files + global file _const_$_L561$_get_input_files + global file _L561$_get_input_files + global file _const_$_L558$_r + global file _L558$_r + global file _const_$_L557$__ + global file _L557$__ + global file _const_$_L556$_read_file + global file _L556$_read_file + global file _const_$_L555$_read_file + global file _L555$_read_file + global file _const_$_L554$_invalid_token + global file _L554$_invalid_token + global file _const_$_L553$_U_ + global file _L553$_U_ + global file _const_$_L552$_L_ + global file _L552$_L_ + global file _const_$_L551$_u_ + global file _L551$_u_ + global file _const_$_L550$_U_ + global file _L550$_U_ + global file _const_$_L549$_L_ + global file _L549$_L_ + global file _const_$_L548$_u_ + global file _L548$_u_ + global file _const_$_L547$_u8_ + global file _L547$_u8_ + global file _const_$_L546$___ + global file _L546$___ + global file _const_$_L545$_eEpP + global file _L545$_eEpP + global file _const_$_L542$_unclosed_block_comme + global file _L542$_unclosed_block_comme + global file _const_$_L541$___ + global file _L541$___ + global file _const_$_L540$___ + global file _L540$___ + global file _const_$_L537$___ + global file _L537$___ + global file _const_$_L534$_tokenize + global file _L534$_tokenize + global file _const_$_L533$_tokenize + global file _L533$_tokenize + global file _const_$_L532$_tokenize_string_lite + global file _L532$_tokenize_string_lite + global file _const_$_L531$_tokenize_string_lite + global file _L531$_tokenize_string_lite + global file _const_$_L528$_add_line_numbers + global file _L528$_add_line_numbers + global file _const_$_L527$_add_line_numbers + global file _L527$_add_line_numbers + global file _const_$_L524$_convert_pp_tokens + global file _L524$_convert_pp_tokens + global file _const_$_L523$_convert_pp_tokens + global file _L523$_convert_pp_tokens + global file _const_$_L522$_invalid_numeric_cons + global file _L522$_invalid_numeric_cons + global file _const_$_L521$_convert_pp_number + global file _L521$_convert_pp_number + global file _const_$_L520$_convert_pp_number + global file _L520$_convert_pp_number + global file _const_$_L519$_ll + global file _L519$_ll + global file _const_$_L518$_LL + global file _L518$_LL + global file _const_$_L517$_ul + global file _L517$_ul + global file _const_$_L516$_lu + global file _L516$_lu + global file _const_$_L515$_ull + global file _L515$_ull + global file _const_$_L514$_uLL + global file _L514$_uLL + global file _const_$_L513$_Ull + global file _L513$_Ull + global file _const_$_L512$_ULL + global file _L512$_ULL + global file _const_$_L511$_llu + global file _L511$_llu + global file _const_$_L510$_llU + global file _L510$_llU + global file _const_$_L509$_LLu + global file _L509$_LLu + global file _const_$_L508$_LLU + global file _L508$_LLU + global file _const_$_L507$_0b + global file _L507$_0b + global file _const_$_L506$_0x + global file _L506$_0x + global file _const_$_L505$_convert_pp_int + global file _L505$_convert_pp_int + global file _const_$_L504$_convert_pp_int + global file _L504$_convert_pp_int + global file _const_$_L503$_unclosed_char_litera + global file _L503$_unclosed_char_litera + global file _const_$_L502$_unclosed_char_litera + global file _L502$_unclosed_char_litera + global file _const_$_L501$_read_char_literal + global file _L501$_read_char_literal + global file _const_$_L500$_read_char_literal + global file _L500$_read_char_literal + global file _const_$_L497$_read_utf32_string_li + global file _L497$_read_utf32_string_li + global file _const_$_L496$_read_utf32_string_li + global file _L496$_read_utf32_string_li + global file _const_$_L493$_read_utf16_string_li + global file _L493$_read_utf16_string_li + global file _const_$_L492$_read_utf16_string_li + global file _L492$_read_utf16_string_li + global file _const_$_L489$_read_string_literal + global file _L489$_read_string_literal + global file _const_$_L488$_read_string_literal + global file _L488$_read_string_literal + global file _const_$_L487$_unclosed_string_lite + global file _L487$_unclosed_string_lite + global file _const_$_L484$_string_literal_end + global file _L484$_string_literal_end + global file _const_$_L483$_string_literal_end + global file _L483$_string_literal_end + global file _const_$_L470$_invalid_hex_escape_s + global file _L470$_invalid_hex_escape_s + global file _const_$_L469$_read_escaped_char + global file _L469$_read_escaped_char + global file _const_$_L468$_read_escaped_char + global file _L468$_read_escaped_char + global file _const_$_L465$___thread + global file _L465$___thread + global file _const_$_L464$__Thread_local + global file _L464$__Thread_local + global file _const_$_L463$_asm + global file _L463$_asm + global file _const_$_L462$_typeof + global file _L462$_typeof + global file _const_$_L461$_double + global file _L461$_double + global file _const_$_L460$_float + global file _L460$_float + global file _const_$_L459$__Noreturn + global file _L459$__Noreturn + global file _const_$_L458$___restrict__ + global file _L458$___restrict__ + global file _const_$_L457$___restrict + global file _L457$___restrict + global file _const_$_L456$_restrict + global file _L456$_restrict + global file _const_$_L455$_register + global file _L455$_register + global file _const_$_L454$_auto + global file _L454$_auto + global file _const_$_L453$_volatile + global file _L453$_volatile + global file _const_$_L452$_const + global file _L452$_const + global file _const_$_L451$___builtin_nuint + global file _L451$___builtin_nuint + global file _const_$_L450$___builtin_nint + global file _L450$___builtin_nint + global file _const_$_L449$_unsigned + global file _L449$_unsigned + global file _const_$_L448$_signed + global file _L448$_signed + global file _const_$_L447$___builtin_va_list + global file _L447$___builtin_va_list + global file _const_$_L446$_do + global file _L446$_do + global file _const_$_L445$__Alignas + global file _L445$__Alignas + global file _const_$_L444$__Alignof + global file _L444$__Alignof + global file _const_$_L443$_extern + global file _L443$_extern + global file _const_$_L442$_default + global file _L442$_default + global file _const_$_L441$_case + global file _L441$_case + global file _const_$_L440$_switch + global file _L440$_switch + global file _const_$_L439$_continue + global file _L439$_continue + global file _const_$_L438$_break + global file _L438$_break + global file _const_$_L437$_goto + global file _L437$_goto + global file _const_$_L436$_static + global file _L436$_static + global file _const_$_L435$_enum + global file _L435$_enum + global file _const_$_L434$__Bool + global file _L434$__Bool + global file _const_$_L433$_typedef + global file _L433$_typedef + global file _const_$_L432$_void + global file _L432$_void + global file _const_$_L431$_long + global file _L431$_long + global file _const_$_L430$_short + global file _L430$_short + global file _const_$_L429$_union + global file _L429$_union + global file _const_$_L428$_struct + global file _L428$_struct + global file _const_$_L427$_char + global file _L427$_char + global file _const_$_L426$_sizeof + global file _L426$_sizeof + global file _const_$_L425$_int + global file _L425$_int + global file _const_$_L424$_while + global file _L424$_while + global file _const_$_L423$_for + global file _L423$_for + global file _const_$_L422$_else + global file _L422$_else + global file _const_$_L421$_if + global file _L421$_if + global file _const_$_L420$_return + global file _L420$_return + global file _const_$_L419$___thread + global file _L419$___thread + global file _const_$_L418$__Thread_local + global file _L418$__Thread_local + global file _const_$_L417$_asm + global file _L417$_asm + global file _const_$_L416$_typeof + global file _L416$_typeof + global file _const_$_L415$_double + global file _L415$_double + global file _const_$_L414$_float + global file _L414$_float + global file _const_$_L413$__Noreturn + global file _L413$__Noreturn + global file _const_$_L412$___restrict__ + global file _L412$___restrict__ + global file _const_$_L411$___restrict + global file _L411$___restrict + global file _const_$_L410$_restrict + global file _L410$_restrict + global file _const_$_L409$_register + global file _L409$_register + global file _const_$_L408$_auto + global file _L408$_auto + global file _const_$_L407$_volatile + global file _L407$_volatile + global file _const_$_L406$_const + global file _L406$_const + global file _const_$_L405$___builtin_nuint + global file _L405$___builtin_nuint + global file _const_$_L404$___builtin_nint + global file _L404$___builtin_nint + global file _const_$_L403$_unsigned + global file _L403$_unsigned + global file _const_$_L402$_signed + global file _L402$_signed + global file _const_$_L401$___builtin_va_list + global file _L401$___builtin_va_list + global file _const_$_L400$_do + global file _L400$_do + global file _const_$_L399$__Alignas + global file _L399$__Alignas + global file _const_$_L398$__Alignof + global file _L398$__Alignof + global file _const_$_L397$_extern + global file _L397$_extern + global file _const_$_L396$_default + global file _L396$_default + global file _const_$_L395$_case + global file _L395$_case + global file _const_$_L394$_switch + global file _L394$_switch + global file _const_$_L393$_continue + global file _L393$_continue + global file _const_$_L392$_break + global file _L392$_break + global file _const_$_L391$_goto + global file _L391$_goto + global file _const_$_L390$_static + global file _L390$_static + global file _const_$_L389$_enum + global file _L389$_enum + global file _const_$_L388$__Bool + global file _L388$__Bool + global file _const_$_L387$_typedef + global file _L387$_typedef + global file _const_$_L386$_void + global file _L386$_void + global file _const_$_L385$_long + global file _L385$_long + global file _const_$_L384$_short + global file _L384$_short + global file _const_$_L383$_union + global file _L383$_union + global file _const_$_L382$_struct + global file _L382$_struct + global file _const_$_L381$_char + global file _L381$_char + global file _const_$_L380$_sizeof + global file _L380$_sizeof + global file _const_$_L379$_int + global file _L379$_int + global file _const_$_L378$_while + global file _L378$_while + global file _const_$_L377$_for + global file _L377$_for + global file _const_$_L376$_else + global file _L376$_else + global file _const_$_L375$_if + global file _L375$_if + global file _const_$_L374$_return + global file _L374$_return + global file _L373$_slvar + global file _L372$_slvar + global file _const_$_L371$_is_keyword + global file _L371$_is_keyword + global file _const_$_L370$_is_keyword + global file _L370$_is_keyword + global file _const_$_L367$___ + global file _L367$___ + global file _const_$_L366$___ + global file _L366$___ + global file _const_$_L365$___ + global file _L365$___ + global file _const_$_L364$___ + global file _L364$___ + global file _const_$_L363$___ + global file _L363$___ + global file _const_$_L362$___ + global file _L362$___ + global file _const_$_L361$___ + global file _L361$___ + global file _const_$_L360$___ + global file _L360$___ + global file _const_$_L359$___ + global file _L359$___ + global file _const_$_L358$___ + global file _L358$___ + global file _const_$_L357$___ + global file _L357$___ + global file _const_$_L356$___ + global file _L356$___ + global file _const_$_L355$___ + global file _L355$___ + global file _const_$_L354$___ + global file _L354$___ + global file _const_$_L353$___ + global file _L353$___ + global file _const_$_L352$___ + global file _L352$___ + global file _const_$_L351$___ + global file _L351$___ + global file _const_$_L350$___ + global file _L350$___ + global file _const_$_L349$___ + global file _L349$___ + global file _const_$_L348$___ + global file _L348$___ + global file _const_$_L347$____ + global file _L347$____ + global file _const_$_L346$____ + global file _L346$____ + global file _const_$_L345$____ + global file _L345$____ + global file _const_$_L344$___ + global file _L344$___ + global file _const_$_L343$___ + global file _L343$___ + global file _const_$_L342$___ + global file _L342$___ + global file _const_$_L341$___ + global file _L341$___ + global file _const_$_L340$___ + global file _L340$___ + global file _const_$_L339$___ + global file _L339$___ + global file _const_$_L338$___ + global file _L338$___ + global file _const_$_L337$___ + global file _L337$___ + global file _const_$_L336$___ + global file _L336$___ + global file _const_$_L335$___ + global file _L335$___ + global file _const_$_L334$___ + global file _L334$___ + global file _const_$_L333$___ + global file _L333$___ + global file _const_$_L332$___ + global file _L332$___ + global file _const_$_L331$___ + global file _L331$___ + global file _const_$_L330$___ + global file _L330$___ + global file _const_$_L329$___ + global file _L329$___ + global file _const_$_L328$___ + global file _L328$___ + global file _const_$_L327$___ + global file _L327$___ + global file _const_$_L326$___ + global file _L326$___ + global file _const_$_L325$___ + global file _L325$___ + global file _const_$_L324$____ + global file _L324$____ + global file _const_$_L323$____ + global file _L323$____ + global file _const_$_L322$____ + global file _L322$____ + global file _L321$_slvar + global file _const_$_L320$_read_punct + global file _L320$_read_punct + global file _const_$_L319$_read_punct + global file _L319$_read_punct + global file _const_$_L318$_from_hex + global file _L318$_from_hex + global file _const_$_L317$_from_hex + global file _L317$_from_hex + global file _const_$_L314$_read_ident + global file _L314$_read_ident + global file _const_$_L313$_read_ident + global file _L313$_read_ident + global file _const_$_L312$_startswith + global file _L312$_startswith + global file _const_$_L311$_startswith + global file _L311$_startswith + global file _const_$_L310$_new_token + global file _L310$_new_token + global file _const_$_L309$_new_token + global file _L309$_new_token + global file _const_$_L308$_consume + global file _L308$_consume + global file _const_$_L307$_consume + global file _L307$_consume + global file _const_$_L306$_expected___s_ + global file _L306$_expected___s_ + global file _const_$_L305$_skip + global file _L305$_skip + global file _const_$_L304$_skip + global file _L304$_skip + global file _const_$_L303$_equal + global file _L303$_equal + global file _const_$_L302$_equal + global file _L302$_equal + global file _const_$_L301$_get_string + global file _L301$_get_string + global file _const_$_L300$_get_string + global file _L300$_get_string + global file _const_$_L299$_warn_tok + global file _L299$_warn_tok + global file _const_$_L298$_warn_tok + global file _L298$_warn_tok + global file _const_$_L297$_error_tok + global file _L297$_error_tok + global file _const_$_L296$_error_tok + global file _L296$_error_tok + global file _const_$_L293$_error_at + global file _L293$_error_at + global file _const_$_L292$_error_at + global file _L292$_error_at + global file _const_$_L291$__ + global file _L291$__ + global file _const_$_L290$___ + global file _L290$___ + global file _const_$_L289$_ + global file _L289$_ + global file _const_$_L288$___s + global file _L288$___s + global file _const_$_L287$____s_ + global file _L287$____s_ + global file _const_$_L286$__s__d__ + global file _L286$__s__d__ + global file _const_$_L281$_verror_at + global file _L281$_verror_at + global file _const_$_L280$_verror_at + global file _L280$_verror_at + global file _const_$_L279$__ + global file _L279$__ + global file _const_$_L278$_error + global file _L278$_error + global file _const_$_L277$_error + global file _L277$_error + global file has_space + global file at_bol + global file input_files + global file current_file + global file _L276$_disp + global file _L275$_disp + global file _L274$_disp + global file _L273$_disp global file _L272$_disp global file _L271$_disp global file _L270$_disp global file _L269$_disp global file _L268$_disp - global file current_fn - global file output_file global file _L267$_disp global file _L266$_disp global file _L265$_disp @@ -2724,66 +2429,64 @@ global file _L2$_disp global file _L1$_disp global file _L0$_disp - function public codegen - function file emit_text - function file emit_data - function file emit_tls_data_init - function file emit_non_tls_data_init - function file emit_data_alloc - function file assign_lvar_offsets - function file emit_type - function file get_member_name - function file get_var_interior - function file safe_to_cil_typename - function file aggregate_types - function file gen_stmt - function file gen_dummy_value - function file gen_expr - function file gen_location - function file gen_const_integer - function file gen_sizeof - function file gen_funcall - function file cast - function file getTypeId - function file cmp_zero - function file store - function file load - function file gen_make_ptr - function file gen_addr - function file gen_make_temp - function file get_cil_callsite - function file make_public_type - function file make_public_type_recursive - function file aggregate_type - function file aggregate_type_recursive - function file add_using_type - function file count - function file print - function file println + function public tokenize_file + function file convert_universal_chars + function file read_universal_char + function file remove_backslash_newline + function file canonicalize_newline + function public new_file + function public get_input_files + function file read_file + function public tokenize + function public tokenize_string_literal + function file add_line_numbers + function public convert_pp_tokens + function file convert_pp_number + function file convert_pp_int + function file read_char_literal + function file read_utf32_string_literal + function file read_utf16_string_literal + function file read_string_literal + function file string_literal_end + function file read_escaped_char + function file is_keyword + function file read_punct + function file from_hex + function file read_ident + function file startswith + function file new_token + function public consume + function public skip + function public equal + function public get_string + function public warn_tok + function public error_tok + function public error_at + function file verror_at + function public error function file WIFSIGNALED function file WIFEXITED structure public glob_t 4 - structure public tm 9 + structure public _tm_$20 9 structure public timespec 2 structure public stat 3 - enumeration public MemoryModel 3 - structure public UsingType 2 - enumeration public TypeId 12 - enumeration public AfterStmt 3 - structure public FILE 0 - structure public StringArray 3 - enumeration public ObjKind 4 - structure public EnumMember 3 - structure public VarScope 7 - structure public Scope 3 - structure public TagScope 4 - structure public Member 11 - structure public Hideset 0 - structure public File 5 - enumeration public TokenKind 7 - structure public Token 17 - enumeration public NodeKind 44 - structure public Node 31 - enumeration public TypeKind 16 - structure public Type 22 - structure public Obj 21 + structure public _tag_$19 5 + structure public _tag_$18 3 + enumeration public _MemoryModel_$17 3 + enumeration public _TokenKind_$16 7 + structure public _HashEntry_$15 3 + structure public _HashMap_$14 3 + structure public _FILE_$13 0 + structure public _Hideset_$12 0 + structure public _File_$11 6 + structure public _tag_$10 3 + structure public _StringArray_$9 3 + enumeration public _ObjKind_$8 4 + structure public _tag_$7 21 + structure public _tag_$6 11 + enumeration public _NodeKind_$5 44 + structure public _tag_$4 33 + enumeration public _TypeKind_$3 16 + structure public _tag_$2 23 + enumeration public _TokenKind_$1 7 + structure public _tag_$0 17 diff --git a/chibiar/chibiar.core.Tests/ArchiverTests.cs b/chibiar/chibiar.core.Tests/ArchiverTests.cs index 809160f..53285ed 100644 --- a/chibiar/chibiar.core.Tests/ArchiverTests.cs +++ b/chibiar/chibiar.core.Tests/ArchiverTests.cs @@ -8,15 +8,11 @@ ///////////////////////////////////////////////////////////////////////////////////// using chibicc.toolchain.Archiving; +using chibicc.toolchain.IO; using chibicc.toolchain.Logging; using NUnit.Framework; -using System; using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Text; using System.Threading.Tasks; -using chibicc.toolchain.IO; using static VerifyNUnit.Verifier; using static chibiar.ArchiverTestRunner; @@ -26,17 +22,18 @@ namespace chibiar; [Parallelizable(ParallelScope.All)] public sealed class ArchiverTests { - private static async Task VerifySymbolTableAsync(ZipArchive zip) + private static async Task VerifySymbolTableAsync(ArchiveReader archiveReader) { - var symTableEntry = zip.GetEntry(ArchiverUtilities.SymbolTableFileName)!; - using var afs = symTableEntry.Open(); + Assert.That( + archiveReader.TryOpenObjectStream(ArchiverUtilities.SymbolTableFileName, true, out var afs), + Is.True); - var tr = StreamUtilities.CreateTextReader(afs); + using var tr = StreamUtilities.CreateTextReader(afs); var actual = await tr.ReadToEndAsync(); await Verify(actual); } - + [Test] public Task ArchiveOne() { @@ -45,56 +42,52 @@ public Task ArchiveOne() logger.Information($"Test runner BasePath={basePath}"); var archivePath = Path.Combine(basePath, "output.a"); - + var archiver = new Archiver(logger); var actual = archiver.AddOrUpdate( archivePath, - new[] - { - Path.Combine(ArtifactsBasePath, "parse.o"), - }, + [ Path.Combine(ArtifactsBasePath, "parse.o"), ], true, false); - + Assert.That(actual, Is.True); - using var zip = ZipFile.OpenRead(archivePath); - + var archiveReader = new ArchiveReader(archivePath); + Assert.That( - zip.Entries.Select(e => e.Name), - Is.EqualTo(new[] { "parse.o", ArchiverUtilities.SymbolTableFileName })); + archiveReader.ObjectNames, + Is.EqualTo(new[] { ArchiverUtilities.SymbolTableFileName, "parse.o", })); - await VerifySymbolTableAsync(zip); + await VerifySymbolTableAsync(archiveReader); }); } - + [Test] public Task ArchiveTwo() { return RunAsync(async (basePath, logger) => { var archivePath = Path.Combine(basePath, "output.a"); - + var archiver = new Archiver(logger); var actual = archiver.AddOrUpdate( archivePath, - new[] - { + [ Path.Combine(ArtifactsBasePath, "parse.o"), Path.Combine(ArtifactsBasePath, "codegen.o"), - }, + ], true, false); - + Assert.That(actual, Is.True); - using var zip = ZipFile.OpenRead(archivePath); - + var archiveReader = new ArchiveReader(archivePath); + Assert.That( - zip.Entries.Select(e => e.Name), - Is.EqualTo(new[] { "parse.o", "codegen.o", ArchiverUtilities.SymbolTableFileName })); + archiveReader.ObjectNames, + Is.EqualTo(new[] { ArchiverUtilities.SymbolTableFileName, "parse.o", "codegen.o" })); - await VerifySymbolTableAsync(zip); + await VerifySymbolTableAsync(archiveReader); }); } @@ -104,45 +97,41 @@ public Task Update() return RunAsync(async (basePath, logger) => { var archivePath = Path.Combine(basePath, "output.a"); - + var newCodegenPath = Path.Combine(basePath, "codegen.o"); - + // It's made for dummy updated codegen.o. File.Copy( Path.Combine(ArtifactsBasePath, "tokenize.o"), newCodegenPath); - + var archiver = new Archiver(logger); var actual1 = archiver.AddOrUpdate( archivePath, - new[] - { + [ Path.Combine(ArtifactsBasePath, "parse.o"), Path.Combine(ArtifactsBasePath, "codegen.o"), - }, + ], true, false); - + Assert.That(actual1, Is.True); var actual2 = archiver.AddOrUpdate( archivePath, - new[] - { - newCodegenPath, - }, + [ newCodegenPath, ], true, false); - + Assert.That(actual2, Is.False); - using var zip = ZipFile.OpenRead(archivePath); - + var archiveReader = new ArchiveReader(archivePath); + Assert.That( - zip.Entries.Select(e => e.Name), - Is.EqualTo(new[] { "parse.o", "codegen.o", ArchiverUtilities.SymbolTableFileName })); + archiveReader.ObjectNames, + Is.EqualTo(new[] { ArchiverUtilities.SymbolTableFileName, "parse.o", "codegen.o", })); - await VerifySymbolTableAsync(zip); + await VerifySymbolTableAsync(archiveReader); }); } } diff --git a/chibiar/chibiar.core/Archiver.cs b/chibiar/chibiar.core/Archiver.cs index 1c9f95e..44e59ef 100644 --- a/chibiar/chibiar.core/Archiver.cs +++ b/chibiar/chibiar.core/Archiver.cs @@ -7,18 +7,15 @@ // ///////////////////////////////////////////////////////////////////////////////////// +using chibiar.Cli; +using chibicc.toolchain.Archiving; +using chibicc.toolchain.IO; +using chibicc.toolchain.Logging; using System; using System.Collections.Generic; using System.IO; -using System.IO.Compression; using System.Linq; -using System.Text; using System.Threading.Tasks; -using chibiar.Cli; -using chibicc.toolchain.Archiving; -using chibicc.toolchain.Internal; -using chibicc.toolchain.IO; -using chibicc.toolchain.Logging; namespace chibiar; @@ -29,244 +26,51 @@ public sealed class Archiver public Archiver(ILogger logger) => this.logger = logger; - private static bool IsSourceFile(string path) => - Path.GetExtension(path) is not ".o"; - - private static Stream OpenObjectStreamToCompressed(string objectFilePath) - { - var ofs = StreamUtilities.OpenStream(objectFilePath, false); - - return IsSourceFile(objectFilePath) ? - new GZipStream(ofs, CompressionLevel.Optimal) : ofs; - } - - private static string GetObjectName(string objectFilePath) => - IsSourceFile(objectFilePath) ? - (Path.GetFileNameWithoutExtension(objectFilePath) + ".o") : - Path.GetFileName(objectFilePath); - - private static bool TryAddOrUpdateObjectFiles( - string archiveFilePath, - string outputArchiveFilePath, - string[] objectFilePaths, - bool isDryrun, - out string[] outputObjectNames) - { - if (!isDryrun) - { - var objectNames = objectFilePaths. - Select(GetObjectName). - ToArray(); - - using var outputArchive = ZipFile.Open( - outputArchiveFilePath, - ZipArchiveMode.Create, - Encoding.UTF8); - - using var readArchive = File.Exists(archiveFilePath) ? - ZipFile.Open( - archiveFilePath, - ZipArchiveMode.Read, - Encoding.UTF8) : - null; - - var outputObjectNameList = new List(); - var isReplaced = new bool[objectFilePaths.Length]; - - foreach (var readEntry in - readArchive?.Entries.AsEnumerable() ?? - CommonUtilities.Empty()) - { - if (readEntry.Name != ArchiverUtilities.SymbolTableFileName) - { - outputObjectNameList.Add(readEntry.Name); - - var index = Array.IndexOf(objectNames, readEntry.Name); - if (index >= 0) - { - var objectFilePath = objectFilePaths[index]; - var objectLastWriteTime = File.GetLastWriteTime(objectFilePath); - - if (objectLastWriteTime > readEntry.LastWriteTime) - { - var objectName = objectNames[index]; - - var outputEntry = outputArchive.CreateEntry( - objectName, CompressionLevel.NoCompression); - - outputEntry.LastWriteTime = objectLastWriteTime; - - using var outputStream = outputEntry.Open(); - using var readStream = OpenObjectStreamToCompressed(objectFilePath); - - readStream.CopyTo(outputStream); - outputStream.Flush(); - - isReplaced[index] = true; - continue; - } - } - - if (readEntry.Name != ArchiverUtilities.SymbolTableFileName) - { - var outputEntry = outputArchive.CreateEntry( - readEntry.Name, CompressionLevel.NoCompression); - - outputEntry.LastWriteTime = readEntry.LastWriteTime; - - using var outputStream = outputEntry.Open(); - using var readStream = readEntry.Open(); - - readStream.CopyTo(outputStream); - outputStream.Flush(); - } - } - } - - for (var index = 0; index < objectFilePaths.Length; index++) - { - if (!isReplaced[index]) - { - var objectFilePath = objectFilePaths[index]; - var objectLastWriteTime = File.GetLastWriteTime(objectFilePath); - - var objectName = objectNames[index]; - outputObjectNameList.Add(objectName); - - var outputEntry = outputArchive.CreateEntry( - objectName, CompressionLevel.NoCompression); - - outputEntry.LastWriteTime = objectLastWriteTime; - - using var outputStream = outputEntry.Open(); - using var readStream = OpenObjectStreamToCompressed(objectFilePath); - - readStream.CopyTo(outputStream); - outputStream.Flush(); - } - } - - outputObjectNames = outputObjectNameList. - ToArray(); - return readArchive == null; - } - else - { - outputObjectNames = objectFilePaths. - Select(GetObjectName). - ToArray(); - return false; - } - } - - private static SymbolList[] GetSymbolLists( - string archiveFilePath, - string[] objectNames, - bool isDryrun) - { - var symbolLists = new SymbolList[objectNames.Length]!; - - if (!isDryrun || File.Exists(archiveFilePath)) - { - Parallel.ForEach(objectNames, - new() { MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount - 1) }, - (objectName, _, index) => - { - if (ArchiverUtilities.TryOpenArchivedObject( - archiveFilePath, - objectName, - true, - out var stream)) - { - using var _s = stream; - - var symbols = ArchiverUtilities.EnumerateSymbolsFromObjectFile(stream). - ToArray(); - - symbolLists[index] = new(objectName, symbols); - } - }); - } - else - { - for (var index = 0; index < symbolLists.Length; index++) - { - symbolLists[index] = new(objectNames[index], CommonUtilities.Empty()); - } - } - - return symbolLists; - } - - private static void AddSymbolTable( - string archiveFilePath, - SymbolList[] symbolLists, - bool isDryrun) - { - if (!isDryrun) - { - using var archive = ZipFile.Open( - archiveFilePath, - ZipArchiveMode.Update, - Encoding.UTF8); - - var symbolTableEntry = archive.CreateEntry( - ArchiverUtilities.SymbolTableFileName, - CompressionLevel.Optimal); - - using var outputStream = symbolTableEntry.Open(); - - ArchiverUtilities.WriteSymbolTable(outputStream, symbolLists); - } - else - { - ArchiverUtilities.WriteSymbolTable(new MemoryStream(), symbolLists); - } - } - internal bool AddOrUpdate( string archiveFilePath, string[] objectFilePaths, - bool isCreateSymbolTable, + bool writeSymbolTable, bool isDryrun) { - var outputArchiveFilePath = $"{archiveFilePath}_{Guid.NewGuid():N}"; + var outputArchiveFilePath = Path.Combine( + Path.GetTempPath(), + $"chibiar_{Path.GetFileNameWithoutExtension(archiveFilePath)}_{Guid.NewGuid():N}{Path.GetExtension(archiveFilePath)}"); try { - if (TryAddOrUpdateObjectFiles( + var isExistArchiveFile = File.Exists(archiveFilePath); + + var symbolListEntries = ArchiverUtilities.GetCombinedSymbolListEntries( archiveFilePath, - outputArchiveFilePath, - objectFilePaths, - isDryrun, - out var outputObjectNames)) + objectFilePaths); + + using (var outputArchiveFileStream = isDryrun ? + new NullStream() : + StreamUtilities.OpenStream(outputArchiveFilePath, true)) { - var symbolLists = GetSymbolLists( - outputArchiveFilePath, - outputObjectNames, - isDryrun); + ArchiverUtilities.WriteArchive( + outputArchiveFileStream, + symbolListEntries, + archiveFilePath, + writeSymbolTable); + } - if (isCreateSymbolTable) - { - AddSymbolTable( - outputArchiveFilePath, - symbolLists, - isDryrun); - } - + if (!isDryrun) + { File.Delete(archiveFilePath); File.Move(outputArchiveFilePath, archiveFilePath); - - return true; } + + return !isExistArchiveFile; } catch { - File.Delete(outputArchiveFilePath); + if (!isDryrun) + { + File.Delete(outputArchiveFilePath); + } throw; } - - return false; } internal void Extract( @@ -274,30 +78,34 @@ internal void Extract( string[] objectNames, bool isDryrun) { - if (!isDryrun || File.Exists(archiveFilePath)) + var hashedObjectNames = new HashSet(objectNames); + var descriptors = ArchiverUtilities.LoadArchivedObjectItemDescriptors( + archiveFilePath, aod => hashedObjectNames.Contains(aod.ObjectName) ? aod : null). + ToArray(); + + Parallel.ForEach(descriptors, + descriptor => + { + var aod = (ArchivedObjectItemDescriptor)descriptor; + + using var archiveFileStream = StreamUtilities.OpenStream(archiveFilePath, false); + + archiveFileStream.Position = aod.Position; + var objectStream = new RangedStream( + archiveFileStream, aod.Length, false); + + using var outputObjectFileStream = isDryrun ? + new NullStream() : + StreamUtilities.OpenStream(aod.ObjectName, true); + objectStream.CopyTo(outputObjectFileStream); + outputObjectFileStream.Flush(); + }); + + foreach (var exceptName in descriptors. + Select(aod => aod!.ObjectName). + Except(objectNames)) { - Parallel.ForEach(objectNames, - new() { MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount - 1) }, - objectName => - { - if (ArchiverUtilities.TryOpenArchivedObject( - archiveFilePath, - objectName, - false, - out var inputStream)) - { - using var outputStream = isDryrun ? - new MemoryStream() : - StreamUtilities.OpenStream(objectName, true); - - inputStream.CopyTo(outputStream); - outputStream.Flush(); - } - else - { - this.logger.Error($"Object is not found: {objectName}"); - } - }); + this.logger.Error($"Object is not found: {exceptName}"); } } @@ -305,24 +113,14 @@ internal void List( string archiveFilePath, string[] objectNames) { - if (objectNames.Length >= 1) - { - var existObjectNames = new HashSet( - ArchiverUtilities.EnumerateArchivedObjectNames(archiveFilePath)); + var hashedObjectNames = new HashSet(objectNames); + var descriptors = ArchiverUtilities.LoadArchivedObjectItemDescriptors( + archiveFilePath, aod => hashedObjectNames.Contains(aod.ObjectName) ? aod : null). + ToArray(); - foreach (var objectName in objectNames. - Where(existObjectNames.Contains)) - { - Console.WriteLine(objectName); - } - } - else + foreach (var descriptor in descriptors) { - foreach (var objectName in - ArchiverUtilities.EnumerateArchivedObjectNames(archiveFilePath)) - { - Console.WriteLine(objectName); - } + Console.WriteLine(descriptor.ObjectName); } } diff --git a/chibild/chibild.core/Generating/ArchivedObjectInputFragment.cs b/chibild/chibild.core/Generating/ArchivedObjectInputFragment.cs index 1b8b843..de5243e 100644 --- a/chibild/chibild.core/Generating/ArchivedObjectInputFragment.cs +++ b/chibild/chibild.core/Generating/ArchivedObjectInputFragment.cs @@ -238,7 +238,7 @@ public static ArchivedObjectInputFragment[] Load( { logger.Information($"Loading symbol table: {relativePath}"); - var symbolLists = ArchiverUtilities.EnumerateSymbolTable( + var symbolLists = ArchiverUtilities.EnumerateSymbolListFromArchive( Path.Combine(baseInputPath, relativePath)); return symbolLists.Select(symbolList => diff --git a/chibild/chibild.core/Internal/Utilities.cs b/chibild/chibild.core/Internal/Utilities.cs index f457e51..9ac0f37 100644 --- a/chibild/chibild.core/Internal/Utilities.cs +++ b/chibild/chibild.core/Internal/Utilities.cs @@ -56,19 +56,6 @@ public static bool TryAdd( } #endif -#if NET45 || NET461 - public static IEnumerable Prepend( - this IEnumerable enumerable, - T value) - { - yield return value; - foreach (var item in enumerable) - { - yield return item; - } - } -#endif - #if NET45 || NET461 || NETSTANDARD2_0 public static HashSet ToHashSet(this IEnumerable enumerable) => new(enumerable); diff --git a/toolchain.common/Archiving/ArchiveObjectStream.cs b/toolchain.common/Archiving/ArchiveObjectStream.cs deleted file mode 100644 index 6707664..0000000 --- a/toolchain.common/Archiving/ArchiveObjectStream.cs +++ /dev/null @@ -1,62 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////// -// -// chibicc-toolchain - The specialized backend toolchain for chibicc-cil -// Copyright (c) Kouji Matsui(@kozy_kekyo, @kekyo @mastodon.cloud) -// -// Licensed under MIT: https://opensource.org/licenses/MIT -// -///////////////////////////////////////////////////////////////////////////////////// - -using System; -using System.IO; -using System.IO.Compression; - -namespace chibicc.toolchain.Archiving; - -internal sealed class ArchiveObjectStream : Stream -{ - // Automatic closer for parent ZipArchive. - - private readonly ZipArchive archive; - private readonly Stream parent; - - public ArchiveObjectStream(ZipArchive archive, Stream parent) - { - this.archive = archive; - this.parent = parent; - } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - this.parent.Dispose(); - this.archive.Dispose(); - } - - public override bool CanRead => true; - public override bool CanSeek => false; - public override bool CanWrite => false; - public override long Length => throw new NotImplementedException(); - - public override long Position - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - public override void Flush() - { - } - - public override int Read(byte[] buffer, int offset, int count) => - this.parent.Read(buffer, offset, count); - - public override long Seek(long offset, SeekOrigin origin) => - throw new System.NotImplementedException(); - - public override void SetLength(long value) => - throw new System.NotImplementedException(); - - public override void Write(byte[] buffer, int offset, int count) => - throw new System.NotImplementedException(); -} diff --git a/toolchain.common/Archiving/ArchiveReader.cs b/toolchain.common/Archiving/ArchiveReader.cs new file mode 100644 index 0000000..7126fab --- /dev/null +++ b/toolchain.common/Archiving/ArchiveReader.cs @@ -0,0 +1,77 @@ +///////////////////////////////////////////////////////////////////////////////////// +// +// chibicc-toolchain - The specialized backend toolchain for chibicc-cil +// Copyright (c) Kouji Matsui(@kozy_kekyo, @kekyo @mastodon.cloud) +// +// Licensed under MIT: https://opensource.org/licenses/MIT +// +///////////////////////////////////////////////////////////////////////////////////// + +using chibicc.toolchain.IO; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; + +namespace chibicc.toolchain.Archiving; + +public sealed class ArchiveReader +{ + private readonly string archiveFilePath; + private readonly Dictionary aods; + + public ArchiveReader( + string archiveFilePath) + { + this.archiveFilePath = archiveFilePath; + var descriptors = ArchiverUtilities.LoadArchivedObjectItemDescriptors( + this.archiveFilePath, aod => aod); + this.ObjectNames = descriptors. + Select(d => d.ObjectName). + ToArray(); + this.aods = descriptors. + ToDictionary(d => d.ObjectName, d => (ArchivedObjectItemDescriptor)d); + } + + public ArchiveReader( + string archiveFilePath, + IEnumerable objectNames) + { + this.archiveFilePath = archiveFilePath; + var hashedObjectNames = new HashSet(objectNames); + var descriptors = ArchiverUtilities.LoadArchivedObjectItemDescriptors( + this.archiveFilePath, aod => hashedObjectNames.Contains(aod.ObjectName) ? aod : null); + this.ObjectNames = descriptors. + Select(d => d.ObjectName). + ToArray(); + this.aods = descriptors. + ToDictionary(d => d.ObjectName, d => (ArchivedObjectItemDescriptor)d); + } + + public IReadOnlyList ObjectNames { get; } + + public bool TryOpenObjectStream( + string objectName, + bool decodeBody, + out Stream stream) + { + if (!this.aods.TryGetValue(objectName, out var aod)) + { + stream = null!; + return false; + } + + var archiveFileStream = StreamUtilities.OpenStream( + this.archiveFilePath, + false); + archiveFileStream.Position = aod.Position; + var rangedStream = new RangedStream( + archiveFileStream, + aod.Length, + false); + stream = decodeBody ? + new GZipStream(rangedStream, CompressionMode.Decompress) : + rangedStream; + return true; + } +} diff --git a/toolchain.common/Archiving/ArchiverUtilities.cs b/toolchain.common/Archiving/ArchiverUtilities.cs index 1cfa8e5..1621c77 100644 --- a/toolchain.common/Archiving/ArchiverUtilities.cs +++ b/toolchain.common/Archiving/ArchiverUtilities.cs @@ -7,25 +7,74 @@ // ///////////////////////////////////////////////////////////////////////////////////// -using System; using chibicc.toolchain.Internal; +using chibicc.toolchain.IO; using chibicc.toolchain.Parsing; using chibicc.toolchain.Tokenizing; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; -using System.Text; -using chibicc.toolchain.IO; +using System.Threading.Tasks; namespace chibicc.toolchain.Archiving; +public interface IObjectItemDescriptor +{ + int Length { get; } + string ObjectName { get; } +} + +public sealed class ArchivedObjectItemDescriptor : IObjectItemDescriptor +{ + public long Position { get; private set; } + public int Length { get; } + public string ObjectName { get; } + + internal ArchivedObjectItemDescriptor(long relativePosition, int length, string objectName) + { + this.Position = relativePosition; + this.Length = length; + this.ObjectName = objectName; + } + + internal void AdjustPosition(long basePosition) => + this.Position += basePosition; +} + +public sealed class ObjectFileDescriptor : IObjectItemDescriptor +{ + public int Length { get; } + public string Path { get; } + public string ObjectName => + ArchiverUtilities.GetObjectName(this.Path); + + internal ObjectFileDescriptor(int length, string path) + { + this.Length = length; + this.Path = path; + } +} + +public record struct SymbolListEntry( + IObjectItemDescriptor Descriptor, + SymbolList SymbolList); + public static class ArchiverUtilities { public static readonly string SymbolTableFileName = "__.SYMDEF"; + public static bool IsSourceFile(string path) => + Path.GetExtension(path) is not ".o"; + + public static string GetObjectName(string objectFilePath) => + IsSourceFile(objectFilePath) ? + (Path.GetFileNameWithoutExtension(objectFilePath) + ".o") : + Path.GetFileName(objectFilePath); + private enum ObjectSymbolStates { Idle, @@ -33,7 +82,7 @@ private enum ObjectSymbolStates Structure, } - private static IEnumerable InternalEnumerateSymbolsFromObjectFile( + private static IEnumerable InternalEnumerateSymbolsFromObjectFileStream( Stream objectFileStream) { var tr = StreamUtilities.CreateTextReader(objectFileStream); @@ -133,47 +182,306 @@ tokens[0] is (TokenTypes.Identity, _)) } } - public static IEnumerable EnumerateSymbolsFromObjectFile( + private static IEnumerable EnumerateSymbolsFromObjectFileStream( Stream objectFileStream) => - InternalEnumerateSymbolsFromObjectFile(objectFileStream). + InternalEnumerateSymbolsFromObjectFileStream(objectFileStream). Distinct(); + + //////////////////////////////////////////////////////////////////// + + private static Stream ToCompressedObjectStream( + Stream objectFileStream, + string referenceObjectFilePath) + { + if (!IsSourceFile(referenceObjectFilePath)) + { + return objectFileStream; + } + var gzs = new GZipStream(objectFileStream, CompressionLevel.Optimal); + var ms = new MemoryStream(); + gzs.CopyTo(ms); + objectFileStream.Dispose(); + ms.Position = 0; + return ms; + } + + private static Stream OpenCompressedObjectStream(string objectFilePath) + { + var ofs = StreamUtilities.OpenStream(objectFilePath, false); + return ToCompressedObjectStream(ofs, objectFilePath); + } + + private static Stream ToDecompressedObjectStream( + Stream objectFileStream, + string referenceObjectFilePath) + { + if (IsSourceFile(referenceObjectFilePath)) + { + return objectFileStream; + } + var gzs = new GZipStream(objectFileStream, CompressionMode.Decompress); + var ms = new MemoryStream(); + gzs.CopyTo(ms); + objectFileStream.Dispose(); + ms.Position = 0; + return ms; + } + + private static Stream OpenDecompressedObjectStream(string objectFilePath) + { + var ofs = StreamUtilities.OpenStream(objectFilePath, false); + return ToDecompressedObjectStream(ofs, objectFilePath); + } + + //////////////////////////////////////////////////////////////////// + + private static IEnumerable EnumerateArchivedObjectItemDescriptors( + Stream archiveFileStream) + { + var ler = new LittleEndianReader(archiveFileStream); + var relativePosition = 0; + while (true) + { + if (!ler.TryReadString(256, out var objectName)) + { + throw new FormatException( + $"Invalid object naming: Position={ler.Position?.ToString() ?? "(Unknown)"}"); + } + if (objectName.Length == 0) + { + // Detected termination. + break; + } + if (!ler.TryReadInt32(out var length)) + { + throw new FormatException( + $"Invalid object length: Position={ler.Position?.ToString() ?? "(Unknown)"}"); + } + yield return new(relativePosition, length, objectName); + relativePosition += length; + } + } + + public static IObjectItemDescriptor[] LoadArchivedObjectItemDescriptors( + string archiveFilePath, + Func selector) + { + using var archiveFileStream = StreamUtilities.OpenStream(archiveFilePath, false); + var descriptors = EnumerateArchivedObjectItemDescriptors(archiveFileStream). + Select(aod => selector(aod)!). + Where(d => d != null). + ToArray(); + var archiveFileBasePosition = archiveFileStream.Position; + foreach (var descriptor in descriptors) + { + if (descriptor is ArchivedObjectItemDescriptor aod) + { + aod.AdjustPosition(archiveFileBasePosition); + } + } + return descriptors; + } + + public static SymbolListEntry[] GetCombinedSymbolListEntries( + string archiveFilePath, + string[] objectFilePaths) + { + var archivedObjectItems = CommonUtilities.Empty(); + + if (File.Exists(archiveFilePath)) + { + var hashedObjectNames = objectFilePaths.ToDictionary(GetObjectName); + archivedObjectItems = LoadArchivedObjectItemDescriptors( + archiveFilePath, + aod => hashedObjectNames.TryGetValue(aod.ObjectName, out var path) ? + new ObjectFileDescriptor(-1, path) : // Will update object file + aod.ObjectName == SymbolTableFileName ? + null : // Will ignore symbol table + aod); // Archived object file + } + + var willAddObjectFileItems = objectFilePaths. + Except(archivedObjectItems. + OfType(). + Select(d => d.Path)). + Select(path => new ObjectFileDescriptor(-1, path)). + ToArray(); + + var symbolListEntries = new SymbolListEntry[ + archivedObjectItems.Length + willAddObjectFileItems.Length]; - public static void WriteSymbolTable( + Parallel.ForEach( + archivedObjectItems.Concat(willAddObjectFileItems), + (entry, _, index) => + { + switch (entry) + { + case ObjectFileDescriptor ofd: + using (var objectRawStream = StreamUtilities.OpenStream(ofd.Path, false)) + { + var length = objectRawStream.Length; + var objectStream = ToDecompressedObjectStream(objectRawStream, ofd.Path); + var symbols = EnumerateSymbolsFromObjectFileStream(objectStream). + ToArray(); + symbolListEntries[index] = new( + new ObjectFileDescriptor((int)length, ofd.Path), + new(ofd.ObjectName, symbols)); + } + break; + case ArchivedObjectItemDescriptor aod: + using (var archiveFileStream = StreamUtilities.OpenStream(archiveFilePath!, false)) + { + archiveFileStream.Position = aod.Position; + var objectStream = ToDecompressedObjectStream( + new RangedStream(archiveFileStream, aod.Length, false), + aod.ObjectName); + var symbols = EnumerateSymbolsFromObjectFileStream(objectStream). + ToArray(); + symbolListEntries[index] = new(aod, new(aod.ObjectName, symbols)); + } + break; + } + }); + + return symbolListEntries; + } + + //////////////////////////////////////////////////////////////////// + + private static void WriteSymbolTable( Stream symbolTableStream, - SymbolList[] symbolLists) + IEnumerable symbolLists) { var tw = StreamUtilities.CreateTextWriter(symbolTableStream); - foreach (var symbolList in symbolLists) { - tw.WriteLine($".object {symbolList.ObjectName}"); - + tw.WriteLine( + $".object {symbolList.ObjectName}"); foreach (var symbol in symbolList.Symbols.Distinct()) { - tw.WriteLine($" {symbol.Directive} {symbol.Scope} {symbol.Name}{(symbol.MemberCount is { } mc ? $" {mc}" : "")}"); + tw.WriteLine( + $" {symbol.Directive} {symbol.Scope} {symbol.Name}{(symbol.MemberCount is { } mc ? $" {mc}" : "")}"); } } - tw.Flush(); } - public static IEnumerable EnumerateSymbolTable( + private static byte[] CreateSymbolTableImage( + IEnumerable symbolListEntries) + { + var symbolTableStream = new MemoryStream(); + using (var compressedStream = new GZipStream(symbolTableStream, CompressionLevel.Fastest)) + { + WriteSymbolTable( + compressedStream, + symbolListEntries.Select(entry => entry.SymbolList)); + compressedStream.Flush(); + } + return symbolTableStream.ToArray(); + } + + //////////////////////////////////////////////////////////////////// + + private static void WriteObjectItemDescriptors( + Stream outputArchiveFileStream, + IEnumerable descriptors) + { + var lew = new LittleEndianWriter(outputArchiveFileStream); + foreach (var descriptor in descriptors) + { + lew.Write(descriptor.ObjectName); + lew.Write(descriptor.Length); + } + lew.Write(string.Empty); // Termination + } + + private static void WriteObjectItemBodies( + Stream outputArchiveFileStream, + string readArchiveFilePath, + IEnumerable descriptors) + { + foreach (var descriptor in descriptors) + { + switch (descriptor) + { + case ObjectFileDescriptor ofd: + using (var objectFileStream = OpenCompressedObjectStream(ofd.Path)) + { + objectFileStream.CopyTo(outputArchiveFileStream); + } + break; + case ArchivedObjectItemDescriptor aod: + using (var archiveFileStream = StreamUtilities.OpenStream(readArchiveFilePath, false)) + { + archiveFileStream.Position = aod.Position; + var objectStream = new RangedStream(archiveFileStream, aod.Length, false); + objectStream.CopyTo(outputArchiveFileStream); + } + break; + } + } + } + + private sealed class SymbolTableDescriptor(int length) : IObjectItemDescriptor + { + public int Length => + length; + public string ObjectName => + SymbolTableFileName; + } + + public static void WriteArchive( + Stream outputArchiveFileStream, + SymbolListEntry[] symbolListEntries, + string readArchiveFilePath, + bool writeSymbolTable) + { + if (writeSymbolTable) + { + var symbolTableStream = new MemoryStream( + CreateSymbolTableImage(symbolListEntries)); + + WriteObjectItemDescriptors( + outputArchiveFileStream, + symbolListEntries. + Select(entry => entry.Descriptor). + Prepend(new SymbolTableDescriptor((int)symbolTableStream.Length))); + + symbolTableStream.CopyTo(outputArchiveFileStream); + } + else + { + WriteObjectItemDescriptors( + outputArchiveFileStream, + symbolListEntries.Select(entry => entry.Descriptor)); + } + + WriteObjectItemBodies( + outputArchiveFileStream, + readArchiveFilePath, + symbolListEntries.Select(entry => entry.Descriptor)); + + outputArchiveFileStream.Flush(); + } + + //////////////////////////////////////////////////////////////////// + + public static IEnumerable EnumerateSymbolListFromArchive( string archiveFilePath) { - using var archive = ZipFile.Open( - archiveFilePath, - ZipArchiveMode.Read, - Encoding.UTF8); + var archiveReader = new ArchiveReader( + archiveFilePath, [ SymbolTableFileName ]); - if (archive.GetEntry(SymbolTableFileName) is { } entry) + if (archiveReader.TryOpenObjectStream( + SymbolTableFileName, true, out var symbolTableStream)) { - using var stream = entry.Open(); - var tr = StreamUtilities.CreateTextReader(stream); + var tr = StreamUtilities.CreateTextReader(symbolTableStream); Token? currentObjectName = null; var symbols = new List(); - - foreach (var tokens in CilTokenizer.TokenizeAll("", SymbolTableFileName, tr). + + foreach (var tokens in CilTokenizer.TokenizeAll( + "", SymbolTableFileName, tr). Where(tokens => tokens.Length >= 2)) { switch (tokens[0]) @@ -194,12 +502,10 @@ when tokens[1] is (TokenTypes.Identity, _): // enumeration public enumbaz 3 // structure public structhoge 5 case (TokenTypes.Identity, var directive) - when tokens.Length >= 3 && - tokens[1] is (TokenTypes.Identity, var scope) && - CommonUtilities.TryParseEnum(scope, out _) && - tokens[2] is (TokenTypes.Identity, var name): - if (tokens.Length >= 4 && - tokens[3] is (TokenTypes.Identity, var mc) && + when tokens is [_, (TokenTypes.Identity, var scope), _, ..] && + CommonUtilities.TryParseEnum(scope, out _) && + tokens[2] is (TokenTypes.Identity, var name): + if (tokens is [_, _, _, (TokenTypes.Identity, var mc), ..] && int.TryParse(mc, NumberStyles.Integer, CultureInfo.InvariantCulture, out var memberCount) && memberCount >= 0) { @@ -212,7 +518,6 @@ tokens[3] is (TokenTypes.Identity, var mc) && break; } } - if (currentObjectName is var (_, con2)) { yield return new( @@ -222,54 +527,15 @@ tokens[3] is (TokenTypes.Identity, var mc) && } } - public static IEnumerable EnumerateArchivedObjectNames( - string archiveFilePath) - { - using var archive = ZipFile.Open( - archiveFilePath, - ZipArchiveMode.Read, - Encoding.UTF8); - - foreach (var entry in archive.Entries. - Where(entry => entry.Name != SymbolTableFileName)) - { - yield return entry.Name; - } - } - public static bool TryOpenArchivedObject( string archiveFilePath, string objectName, - bool is_decoded_body, + bool decodedBody, out Stream stream) { - var archive = ZipFile.Open( - archiveFilePath, - ZipArchiveMode.Read, - Encoding.UTF8); - - try - { - if (archive.GetEntry(objectName) is { } entry) - { - var ofs = is_decoded_body ? - new GZipStream(entry.Open(), CompressionMode.Decompress) : - entry.Open(); - - stream = new ArchiveObjectStream(archive, ofs); - return true; - } - else - { - archive.Dispose(); - stream = null!; - return false; - } - } - catch - { - archive.Dispose(); - throw; - } + var archiveReader = new ArchiveReader( + archiveFilePath, [ objectName ]); + return archiveReader.TryOpenObjectStream( + objectName, decodedBody, out stream); } } diff --git a/toolchain.common/IO/LittleEndianReader.cs b/toolchain.common/IO/LittleEndianReader.cs new file mode 100644 index 0000000..f98ce33 --- /dev/null +++ b/toolchain.common/IO/LittleEndianReader.cs @@ -0,0 +1,116 @@ +///////////////////////////////////////////////////////////////////////////////////// +// +// chibicc-toolchain - The specialized backend toolchain for chibicc-cil +// Copyright (c) Kouji Matsui(@kozy_kekyo, @kekyo @mastodon.cloud) +// +// Licensed under MIT: https://opensource.org/licenses/MIT +// +///////////////////////////////////////////////////////////////////////////////////// + +using chibicc.toolchain.Internal; +using System.Collections.Generic; +using System.IO; + +namespace chibicc.toolchain.IO; + +internal sealed class LittleEndianReader +{ + private readonly Stream parent; + + public LittleEndianReader(Stream parent) => + this.parent = parent; + + public long? Position => + this.parent.CanSeek ? this.parent.Position : null; + + private int ReadByte() => + this.parent.ReadByte(); + + public bool TryReadByte(out byte value) + { + var ch = this.ReadByte(); + if (ch == -1) + { + value = 0; + return false; + } + value = (byte)ch; + return true; + } + + public bool TryReadInt16(out short value) + { + ushort v = 0; + for (var i = 0; i < sizeof(short); i++) + { + var ch = this.ReadByte(); + if (ch == -1) + { + value = 0; + return false; + } + v |= (ushort)(((ushort)ch) << (i * 8)); + } + value = (short)v; + return true; + } + + public bool TryReadInt32(out int value) + { + uint v = 0; + for (var i = 0; i < sizeof(int); i++) + { + var ch = this.ReadByte(); + if (ch == -1) + { + value = 0; + return false; + } + v |= (uint)(((uint)ch) << (i * 8)); + } + value = (int)v; + return true; + } + + public bool TryReadInt64(out long value) + { + ulong v = 0; + for (var i = 0; i < sizeof(long); i++) + { + var ch = this.ReadByte(); + if (ch == -1) + { + value = 0; + return false; + } + v |= (ulong)(((ulong)ch) << (i * 8)); + } + value = (long)v; + return true; + } + + public bool TryReadString(int maxLength, out string value) + { + if (maxLength >= 1) + { + var buffer = new List(maxLength); + while (buffer.Count < maxLength) + { + var ch = this.parent.ReadByte(); + if (ch == -1) + { + value = null!; + return false; + } + if (ch == 0) + { + value = CommonUtilities.UTF8.GetString(buffer.ToArray()); + return true; + } + buffer.Add((byte)ch); + } + } + value = null!; + return false; + } +} diff --git a/toolchain.common/IO/LittleEndianWriter.cs b/toolchain.common/IO/LittleEndianWriter.cs new file mode 100644 index 0000000..a7c6eb5 --- /dev/null +++ b/toolchain.common/IO/LittleEndianWriter.cs @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////////////// +// +// chibicc-toolchain - The specialized backend toolchain for chibicc-cil +// Copyright (c) Kouji Matsui(@kozy_kekyo, @kekyo @mastodon.cloud) +// +// Licensed under MIT: https://opensource.org/licenses/MIT +// +///////////////////////////////////////////////////////////////////////////////////// + +using chibicc.toolchain.Internal; +using System.IO; + +namespace chibicc.toolchain.IO; + +internal sealed class LittleEndianWriter +{ + private readonly Stream parent; + private readonly byte[] buffer = new byte[8]; + + public LittleEndianWriter(Stream parent) => + this.parent = parent; + + public void Write(byte value) + { + this.buffer[0] = value; + this.parent.Write(this.buffer, 0, sizeof(byte)); + } + + public void Write(short value) + { + for (var i = 0; i < sizeof(short); i++) + { + this.buffer[i] = (byte)value; + value >>= 8; + } + this.parent.Write(this.buffer, 0, sizeof(short)); + } + + public void Write(int value) + { + for (var i = 0; i < sizeof(int); i++) + { + this.buffer[i] = (byte)value; + value >>= 8; + } + this.parent.Write(this.buffer, 0, sizeof(int)); + } + + public void Write(long value) + { + for (var i = 0; i < sizeof(long); i++) + { + this.buffer[i] = (byte)value; + value >>= 8; + } + this.parent.Write(this.buffer, 0, sizeof(long)); + } + + public void Write(string value) + { + var bytes = CommonUtilities.UTF8.GetBytes(value); + this.parent.Write(bytes, 0, bytes.Length); + this.buffer[0] = 0; + this.parent.Write(this.buffer, 0, sizeof(byte)); + } + + public void Write(byte[] buffer, int offset, int length) => + this.parent.Write(buffer, offset, length); + + public void Flush() => + this.parent.Flush(); +} diff --git a/toolchain.common/IO/NullStream.cs b/toolchain.common/IO/NullStream.cs new file mode 100644 index 0000000..0936c0d --- /dev/null +++ b/toolchain.common/IO/NullStream.cs @@ -0,0 +1,52 @@ +///////////////////////////////////////////////////////////////////////////////////// +// +// chibicc-toolchain - The specialized backend toolchain for chibicc-cil +// Copyright (c) Kouji Matsui(@kozy_kekyo, @kekyo @mastodon.cloud) +// +// Licensed under MIT: https://opensource.org/licenses/MIT +// +///////////////////////////////////////////////////////////////////////////////////// + +using System; +using System.IO; + +namespace chibicc.toolchain.IO; + +internal sealed class NullStream : Stream +{ + public NullStream() + { + } + + public override bool CanRead => + true; + public override bool CanSeek => + false; + public override bool CanWrite => + true; + + public override long Length => + throw new InvalidOperationException(); + + public override long Position + { + get => throw new InvalidOperationException(); + set => throw new InvalidOperationException(); + } + + public override int Read(byte[] buffer, int offset, int count) => + 0; + + public override void Write(byte[] buffer, int offset, int count) + { + } + + public override void Flush() + { + } + + public override long Seek(long offset, SeekOrigin origin) => + throw new InvalidOperationException(); + public override void SetLength(long value) => + throw new InvalidOperationException(); +} diff --git a/toolchain.common/IO/RangeStream.cs b/toolchain.common/IO/RangeStream.cs new file mode 100644 index 0000000..2ed03b0 --- /dev/null +++ b/toolchain.common/IO/RangeStream.cs @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////////////// +// +// chibicc-toolchain - The specialized backend toolchain for chibicc-cil +// Copyright (c) Kouji Matsui(@kozy_kekyo, @kekyo @mastodon.cloud) +// +// Licensed under MIT: https://opensource.org/licenses/MIT +// +///////////////////////////////////////////////////////////////////////////////////// + +using System; +using System.IO; +using System.Threading; + +namespace chibicc.toolchain.IO; + +internal sealed class RangedStream : Stream +{ + private readonly bool leaveOpen; + private Stream parent; + private long position; + + public RangedStream(Stream parent, long length, bool leaveOpen) + { + this.parent = parent; + this.Length = length; + this.leaveOpen = leaveOpen; + } + + public override bool CanRead => + true; + public override bool CanSeek => + false; + public override bool CanWrite => + false; + + public override long Length { get; } + public override long Position + { + get => this.position; + set => throw new InvalidOperationException(); + } + + public override void Close() + { + if (!this.leaveOpen) + { + if (Interlocked.Exchange(ref this.parent, null!) is { } parent) + { + parent.Dispose(); + } + } + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + this.Close(); + } + } + + public override int Read(byte[] buffer, int offset, int count) + { + var remains = (int)Math.Min(count, this.Length - this.position); + if (remains == 0) + { + return 0; + } + + var read = this.parent.Read(buffer, offset, remains); + + this.position += read; + return read; + } + + public override void Flush() + { + } + + public override long Seek(long offset, SeekOrigin origin) => + throw new InvalidOperationException(); + public override void SetLength(long value) => + throw new InvalidOperationException(); + public override void Write(byte[] buffer, int offset, int count) => + throw new InvalidOperationException(); +} diff --git a/toolchain.common/IO/StreamUtilities.cs b/toolchain.common/IO/StreamUtilities.cs index 3c5c4df..9b7a4c5 100644 --- a/toolchain.common/IO/StreamUtilities.cs +++ b/toolchain.common/IO/StreamUtilities.cs @@ -10,13 +10,12 @@ using System; using System.IO; using System.Text; +using chibicc.toolchain.Internal; namespace chibicc.toolchain.IO; public static class StreamUtilities { - private static readonly Encoding utf8 = new UTF8Encoding(false); - public static Stream OpenStream(string path, bool writable) => (path == "-") ? (writable ? Console.OpenStandardOutput() : Console.OpenStandardInput()) : @@ -28,8 +27,8 @@ public static Stream OpenStream(string path, bool writable) => 1024 * 1024); public static TextReader CreateTextReader(Stream stream) => - new StreamReader(stream, utf8, true); + new StreamReader(stream, CommonUtilities.UTF8, true); public static TextWriter CreateTextWriter(Stream stream) => - new StreamWriter(stream, utf8); + new StreamWriter(stream, CommonUtilities.UTF8); } diff --git a/toolchain.common/Internal/CommonUtilities.cs b/toolchain.common/Internal/CommonUtilities.cs index 13f238b..9caf6cc 100644 --- a/toolchain.common/Internal/CommonUtilities.cs +++ b/toolchain.common/Internal/CommonUtilities.cs @@ -10,6 +10,7 @@ using System; using System.Globalization; using System.IO; +using System.Text; #if NET45 || NET461 using System.Collections.Generic; @@ -52,6 +53,8 @@ internal static class CommonUtilities { private static readonly IFormatProvider invariantCulture = CultureInfo.InvariantCulture; + public static readonly Encoding UTF8 = new UTF8Encoding(false); + public static readonly bool IsInWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; @@ -73,6 +76,19 @@ public static T[] Empty() => Array.Empty(); #endif +#if NET40 || NET45 || NET461 + public static IEnumerable Prepend( + this IEnumerable enumerable, + T value) + { + yield return value; + foreach (var item in enumerable) + { + yield return item; + } + } +#endif + public static bool TryParseUInt8( string word, out byte value) =>