@@ -2968,6 +2968,9 @@ func void print_coff(struct string output_file_path, struct memory_arena *arena,
29682968 }
29692969 }
29702970
2971+ #undef begin_id_record
2972+ #undef end_id_record
2973+
29712974 ipi_stream_header -> byte_count_of_type_record_data_following_the_header = (u32 )(arena_current (& ipi_stream ) - (u8 * )(ipi_stream_header + 1 ));
29722975 ipi_stream_header -> one_past_last_type_index = id_index_at ;
29732976
@@ -3027,211 +3030,155 @@ func void print_coff(struct string output_file_path, struct memory_arena *arena,
30273030 stream_emit_struct (context , ipi_stream .base , arena_current (& ipi_stream ) - ipi_stream .base );
30283031 }
30293032
3030-
3033+ //
3034+ // We for now just have a single module stream.
3035+ // I don't really see a reason to have multiple.
3036+ // And we don't have to duplicate things like file tables if we only have one.
3037+ //
30313038
30323039 u32 module_stream_symbol_size ;
30333040 u32 module_stream_line_info_size ;
30343041
3035- begin_counter (timing , module_stream );
3036- // stream > 12: Module streams
3037- { // :module_streams
3038- set_current_stream (context , STREAM_module_zero );
3039- // module layout:
3040- // u32 signature; always 4
3041- // u8 symbols[symbol_byte_size - 4];
3042- // u8 line_information[line_info_byte_size]
3043- // u32 global_refs_byte_size;
3044- // u8 global_refs[global_refs_byte_size]
3042+ struct string module_object_name_full_path = push_format_string (scratch , "%.*s.obj" , root_file_name .size , root_file_name .data );
3043+ replace_characters (module_object_name_full_path , "/" , '\\' );
3044+
3045+ struct memory_arena module_stream = create_memory_arena (giga_bytes (4 ), 2.0f , 0 );
3046+
3047+ { // Module streams :module_streams
3048+ //
3049+ // Module stream layout:
3050+ //
3051+ // u32 signature;
3052+ // u8 symbols[symbol_byte_size - 4];
3053+ // u8 line_information[line_info_byte_size];
3054+ // u32 global_refs_byte_size;
3055+ // u8 global_refs[global_refs_byte_size];
3056+ //
30453057
3046- struct pdb_location module_stream_begin = get_current_pdb_location (context );
3047- context -> module_stream_begin = module_stream_begin ;
3058+ * push_struct (& module_stream , u32 ) = /*CV_SIGNATURE_C13*/ 4 ;
30483059
3049- out_int (4 , u32 ); // signature
3060+ #define begin_symbol_record (record_kind ) { current_symbol_record = push_struct(&module_stream, struct codeview_type_record_header); current_symbol_record->kind = (record_kind); }
3061+ #define end_symbol_record () { push_f3f2f1_align(&module_stream, sizeof(u32)); current_symbol_record->length = to_u16(arena_current(&module_stream) - (u8 *)¤t_symbol_record->kind); }
30503062
3051- // first thing is always the OBJNAME, then the COMPILE3
3063+ struct codeview_type_record_header * current_symbol_record ;
30523064
3053- begin_symbol (0x1101 );{ // OBJNAME
3054- out_int (0 , u32 ); // signature
3055- char module_string [] = "l:\\l++\\build\\test.obj" ;
3056- out_struct (module_string ); // obj name
3057- }end_symbol ();
3065+ //
3066+ // First thing is always the S_OBJNAME, then the S_COMPILE3.
3067+ //
3068+ begin_symbol_record (0x1101 ); // S_OBJNAME
3069+ * push_struct (& module_stream , u32 ) = 0 ; // Signature (?)
3070+ push_zero_terminated_string_copy (& module_stream , module_object_name_full_path );
3071+ end_symbol_record ();
30583072
3059- begin_symbol (0x113c );{ // S_COMPILE3
3060-
3061- out_int (0 , u32 ); // flags, the first byte is for the _language index_ 0 means C
3062- out_int (0xd0 , u16 ); // machine
3063-
3064- // @note: this is copied from the dump
3065- out_int (19 , u16 ); // front end major version
3066- out_int (11 , u16 ); // front end minor version
3067- out_int (25506 , u16 ); // front end build version
3068- out_int (0 , u16 ); // front end QFE version ????
3069- out_int (19 , u16 ); // back end major version
3070- out_int (11 , u16 ); // back end minor version
3071- out_int (25506 , u16 ); // back end build version
3072- out_int (0 , u16 ); // back end QFE version ????
3073- char version_string [] = "ccup" ;
3074- out_struct (version_string );
3075- }end_symbol ();
30763073
3074+ begin_symbol_record (0x113c ); // S_COMPILE3
3075+
3076+ struct codeview_compile3 {
3077+ u32 flags ;
3078+ u16 machine ;
3079+
3080+ u16 front_end_major_version ;
3081+ u16 front_end_minor_version ;
3082+ u16 front_end_build_version ;
3083+ u16 front_end_QFE_version ;
3084+
3085+ u16 back_end_major_version ;
3086+ u16 back_end_minor_version ;
3087+ u16 back_end_build_version ;
3088+ u16 back_end_QFE_version ;
3089+
3090+ char compiler_version_string [];
3091+ } * compile3 = push_struct (& module_stream , struct codeview_compile3 );
3092+ compile3 -> flags = 0 ; // 0 means C
3093+ compile3 -> machine = 0xd0 ; // machine = x64 <- This is used by cvdump.
3094+
3095+ // @cleanup: Not sure what to do about these, but I am also not sure that anyone cares.
3096+ compile3 -> front_end_major_version = 19 ;
3097+ compile3 -> front_end_minor_version = 11 ;
3098+ compile3 -> front_end_build_version = 25506 ;
3099+ compile3 -> front_end_QFE_version = 0 ;
3100+
3101+ compile3 -> back_end_major_version = 19 ;
3102+ compile3 -> back_end_minor_version = 11 ;
3103+ compile3 -> back_end_build_version = 25506 ;
3104+ compile3 -> back_end_QFE_version = 0 ;
3105+
3106+ push_zero_terminated_string_copy (& module_stream , string ("hlc" )); // @cleanup: When we have a version system thing, we should probably put it in here.
3107+
3108+ end_symbol_record ();
30773109
3078- begin_counter (timing , module_function_info );
30793110 for_ast_list (defined_functions ){
3080- struct ast_function * function = cast (struct ast_function * )it -> value ;
3111+ struct ast_function * function = (struct ast_function * )it -> value ;
30813112
3082- function -> debug_symbol_offset = pdb_current_offset_from_location (context , module_stream_begin );
3083-
3084- struct pdb_location function_pointer_to_end ;
3085-
3086- u16 symbol = (function -> decl_flags & DECLARATION_FLAGS_is_static ) ? /* LPROC32 */ 0x110f : /* GPROC32 */ 0x1110 ;
3087- begin_symbol (symbol );{ // GPROC32 (global procdure start)
3088- out_int (0 , u32 ); // pointer to parent (what is a pointer ?)
3089- function_pointer_to_end = stream_allocate_bytes (context , sizeof (u32 )); // pointer to end
3090- out_int (0 , u32 ); // pointer to next symbol? why is this always 0?
3091- out_int (function -> byte_size , u32 ); // length of the procedure
3092- out_int (function -> size_of_prolog , u32 ); // offset in the function where debugging makes sense
3093- out_int (function -> byte_size , u32 ); // end of the section where it makes sense to debug @cleanup
3094- out_int (function -> type -> base .pdb_type_index , u32 ); // type_index
3095- out_int (function -> offset_in_text_section , u32 ); // offset in segment
3096- out_int (text_section_id , u16 ); // segment
3097- out_int (0 , u8 ); // flags: Frame pointer, @cleanup: custom calling convention, no_return
3098- // these are somehow never present???
3099- out_string (function -> identifier -> string );
3100- }end_symbol ();
3113+ function -> debug_symbol_offset = (u32 )(arena_current (& module_stream ) - module_stream .base );
31013114
3102- begin_symbol (0x1012 );{ // FRAMEPROC
3103-
3104- // dll_return_a_struct:
3105- // 0000000180001030: 48 89 4C 24 08 mov qword ptr [rsp+8],rcx
3106- // 0000000180001035: 56 push rsi
3107- // 0000000180001036: 57 push rdi
3108- // 0000000180001037: 48 81 EC 88 00 00 sub rsp,88h
3109-
3110- // Frame size = 0x00000088 bytes
3111- // Pad size = 0x00000000 bytes
3112- // Offset of pad in frame = 0x00000000
3113- // Size of callee save registers = 0x00000000
3114- // Address of exception handler = 0000:00000000
3115- // Function info: asynceh invalid_pgo_counts opt_for_speed Local=rsp Param=rsp (0x00114200)
3116-
3117- // this appearanly is not really the frame size, but only the space used by the function
3118- // no pushed registers and return value usw.
3119- u32 frame_size = to_u32 (function -> stack_space_needed );
3120-
3121- out_int (frame_size , u32 ); // frame size
3122- out_int (0 , u32 ); // pad size @cleanup: search up what this was again
3123- out_int (0 , u32 ); // offset of pad
3124- out_int (0 , u32 ); // callee saved register byte size (not sure)
3125- out_int (0 , u32 ); // offset of exception handler
3126- out_int (0 , u16 ); // section id of exception handler
3127-
3128- u32 flags = 0 ;
3129- flags |= (2 << 14 ); // local base pointer (3 = r13) (2 = rbp) (1 = rsp) (0 = none)
3130- flags |= (2 << 16 ); // param base pointer (3 = r13) (2 = rbp) (1 = rsp) (0 = none)
3131- flags |= (1 << 9 ); // asynceh, function compiled with /EHa ?
3132- flags |= (1 << 20 ); // opt_for_speed, always set for some reason
3133- out_int (flags , u32 ); // asynceh invalid_pgo_counts opt_for_speed Local=rsp Param=rsp ???
3134- }end_symbol ();
3115+ u16 function_symbol_kind = (function -> decl_flags & DECLARATION_FLAGS_is_static ) ? /* LPROC32 */ 0x110f : /* GPROC32 */ 0x1110 ;
31353116
3136- // @cleanup: we don't have to emit blocks, that do not have variables
3137- // and also we do not have to emit the _initial_ block as it is implicit,
3138- // but these might be things to do in the part that creates debug_members
3117+ begin_symbol_record (function_symbol_kind );
31393118
3119+ struct codeview_proc {
3120+ u32 pointer_to_parent ;
3121+ u32 pointer_to_end ;
3122+ u32 pointer_to_next ;
3123+ u32 procedure_length ;
3124+ u32 debug_start_offset ;
3125+ u32 debug_end_offset ;
3126+ u32 type_index ;
3127+ u32 offset_in_section ;
3128+ u16 section_id ;
3129+ u8 procedure_flags ;
3130+ u8 procedure_name [];
3131+ } * proc_symbol = push_struct_ (& module_stream , offset_in_type (struct codeview_proc , procedure_name ) + (function -> identifier -> length + 1 ), 4 );
3132+ proc_symbol -> pointer_to_parent = 0 ;
3133+ proc_symbol -> pointer_to_end = 0 ;
3134+ proc_symbol -> pointer_to_next = 0 ;
3135+ proc_symbol -> procedure_length = (u32 )function -> byte_size ;
3136+ proc_symbol -> debug_start_offset = (u32 )function -> size_of_prolog ;
3137+ proc_symbol -> debug_end_offset = (u32 )function -> byte_size ;
3138+ proc_symbol -> type_index = function -> type -> base .pdb_type_index ;
3139+ proc_symbol -> offset_in_section = (u32 )function -> offset_in_text_section ;
3140+ proc_symbol -> section_id = text_section_id ;
3141+ proc_symbol -> procedure_flags = 0 ; // Flags, somehow never present.
3142+ memcpy (proc_symbol -> procedure_name , function -> identifier -> data , function -> identifier -> length );
3143+ proc_symbol -> procedure_name [function -> identifier -> length ] = 0 ;
3144+
3145+ end_symbol_record ();
31403146
31413147 // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
31423148
3143- emit_debug_info_for_function ( context , function );
3149+ codeview_emit_debug_info_for_function ( function , & module_stream , /*relocation_arena (used by obj_writer.c)*/ null , /*debug_symbol_base (used by obj_writer.c)*/ null , text_section_id );
31443150
31453151 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31463152
3153+ proc_symbol -> pointer_to_end = (u32 )(arena_current (& module_stream ) - module_stream .base );
31473154
3148- u32 diff = pdb_current_offset_from_location (context , module_stream_begin );
3149- stream_write_bytes (context , & function_pointer_to_end , & diff , sizeof (u32 ));
3150- begin_symbol (0x6 );{ // S_END
3151- }end_symbol ();
3155+ begin_symbol_record (0x6 ); end_symbol_record (); // S_END
31523156 }
3153- end_counter (timing , module_function_info );
31543157
3155- begin_symbol (0x114c );{ // S_BUILDINFO
3156- out_int ( build_info_symbol , u32 ); // Item Id: type_index of a LF_BUILDINFO in the IPI stream
3157- } end_symbol ();
3158+ begin_symbol_record (0x114c ); // S_BUILDINFO
3159+ * push_struct ( & module_stream , u32 ) = build_info_symbol ; // Item Id: type_index of a LF_BUILDINFO in the IPI stream
3160+ end_symbol_record ();
31583161
3159- struct pdb_location symbols_end = get_current_pdb_location (context );
3160- module_stream_symbol_size = pdb_location_diff (symbols_end , module_stream_begin );
3162+ module_stream_symbol_size = (u32 )(arena_current (& module_stream ) - module_stream .base );
31613163
3162- begin_counter (timing , module_file_info );
3163- //
3164- // Here come the md5's
3165- //
3166- {
3167- out_int (0xf4 , u32 ); // DEBUG_S_FILECHKSUM or something like that
3168- struct pdb_location size_loc = stream_allocate_bytes (context , sizeof (u32 ));
3169- struct pdb_location begin_loc = get_current_pdb_location (context );
3170- for (smm file_index = 0 ; file_index < array_count (globals .file_table .data ); file_index ++ ){
3171- struct file * node = globals .file_table .data [file_index ];
3172- if (!node ) continue ;
3173-
3174- node -> offset_in_f4 = pdb_current_offset_from_location (context , begin_loc );
3175- out_int (node -> offset_in_names , u32 ); // offset in /names
3176- out_int (0x110 , u16 ); // kind of hash function (md5)
3177-
3178- // :padded_file_size
3179- //
3180- // We have padded the file size when allocating for it so we can use 'hash_md5_inplace'
3181- // here instead of 'hash_md5' which would have to allocate.
3182- //
3183- m128 md5 = hash_md5_inplace (node -> file .memory , node -> file .size , node -> file .size + 128 );
3184-
3185- stream_emit_struct (context , md5 ._u8 , 16 );
3186- out_align (sizeof (u32 )); // align up to 32.. there are two bytes of pad
3187- }
3188- struct pdb_location end_loc = get_current_pdb_location (context );
3189- smm size = pdb_location_diff (end_loc , begin_loc );
3190- stream_write_bytes (context , & size_loc , & size , sizeof (u32 ));
3191- }
3164+ u8 * line_information_start = arena_current (& module_stream );
31923165
3193- end_counter ( timing , module_file_info );
3166+ codeview_push_debug_s_file_checksums ( & module_stream );
31943167
3195- begin_counter (timing , module_line_info );
31963168 // now comes the line info
31973169 for_ast_list (defined_functions ){
31983170 struct ast_function * function = cast (struct ast_function * )it -> value ;
3199- struct ast_scope * scope = function -> scope ;
3200-
3201- out_int (0xf2 , u32 ); // DEBUG_S_LINES
3202- struct pdb_location size_loc = stream_allocate_bytes (context , sizeof (u32 ));
3203- struct pdb_location begin_loc = get_current_pdb_location (context );
3204-
3205- // DEBUG_S_LINES header
3206- out_int (function -> offset_in_text_section , u32 ); // offset in the section contribution
3207- out_int (text_section_id , u16 ); // section id (segment ?)
3208- out_int (0 , u16 ); // flags (0x1 = have columns)
3209- out_int (function -> byte_size , u32 ); // the size of the contribution
3210-
3211- struct pdb_location block_begin = get_current_pdb_location (context );
32123171
3213- // offset of the file info in the 0xf4 DEBUG_S_SECTION
3214- out_int (globals .file_table .data [scope -> token -> file_index ]-> offset_in_f4 , u32 );
3215- struct pdb_location amount_of_lines_loc = stream_allocate_bytes (context , sizeof (u32 ));
3216- struct pdb_location block_write = stream_allocate_bytes (context , sizeof (u32 ));
3217-
3218- emit_pdb_line_info_for_function (context , function );
3219- u32 amount_of_lines = save_truncate_smm_to_u32 (context -> pdb_amount_of_lines );
3220- stream_write_bytes (context , & amount_of_lines_loc , & amount_of_lines , sizeof (u32 ));
3221-
3222- struct pdb_location end_loc = get_current_pdb_location (context );
3223- smm block_size = pdb_location_diff (end_loc , block_begin );
3224- stream_write_bytes (context , & block_write , & block_size , sizeof (u32 ));
3225-
3226- smm size = pdb_location_diff (end_loc , begin_loc );
3227- stream_write_bytes (context , & size_loc , & size , sizeof (u32 ));
3172+ codeview_push_debug_s_lines (function , & module_stream , /*relocation_arena (used by obj_writer.c)*/ null , /*debug_symbol_base (used by obj_writer.c)*/ null , text_section_id );
32283173 }
3229- end_counter (timing , module_line_info );
32303174
3231- struct pdb_location module_stream_end = get_current_pdb_location (context );
3232- module_stream_line_info_size = pdb_location_diff (module_stream_end , symbols_end );
32333175
3234- out_int (0 , u32 ); // amount_of global references
3176+ module_stream_line_info_size = (u32 )(arena_current (& module_stream ) - line_information_start );
3177+
3178+ * push_struct (& module_stream , u32 ) = 0 ; // Amount of global references.
3179+
3180+ set_current_stream (context , STREAM_module_zero );
3181+ stream_emit_struct (context , module_stream .base , arena_current (& module_stream ) - module_stream .base );
32353182 }
32363183 end_counter (timing , module_stream );
32373184
0 commit comments