@@ -525,6 +525,7 @@ static struct{
525525 struct token * token ;
526526 } * globally_referenced_declarations ;
527527
528+
528529 //
529530 // Basic types:
530531 // @WARNING: The non-atomic version need to stay in the same order as the atomic versions,
@@ -571,6 +572,8 @@ static struct{
571572 struct ast_type * typedef_u8_pointer ;
572573 struct ast_type * typedef_s8_pointer ;
573574
575+ struct ast_function_type * seh_filter_funtion_type ;
576+
574577 //
575578 // Invalid/Default values
576579 //
@@ -583,6 +586,8 @@ static struct{
583586
584587 struct ast_declaration * tls_index_declaration ;
585588
589+ struct token * seh_used ;
590+ struct ast_function * C_specific_handler_declaration ;
586591} globals ;
587592
588593//_____________________________________________________________________________________________________________________
@@ -759,6 +764,10 @@ struct context{
759764 smm in_conditional_expression ;
760765 int current_statement_returns_a_value ;
761766
767+ smm in_exception_filter ;
768+ smm in_finally_block ;
769+ smm filter_function_index ;
770+
762771 struct ast_stack_entry {
763772 enum ast_kind ast_kind ;
764773 struct token * token ;
@@ -956,7 +965,7 @@ func void emit_patch(struct context *context, enum patch_kind kind, struct ir *s
956965// Reference graph.
957966
958967func void add_global_reference_for_declaration (struct memory_arena * arena , struct ast_declaration * declaration ){
959- assert (globals .compile_stage == COMPILE_STAGE_parse_global_scope_entries );
968+ // assert(globals.compile_stage == COMPILE_STAGE_parse_global_scope_entries); This is not true anymore because of __C_specific_handler.
960969
961970 struct declaration_reference_node * node = push_struct (arena , struct declaration_reference_node );
962971 node -> declaration = declaration ;
@@ -1493,6 +1502,18 @@ func void wake_up_sleepers(struct sleeper_table *sleeper_table, struct token *sl
14931502#include "preprocess.c"
14941503//_____________________________________________________________________________________________________________________
14951504
1505+ func struct token * push_dummy_token (struct memory_arena * arena , struct atom token_atom , enum token_type token_type ){
1506+
1507+ struct token * token = push_struct (arena , struct token );
1508+ token -> type = token_type ;
1509+ token -> atom = token_atom ;
1510+ token -> file_index = -1 ; // invalid file index.
1511+ token -> line = 1 ;
1512+ token -> column = 1 ;
1513+
1514+ return token ;
1515+ }
1516+
14961517func struct parse_work * push_parse_work (struct context * context , struct token_array tokens , struct compilation_unit * compilation_unit , struct ast_function * function ){
14971518 struct parse_work * parse_work = push_uninitialized_struct (context -> arena , struct parse_work ); // @note: No need to zero, 'arena' never has any non-zero bytes.
14981519 parse_work -> tokens = tokens ;
@@ -2640,6 +2661,8 @@ func void reset_context(struct context *context){
26402661 context -> goto_list .first = context -> goto_list .last = 0 ;
26412662 context -> label_list .first = context -> label_list .last = 0 ;
26422663
2664+ context -> filter_function_index = 0 ;
2665+
26432666 context -> pragma_pack_stack .first = context -> pragma_pack_stack .last = null ;
26442667}
26452668
@@ -3477,19 +3500,7 @@ func u32 work_thread_proc(void *param){
34773500//_____________________________________________________________________________________________________________________
34783501// Setup code needed by main
34793502
3480- func struct token * push_dummy_token (struct memory_arena * arena , struct atom token_atom , enum token_type token_type ){
3481-
3482- struct token * token = push_struct (arena , struct token );
3483- token -> type = token_type ;
3484- token -> atom = token_atom ;
3485- token -> file_index = -1 ; // invalid file index.
3486- token -> line = 1 ;
3487- token -> column = 1 ;
3488-
3489- return token ;
3490- }
3491-
3492- func void register_intrinsic_function_declaration (struct context * context , struct token * token , struct ast_function_type * type ){
3503+ func struct ast_declaration * register_intrinsic_function_declaration (struct context * context , struct token * token , struct ast_function_type * type ){
34933504
34943505 struct ast_function * declaration = push_uninitialized_struct (context -> arena , struct ast_function ); // @note: No need to zero, 'arena' never has any non-zero bytes.
34953506 declaration -> kind = IR_function ;
@@ -3499,7 +3510,10 @@ func void register_intrinsic_function_declaration(struct context *context, struc
34993510 declaration -> compilation_unit = & globals .hacky_global_compilation_unit ;
35003511 declaration -> as_decl .flags |= DECLARATION_FLAGS_is_intrinsic | DECLARATION_FLAGS_is_global ;
35013512
3502- ast_table_add_or_return_previous_entry (& globals .global_declarations , & declaration -> kind , token );
3513+ struct ast_declaration * redecl = (struct ast_declaration * )ast_table_add_or_return_previous_entry (& globals .global_declarations , & declaration -> kind , token );
3514+ if (redecl ) return redecl ;
3515+
3516+ return & declaration -> as_decl ;
35033517}
35043518
35053519
@@ -4464,6 +4478,11 @@ globals.typedef_##postfix = (struct ast_type){
44644478 void_pointer -> base .alignment = 8 ;
44654479 globals .typedef_void_pointer = & void_pointer -> base ;
44664480
4481+ struct ast_function_type * seh_filter_function_type = parser_type_push (context , function_type );
4482+ seh_filter_function_type -> return_type = & globals .typedef_s32 ;
4483+ seh_filter_function_type -> flags |= FUNCTION_TYPE_FLAGS_is_seh_filter ;
4484+ globals .seh_filter_funtion_type = seh_filter_function_type ;
4485+
44674486 globals .wake_event = CreateEventA (0 , true, 0 , 0 );
44684487
44694488 globals .declaration_sleeper_table = sleeper_table_create (1 << 8 );
@@ -4537,6 +4556,44 @@ globals.typedef_##postfix = (struct ast_type){
45374556 register_intrinsic_function_declaration (context , token , type );
45384557 }
45394558
4559+ { //
4560+ // void *_exception_info(void)
4561+ //
4562+
4563+ struct token * token = push_dummy_token (arena , atom_for_string (string ("_exception_info" )), TOKEN_identifier );
4564+
4565+ struct ast_function_type * type = parser_type_push (context , function_type );
4566+ type -> return_type = & void_pointer -> base ;
4567+ type -> flags |= FUNCTION_TYPE_FLAGS_is_seh_intrinsic ;
4568+
4569+ register_intrinsic_function_declaration (context , token , type );
4570+ }
4571+
4572+ { //
4573+ // unsigned __int32 _exception_code(void)
4574+ //
4575+
4576+ struct token * token = push_dummy_token (arena , atom_for_string (string ("_exception_code" )), TOKEN_identifier );
4577+
4578+ struct ast_function_type * type = parser_type_push (context , function_type );
4579+ type -> return_type = & globals .typedef_u32 ;
4580+ type -> flags |= FUNCTION_TYPE_FLAGS_is_seh_intrinsic ;
4581+
4582+ register_intrinsic_function_declaration (context , token , type );
4583+ }
4584+
4585+ { //
4586+ // int _abnormal_termination(void)
4587+ //
4588+
4589+ struct token * token = push_dummy_token (arena , atom_for_string (string ("_abnormal_termination" )), TOKEN_identifier );
4590+
4591+ struct ast_function_type * type = parser_type_push (context , function_type );
4592+ type -> return_type = & globals .typedef_s32 ;
4593+ type -> flags |= FUNCTION_TYPE_FLAGS_is_seh_intrinsic ;
4594+
4595+ register_intrinsic_function_declaration (context , token , type );
4596+ }
45404597
45414598 globals .invalid_identifier_token = push_dummy_token (arena , globals .invalid_identifier , TOKEN_identifier );
45424599
@@ -5065,7 +5122,6 @@ globals.typedef_##postfix = (struct ast_type){
50655122 }
50665123 }
50675124
5068-
50695125 //
50705126 // At this point no more sleepers will get filled in.
50715127 // So _if_ there are any, report them.
@@ -5100,8 +5156,72 @@ globals.typedef_##postfix = (struct ast_type){
51005156 assert (globals .work_queue_parse_functions .work_entries_in_flight == 0 );
51015157 if (globals .an_error_has_occurred ) goto end ;
51025158
5159+
51035160 // @cleanup: is there a good way here to assert that nothing is sleeping?
51045161
5162+
5163+ if (globals .seh_used ){
5164+
5165+ struct atom atom = atom_for_string (string ("__C_specific_handler" ));
5166+
5167+ struct ast_declaration * decl = (struct ast_declaration * )ast_table_get (& globals .global_declarations , atom );
5168+
5169+ if (decl && decl -> assign_expr ){
5170+ // We found a user-defined version, add a global reference to it!
5171+ add_global_reference_for_declaration (arena , decl );
5172+ }else {
5173+
5174+ if (decl ){
5175+ // It is not defined, but we already have it.
5176+ }else {
5177+ struct token * token = push_dummy_token (arena , atom , TOKEN_identifier );
5178+
5179+ struct ast_function_type * type = parser_type_push (context , function_type );
5180+ type -> return_type = & globals .typedef_s32 ;
5181+
5182+ decl = register_intrinsic_function_declaration (context , token , type );
5183+ decl -> flags &= ~DECLARATION_FLAGS_is_intrinsic ;
5184+ }
5185+
5186+ decl -> flags |= DECLARATION_FLAGS_is_dllimport ;
5187+ decl -> flags |= DECLARATION_FLAGS_need_dllimport_stub_function ;
5188+ decl -> flags |= DECLARATION_FLAGS_is_reachable_from_entry ;
5189+
5190+ struct dll_node * vcruntime = null ;
5191+
5192+ for (struct dll_node * dll = globals .dlls .first ; dll ; dll = dll -> next ){
5193+ if (string_match_case_insensitive (dll -> name , string ("ntdll.dll" ))){
5194+ vcruntime = dll ;
5195+ break ;
5196+ }
5197+ }
5198+
5199+ if (!vcruntime ){
5200+ vcruntime = push_struct (arena , struct dll_node );
5201+ vcruntime -> name = string ("ntdll.dll" );
5202+ sll_push_back (globals .dlls , vcruntime );
5203+ globals .dlls .amount += 1 ;
5204+ }
5205+
5206+ struct dll_import_node * import_node = push_struct (arena , struct dll_import_node );
5207+ import_node -> import_name = atom .string ;
5208+ sll_push_back (vcruntime -> import_list , import_node );
5209+ vcruntime -> import_list .count += 1 ;
5210+
5211+ if (decl -> kind == AST_function ){
5212+ ((struct ast_function * )decl )-> dll_import_node = import_node ;
5213+ }
5214+ }
5215+
5216+ if (decl -> kind != AST_function ){
5217+ // :Error
5218+ report_error (context , decl -> identifier , "__C_specific_handler defined as non-function. It is needed for Structured Exception Handling (SEH) (__try/__except)." );
5219+ }else {
5220+ globals .C_specific_handler_declaration = (struct ast_function * )decl ;
5221+ }
5222+ }
5223+
5224+
51055225 stage_two_parsing_time = os_get_time_in_seconds () - stage_two_parsing_time ;
51065226
51075227 //
@@ -5471,8 +5591,6 @@ globals.typedef_##postfix = (struct ast_type){
54715591 #endif
54725592 }
54735593
5474- end_counter (context , report_error_for_undefined_functions_and_types );
5475-
54765594 end :;
54775595
54785596 print_warning_or_error_reports (context );
0 commit comments