]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
(STMP_FIXPROTO, exeext): New defs.
[gcc.git] / gcc / cp / except.c
CommitLineData
8d08fdba 1/* Handle exceptional things in C++.
6467930b 2 Copyright (C) 1989, 92-95, 1996 Free Software Foundation, Inc.
8d2733ca
MS
3 Contributed by Michael Tiemann <tiemann@cygnus.com>
4 Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
5 initial re-implementation courtesy Tad Hunt.
8d08fdba
MS
6
7This file is part of GNU CC.
8
9GNU CC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GNU CC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU CC; see the file COPYING. If not, write to
e9fa0c7c
RK
21the Free Software Foundation, 59 Temple Place - Suite 330,
22Boston, MA 02111-1307, USA. */
8d08fdba
MS
23
24
8d08fdba
MS
25#include "config.h"
26#include "tree.h"
27#include "rtl.h"
28#include "cp-tree.h"
29#include "flags.h"
8d2733ca
MS
30#include "obstack.h"
31#include "expr.h"
21451173 32#include "output.h"
6467930b
MS
33#include "except.h"
34#include "function.h"
8d08fdba 35
f30432d7 36rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
a3b49ccd 37
8d2733ca
MS
38/* holds the fndecl for __builtin_return_address () */
39tree builtin_return_address_fndecl;
8d2733ca
MS
40
41/* A couple of backend routines from m88k.c */
42
43/* used to cache a call to __builtin_return_address () */
44static tree BuiltinReturnAddress;
f30432d7 45
8d2733ca
MS
46
47#include <stdio.h>
48
8d2733ca
MS
49static void
50easy_expand_asm (str)
51 char *str;
52{
53 expand_asm (build_string (strlen (str)+1, str));
8d08fdba
MS
54}
55
8d08fdba 56
8d2733ca 57#if 0
e92cc029 58/* This is the startup, and finish stuff per exception table. */
8d08fdba 59
8d2733ca
MS
60/* XXX - Tad: exception handling section */
61#ifndef EXCEPT_SECTION_ASM_OP
62#define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
63#endif
8d08fdba 64
8d2733ca
MS
65#ifdef EXCEPT_SECTION_ASM_OP
66typedef struct {
6467930b
MS
67 void *start_region;
68 void *end_region;
8d2733ca
MS
69 void *exception_handler;
70 } exception_table;
71#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 72
8d2733ca 73#ifdef EXCEPT_SECTION_ASM_OP
8d08fdba 74
8d2733ca
MS
75 /* on machines which support it, the exception table lives in another section,
76 but it needs a label so we can reference it... This sets up that
77 label! */
78asm (EXCEPT_SECTION_ASM_OP);
79exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
80asm (TEXT_SECTION_ASM_OP);
8d08fdba 81
8d2733ca 82#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 83
8d2733ca
MS
84#ifdef EXCEPT_SECTION_ASM_OP
85
86 /* we need to know where the end of the exception table is... so this
87 is how we do it! */
88
89asm (EXCEPT_SECTION_ASM_OP);
90exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
91asm (TEXT_SECTION_ASM_OP);
92
93#endif /* EXCEPT_SECTION_ASM_OP */
94
95#endif
8d08fdba 96
8d2733ca 97#include "decl.h"
8d2733ca
MS
98#include "insn-flags.h"
99#include "obstack.h"
8d2733ca
MS
100
101/* ======================================================================
102 Briefly the algorithm works like this:
103
104 When a constructor or start of a try block is encountered,
105 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
106 new entry in the unwind protection stack and returns a label to
107 output to start the protection for that block.
108
109 When a destructor or end try block is encountered, pop_eh_entry
6467930b
MS
110 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
111 created when push_eh_entry () was called. The eh_entry structure
8d2733ca
MS
112 contains three things at this point. The start protect label,
113 the end protect label, and the exception handler label. The end
114 protect label should be output before the call to the destructor
115 (if any). If it was a destructor, then its parse tree is stored
6467930b 116 in the finalization variable in the eh_entry structure. Otherwise
8d2733ca 117 the finalization variable is set to NULL to reflect the fact that
6467930b 118 is the the end of a try block. Next, this modified eh_entry node
8d2733ca
MS
119 is enqueued in the finalizations queue by calling
120 enqueue_eh_entry (&queue,entry).
121
122 +---------------------------------------------------------------+
123 |XXX: Will need modification to deal with partially |
124 | constructed arrays of objects |
125 | |
126 | Basically, this consists of keeping track of how many |
127 | of the objects have been constructed already (this |
128 | should be in a register though, so that shouldn't be a |
129 | problem. |
130 +---------------------------------------------------------------+
131
132 When a catch block is encountered, there is a lot of work to be
133 done.
134
135 Since we don't want to generate the catch block inline with the
136 regular flow of the function, we need to have some way of doing
f30432d7
MS
137 so. Luckily, we can use sequences to defer the catch sections.
138 When the start of a catch block is encountered, we start the
139 sequence. After the catch block is generated, we end the
140 sequence.
141
8d2733ca
MS
142 Next we must insure that when the catch block is executed, all
143 finalizations for the matching try block have been completed. If
144 any of those finalizations throw an exception, we must call
145 terminate according to the ARM (section r.15.6.1). What this
146 means is that we need to dequeue and emit finalizations for each
6467930b 147 entry in the eh_queue until we get to an entry with a NULL
8d2733ca
MS
148 finalization field. For any of the finalization entries, if it
149 is not a call to terminate (), we must protect it by giving it
150 another start label, end label, and exception handler label,
151 setting its finalization tree to be a call to terminate (), and
6467930b 152 enqueue'ing this new eh_entry to be output at an outer level.
8d2733ca
MS
153 Finally, after all that is done, we can get around to outputting
154 the catch block which basically wraps all the "catch (...) {...}"
155 statements in a big if/then/else construct that matches the
156 correct block to call.
157
158 ===================================================================== */
159
160extern rtx emit_insn PROTO((rtx));
161extern rtx gen_nop PROTO(());
8d2733ca
MS
162
163/* local globals for function calls
164 ====================================================================== */
165
166/* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
f30432d7 167 "set_unexpected ()" after default_conversion. (lib-except.c) */
6467930b 168static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch;
8d2733ca
MS
169
170/* used to cache __find_first_exception_table_match ()
171 for throw (lib-except.c) */
172static tree FirstExceptionMatch;
173
f30432d7 174/* used to cache a call to __unwind_function () (lib-except.c) */
8d2733ca
MS
175static tree Unwind;
176
f30432d7 177/* holds a ready to emit call to "terminate ()". */
8d2733ca
MS
178static tree TerminateFunctionCall;
179
72b7eeff
MS
180static tree empty_fndecl;
181
8d2733ca
MS
182/* ====================================================================== */
183
184
8d2733ca
MS
185/* ========================================================================= */
186
187
188
189/* local globals - these local globals are for storing data necessary for
190 generating the exception table and code in the correct order.
191
192 ========================================================================= */
193
a3b49ccd 194/* Holds the pc for doing "throw" */
5566b478 195static tree saved_pc;
e92cc029 196/* Holds the type of the thing being thrown. */
5566b478 197static tree saved_throw_type;
a3b49ccd 198/* Holds the value being thrown. */
5566b478 199static tree saved_throw_value;
72b7eeff 200/* Holds the cleanup for the value being thrown. */
5566b478 201static tree saved_cleanup;
a50f0918
MS
202/* Indicates if we are in a catch clause. */
203static tree saved_in_catch;
f30432d7 204
6467930b
MS
205extern int throw_used;
206extern rtx catch_clauses;
8d2733ca 207
8d2733ca
MS
208/* ========================================================================= */
209
6467930b 210/* Cheesyness to save some typing. Returns the return value rtx. */
8d2733ca 211
5566b478 212static rtx
f30432d7
MS
213do_function_call (func, params, return_type)
214 tree func, params, return_type;
215{
216 tree func_call;
217 func_call = build_function_call (func, params);
218 expand_call (func_call, NULL_RTX, 0);
219 if (return_type != NULL_TREE)
220 return hard_function_value (return_type, func_call);
221 return NULL_RTX;
222}
223
8d2733ca
MS
224/* ========================================================================= */
225
8ccc31eb
MS
226extern tree auto_function PROTO((tree, tree, enum built_in_function));
227
8d2733ca
MS
228/* sets up all the global eh stuff that needs to be initialized at the
229 start of compilation.
230
231 This includes:
6467930b 232 - Setting up all the function call trees. */
8d08fdba 233
8d08fdba 234void
8d2733ca 235init_exception_processing ()
8d08fdba 236{
8d2733ca
MS
237 extern tree define_function ();
238 tree unexpected_fndecl, terminate_fndecl;
239 tree set_unexpected_fndecl, set_terminate_fndecl;
240 tree catch_match_fndecl;
241 tree find_first_exception_match_fndecl;
242 tree unwind_fndecl;
f30432d7
MS
243 tree declspecs;
244 tree d;
a3b49ccd 245
8d2733ca 246 /* void (*)() */
8ccc31eb
MS
247 tree PFV = build_pointer_type (build_function_type
248 (void_type_node, void_list_node));
8d08fdba 249
8d2733ca
MS
250 /* arg list for the build_function_type call for set_terminate () and
251 set_unexpected () */
8ccc31eb 252 tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
8d08fdba 253
8ccc31eb
MS
254 /* void (*pfvtype (void (*) ()))() */
255 tree pfvtype = build_function_type (PFV, pfvlist);
8d2733ca 256
8ccc31eb
MS
257 /* void vtype () */
258 tree vtype = build_function_type (void_type_node, void_list_node);
259
260 set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
261 pfvtype, NOT_BUILT_IN);
262 set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
263 pfvtype, NOT_BUILT_IN);
264 unexpected_fndecl = auto_function (get_identifier ("unexpected"),
265 vtype, NOT_BUILT_IN);
266 terminate_fndecl = auto_function (get_identifier ("terminate"),
267 vtype, NOT_BUILT_IN);
268
8ccc31eb 269 push_lang_context (lang_name_c);
8d2733ca 270
8d2733ca 271 catch_match_fndecl =
72b7eeff
MS
272 builtin_function (flag_rtti
273 ? "__throw_type_match_rtti"
274 : "__throw_type_match",
275 build_function_type (ptr_type_node,
276 tree_cons (NULL_TREE, ptr_type_node,
277 tree_cons (NULL_TREE, ptr_type_node,
278 tree_cons (NULL_TREE, ptr_type_node,
279 void_list_node)))),
280 NOT_BUILT_IN, NULL_PTR);
8d2733ca 281 find_first_exception_match_fndecl =
72b7eeff
MS
282 builtin_function ("__find_first_exception_table_match",
283 build_function_type (ptr_type_node,
284 tree_cons (NULL_TREE, ptr_type_node,
285 void_list_node)),
286 NOT_BUILT_IN, NULL_PTR);
8d2733ca 287 unwind_fndecl =
72b7eeff
MS
288 builtin_function ("__unwind_function",
289 build_function_type (void_type_node,
290 tree_cons (NULL_TREE, ptr_type_node,
291 void_list_node)),
292 NOT_BUILT_IN, NULL_PTR);
72b7eeff
MS
293 empty_fndecl =
294 builtin_function ("__empty",
295 build_function_type (void_type_node, void_list_node),
296 NOT_BUILT_IN, NULL_PTR);
297 DECL_EXTERNAL (empty_fndecl) = 1;
298 TREE_PUBLIC (empty_fndecl) = 1;
8d2733ca
MS
299
300 Unexpected = default_conversion (unexpected_fndecl);
301 Terminate = default_conversion (terminate_fndecl);
302 SetTerminate = default_conversion (set_terminate_fndecl);
303 SetUnexpected = default_conversion (set_unexpected_fndecl);
304 CatchMatch = default_conversion (catch_match_fndecl);
305 FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
306 Unwind = default_conversion (unwind_fndecl);
307 BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
308
309 TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
310
311 pop_lang_context ();
f30432d7 312
f30432d7
MS
313 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
314 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_pc"));
315 d = start_decl (d, declspecs, 0, NULL_TREE);
316 DECL_COMMON (d) = 1;
9e9ff709 317 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7
MS
318 saved_pc = lookup_name (get_identifier ("__eh_pc"), 0);
319
320 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
321 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_type"));
322 d = start_decl (d, declspecs, 0, NULL_TREE);
323 DECL_COMMON (d) = 1;
9e9ff709 324 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7
MS
325 saved_throw_type = lookup_name (get_identifier ("__eh_type"), 0);
326
327 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
328 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_value"));
329 d = start_decl (d, declspecs, 0, NULL_TREE);
330 DECL_COMMON (d) = 1;
9e9ff709 331 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7 332 saved_throw_value = lookup_name (get_identifier ("__eh_value"), 0);
72b7eeff
MS
333
334 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
335 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_cleanup"));
336 d = build_parse_node (CALL_EXPR, d, void_list_node, NULL_TREE);
337 d = start_decl (d, declspecs, 0, NULL_TREE);
338 DECL_COMMON (d) = 1;
9e9ff709 339 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
72b7eeff 340 saved_cleanup = lookup_name (get_identifier ("__eh_cleanup"), 0);
a50f0918
MS
341
342 declspecs = tree_cons (NULL_TREE, get_identifier ("bool"), NULL_TREE);
343 d = get_identifier ("__eh_in_catch");
344 d = start_decl (d, declspecs, 0, NULL_TREE);
345 DECL_COMMON (d) = 1;
346 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
347 saved_in_catch = lookup_name (get_identifier ("__eh_in_catch"), 0);
8d2733ca
MS
348}
349
f30432d7
MS
350/* Build a type value for use at runtime for a type that is matched
351 against by the exception handling system. */
6467930b 352
f30432d7
MS
353static tree
354build_eh_type_type (type)
355 tree type;
8d08fdba 356{
f30432d7
MS
357 char *typestring;
358 tree exp;
8d2733ca 359
f30432d7
MS
360 if (type == error_mark_node)
361 return error_mark_node;
8d2733ca 362
e92cc029 363 /* peel back references, so they match. */
f30432d7
MS
364 if (TREE_CODE (type) == REFERENCE_TYPE)
365 type = TREE_TYPE (type);
8d08fdba 366
e92cc029 367 /* Peel off cv qualifiers. */
f30432d7 368 type = TYPE_MAIN_VARIANT (type);
8d2733ca 369
f30432d7 370 if (flag_rtti)
8d08fdba 371 {
f30432d7 372 return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
8d08fdba 373 }
f30432d7
MS
374
375 typestring = build_overload_name (type, 1, 1);
376 exp = combine_strings (build_string (strlen (typestring)+1, typestring));
377 return build1 (ADDR_EXPR, ptr_type_node, exp);
8d08fdba 378}
8d08fdba 379
faae18ab
MS
380/* Build a type value for use at runtime for a exp that is thrown or
381 matched against by the exception handling system. */
6467930b 382
faae18ab
MS
383static tree
384build_eh_type (exp)
385 tree exp;
386{
faae18ab
MS
387 if (flag_rtti)
388 {
389 exp = build_typeid (exp);
390 return build1 (ADDR_EXPR, ptr_type_node, exp);
391 }
f30432d7 392 return build_eh_type_type (TREE_TYPE (exp));
faae18ab
MS
393}
394
72b7eeff 395/* This routine creates the cleanup for the exception handling object. */
6467930b 396
5566b478 397static void
72b7eeff
MS
398push_eh_cleanup ()
399{
400 /* All cleanups must last longer than normal. */
401 int yes = suspend_momentary ();
402
403 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
404 tree cleanup = build_function_call (saved_cleanup, NULL_TREE);
a50f0918
MS
405 cleanup = build (COMPOUND_EXPR, void_type_node, cleanup,
406 build_modify_expr (saved_in_catch, NOP_EXPR,
407 build_modify_expr (saved_throw_type, NOP_EXPR, integer_zero_node)));
e349ee73 408 expand_decl_cleanup (NULL_TREE, cleanup);
72b7eeff
MS
409
410 resume_momentary (yes);
411}
412
413
8d2733ca
MS
414/* call this to start a catch block. Typename is the typename, and identifier
415 is the variable to place the object in or NULL if the variable doesn't
416 matter. If typename is NULL, that means its a "catch (...)" or catch
417 everything. In that case we don't need to do any type checking.
418 (ie: it ends up as the "else" clause rather than an "else if" clause) */
6467930b 419
8d08fdba 420void
a4443a08
MS
421expand_start_catch_block (declspecs, declarator)
422 tree declspecs, declarator;
8d08fdba 423{
8d2733ca 424 rtx false_label_rtx;
faae18ab 425 tree decl = NULL_TREE;
a3b49ccd 426 tree init;
8d2733ca
MS
427
428 if (! doing_eh (1))
429 return;
430
a3b49ccd
MS
431 /* Create a binding level for the parm. */
432 expand_start_bindings (0);
433
f675499c 434 false_label_rtx = gen_label_rtx ();
72b7eeff 435 push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
a3b49ccd 436
faae18ab 437 if (declspecs)
8d08fdba 438 {
faae18ab 439 tree exp;
8d2733ca 440 rtx call_rtx, return_value_rtx;
faae18ab
MS
441 tree init_type;
442
f30432d7
MS
443 decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1,
444 NULL_TREE, NULL_TREE);
faae18ab
MS
445
446 if (decl == NULL_TREE)
447 {
448 error ("invalid catch parameter");
6467930b
MS
449
450 /* This is cheap, but we want to maintain the data structures. */
451 expand_eh_region_start ();
faae18ab
MS
452 return;
453 }
454
be99da77
MS
455 /* Make sure we mark the catch param as used, otherwise we'll get
456 a warning about an unused ((anonymous)). */
457 TREE_USED (decl) = 1;
458
e92cc029 459 /* Figure out the type that the initializer is. */
faae18ab 460 init_type = TREE_TYPE (decl);
f30432d7
MS
461 if (TREE_CODE (init_type) != REFERENCE_TYPE
462 && TREE_CODE (init_type) != POINTER_TYPE)
faae18ab
MS
463 init_type = build_reference_type (init_type);
464
f30432d7 465 exp = saved_throw_value;
faae18ab 466 exp = tree_cons (NULL_TREE,
f30432d7 467 build_eh_type_type (TREE_TYPE (decl)),
faae18ab 468 tree_cons (NULL_TREE,
f30432d7 469 saved_throw_type,
faae18ab
MS
470 tree_cons (NULL_TREE, exp, NULL_TREE)));
471 exp = build_function_call (CatchMatch, exp);
472 call_rtx = expand_call (exp, NULL_RTX, 0);
e1cd6e56 473 assemble_external (TREE_OPERAND (CatchMatch, 0));
8d2733ca 474
faae18ab 475 return_value_rtx = hard_function_value (ptr_type_node, exp);
8d2733ca
MS
476
477 /* did the throw type match function return TRUE? */
faae18ab 478 emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
8d2733ca
MS
479 GET_MODE (return_value_rtx), 0, 0);
480
481 /* if it returned FALSE, jump over the catch block, else fall into it */
faae18ab
MS
482 emit_jump_insn (gen_beq (false_label_rtx));
483
72b7eeff
MS
484 push_eh_cleanup ();
485
faae18ab
MS
486 init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
487
488 /* Do we need the below two lines? */
b3417a04 489 /* Let `cp_finish_decl' know that this initializer is ok. */
faae18ab
MS
490 DECL_INITIAL (decl) = init;
491 decl = pushdecl (decl);
b3417a04 492 cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
8d08fdba
MS
493 }
494 else
495 {
72b7eeff
MS
496 push_eh_cleanup ();
497
e92cc029 498 /* Fall into the catch all section. */
8d08fdba 499 }
a3b49ccd 500
a50f0918 501 emit_move_insn (DECL_RTL (saved_in_catch), const1_rtx);
f30432d7 502
6467930b
MS
503 /* Because we are reordered out of line, we arrange
504 to rethrow in the outer context, should we encounter
505 an exception in the catch handler.
f30432d7 506
6467930b
MS
507 Matches the end in expand_end_catch_block (). */
508 expand_eh_region_start ();
f30432d7 509
6467930b
MS
510 emit_line_note (input_filename, lineno);
511}
f30432d7 512
f30432d7 513
f30432d7 514
8d2733ca
MS
515/* Call this to end a catch block. Its responsible for emitting the
516 code to handle jumping back to the correct place, and for emitting
517 the label to jump to if this catch block didn't match. */
6467930b 518
8d2733ca 519void expand_end_catch_block ()
8d08fdba 520{
6467930b
MS
521 rtx start_region_label_rtx;
522 rtx end_region_label_rtx;
523 tree decls, t;
a3b49ccd 524
f30432d7
MS
525 if (! doing_eh (1))
526 return;
8d2733ca 527
6467930b 528 /* Fall to outside the try statement when done executing handler and
f30432d7
MS
529 we fall off end of handler. This is jump Lresume in the
530 documentation. */
72b7eeff 531 expand_goto (top_label_entry (&caught_return_label_stack));
a3b49ccd 532
6467930b
MS
533 t = make_node (RTL_EXPR);
534 TREE_TYPE (t) = void_type_node;
535 RTL_EXPR_RTL (t) = const0_rtx;
536 TREE_SIDE_EFFECTS (t) = 1;
537 start_sequence_for_rtl_expr (t);
538 expand_internal_throw (DECL_RTL (top_label_entry (&caught_return_label_stack)));
539 RTL_EXPR_SEQUENCE (t) = get_insns ();
540 end_sequence ();
f30432d7 541
6467930b
MS
542 /* Matches the start in expand_start_catch_block (). */
543 expand_eh_region_end (t);
f30432d7 544
6467930b 545 expand_leftover_cleanups ();
f30432d7
MS
546
547 /* Cleanup the EH parameter. */
548 decls = getdecls ();
549 expand_end_bindings (decls, decls != NULL_TREE, 0);
a3b49ccd 550
6467930b 551 /* label we emit to jump to if this catch block didn't match. */
f30432d7
MS
552 /* This the closing } in the `if (eq) {' of the documentation. */
553 emit_label (pop_label_entry (&false_label_stack));
8d2733ca 554}
8d08fdba 555
6467930b
MS
556/* unwind the stack. */
557
db5ae43f 558static void
f30432d7
MS
559do_unwind (inner_throw_label)
560 rtx inner_throw_label;
db5ae43f 561{
be99da77
MS
562#if defined (SPARC_STACK_ALIGN) /* was sparc */
563 /* This doesn't work for the flat model sparc, I bet. */
db5ae43f
MS
564 tree fcall;
565 tree params;
566 rtx return_val_rtx;
f30432d7 567 rtx temp;
db5ae43f
MS
568
569 /* call to __builtin_return_address () */
f30432d7 570 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
db5ae43f 571 fcall = build_function_call (BuiltinReturnAddress, params);
f30432d7 572 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
ddd5a7c1 573 /* In the return, the new pc is pc+8, as the value coming in is
db5ae43f 574 really the address of the call insn, not the next insn. */
f30432d7
MS
575 temp = gen_reg_rtx (Pmode);
576 emit_move_insn (temp, inner_throw_label);
577 emit_move_insn (return_val_rtx, plus_constant (temp, -8));
d11ad92e 578 emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)));
db5ae43f
MS
579 easy_expand_asm ("ret");
580 easy_expand_asm ("restore");
581 emit_barrier ();
582#endif
be99da77 583#if defined (ARM_FRAME_RTX) /* was __arm */
f30432d7
MS
584 if (flag_omit_frame_pointer)
585 sorry ("this implementation of exception handling requires a frame pointer");
db5ae43f 586
f30432d7
MS
587 emit_move_insn (stack_pointer_rtx,
588 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));
589 emit_move_insn (hard_frame_pointer_rtx,
590 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));
db5ae43f 591#endif
be99da77 592#if defined (TARGET_88000) /* was m88k */
db5ae43f
MS
593 rtx temp_frame = frame_pointer_rtx;
594
595 temp_frame = memory_address (Pmode, temp_frame);
596 temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
597
598 /* hopefully this will successfully pop the frame! */
599 emit_move_insn (frame_pointer_rtx, temp_frame);
600 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
601 emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
602 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
603 (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
604
605#if 0
606 emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
607 -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
608
609 emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
610
611 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
612 (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
613#endif
614#endif
be99da77 615#if ! defined (TARGET_88000) && ! defined (ARM_FRAME_RTX) && ! defined (SPARC_STACK_ALIGN)
f30432d7
MS
616 tree fcall;
617 tree params;
618 rtx return_val_rtx;
e1cd6e56 619
be99da77 620#if 0
e92cc029 621 /* I would like to do this here, but the move below doesn't seem to work. */
f30432d7
MS
622 /* call to __builtin_return_address () */
623 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
624 fcall = build_function_call (BuiltinReturnAddress, params);
625 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
be99da77 626
f30432d7 627 emit_move_insn (return_val_rtx, inner_throw_label);
e92cc029 628 /* So, for now, just pass throw label to stack unwinder. */
f30432d7
MS
629#endif
630 params = tree_cons (NULL_TREE, make_tree (ptr_type_node,
631 inner_throw_label), NULL_TREE);
632
633 do_function_call (Unwind, params, NULL_TREE);
634 assemble_external (TREE_OPERAND (Unwind, 0));
635 emit_barrier ();
e1cd6e56 636#endif
db5ae43f 637}
8d08fdba 638
f30432d7 639
e1cd6e56 640/* is called from expand_exception_blocks () to generate the code in a function
ddd5a7c1 641 to "throw" if anything in the function needs to perform a throw.
8d08fdba 642
ddd5a7c1 643 expands "throw" as the following pseudo code:
8d2733ca
MS
644
645 throw:
646 eh = find_first_exception_match (saved_pc);
647 if (!eh) goto gotta_rethrow_it;
648 goto eh;
649
650 gotta_rethrow_it:
651 saved_pc = __builtin_return_address (0);
652 pop_to_previous_level ();
6467930b 653 goto throw; */
8d2733ca 654
f30432d7 655void
8d2733ca
MS
656expand_builtin_throw ()
657{
658 tree fcall;
659 tree params;
660 rtx return_val_rtx;
f30432d7
MS
661 rtx gotta_rethrow_it;
662 rtx gotta_call_terminate;
f30432d7
MS
663 rtx top_of_loop;
664 rtx unwind_first;
665 tree t;
666
667 if (! doing_eh (0))
668 return;
669
670 if (! throw_used)
671 return;
8d2733ca 672
f30432d7
MS
673 params = void_list_node;
674 t = build_parse_node (CALL_EXPR, get_identifier ("__throw"), params, NULL_TREE);
675 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
676 void_list_node),
677 t, NULL_TREE, NULL_TREE, 0);
678 store_parm_decls ();
679 pushlevel (0);
680 clear_last_expr ();
681 push_momentary ();
682 expand_start_bindings (0);
683
684 gotta_rethrow_it = gen_label_rtx ();
685 gotta_call_terminate = gen_label_rtx ();
f30432d7
MS
686 top_of_loop = gen_label_rtx ();
687 unwind_first = gen_label_rtx ();
688
a50f0918 689 /* These two can be frontend specific. If wanted, they can go in
e92cc029 690 expand_throw. */
a50f0918
MS
691 /* Do we have a valid object we are throwing? */
692 emit_cmp_insn (DECL_RTL (saved_throw_type), const0_rtx, EQ, NULL_RTX,
693 GET_MODE (DECL_RTL (saved_throw_type)), 0, 0);
694 emit_jump_insn (gen_beq (gotta_call_terminate));
695
f30432d7
MS
696 emit_jump (unwind_first);
697
698 emit_label (top_of_loop);
8d2733ca
MS
699
700 /* search for an exception handler for the saved_pc */
701 return_val_rtx = do_function_call (FirstExceptionMatch,
f30432d7 702 tree_cons (NULL_TREE, saved_pc, NULL_TREE),
8d2733ca 703 ptr_type_node);
e1cd6e56 704 assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
8d2733ca
MS
705
706 /* did we find one? */
707 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
708 GET_MODE (return_val_rtx), 0, 0);
709
710 /* if not, jump to gotta_rethrow_it */
711 emit_jump_insn (gen_beq (gotta_rethrow_it));
712
713 /* we found it, so jump to it */
714 emit_indirect_jump (return_val_rtx);
715
716 /* code to deal with unwinding and looking for it again */
717 emit_label (gotta_rethrow_it);
718
719 /* call to __builtin_return_address () */
be99da77
MS
720#if defined (ARM_FRAME_RTX) /* was __arm */
721 /* This should be moved into arm.h:RETURN_ADDR_RTX */
722 /* This replaces a 'call' to __builtin_return_address */
e1cd6e56 723 return_val_rtx = gen_reg_rtx (Pmode);
f30432d7 724 emit_move_insn (return_val_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
e1cd6e56 725#else
f30432d7 726 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
8d2733ca 727 fcall = build_function_call (BuiltinReturnAddress, params);
f30432d7 728 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
e1cd6e56 729#endif
8d2733ca
MS
730
731 /* did __builtin_return_address () return a valid address? */
732 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
733 GET_MODE (return_val_rtx), 0, 0);
734
735 emit_jump_insn (gen_beq (gotta_call_terminate));
736
be99da77 737 return_val_rtx = eh_outer_context (return_val_rtx);
e1cd6e56 738
be99da77 739 /* Yes it did. */
6467930b 740 emit_move_insn (eh_saved_pc_rtx, return_val_rtx);
f30432d7
MS
741
742 do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop));
743 emit_jump (top_of_loop);
8d2733ca
MS
744
745 /* no it didn't --> therefore we need to call terminate */
746 emit_label (gotta_call_terminate);
747 do_function_call (Terminate, NULL_TREE, NULL_TREE);
e1cd6e56 748 assemble_external (TREE_OPERAND (Terminate, 0));
f30432d7
MS
749
750 {
751 rtx ret_val, return_val_rtx;
752 emit_label (unwind_first);
753 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
754 0, hard_frame_pointer_rtx);
755
756 /* Set it up so that we continue inside, at the top of the loop. */
757 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
21451173
MS
758#ifdef RETURN_ADDR_OFFSET
759 return_val_rtx = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
f30432d7
MS
760 if (return_val_rtx != ret_val)
761 emit_move_insn (ret_val, return_val_rtx);
762#endif
763
e92cc029 764 /* Fall into epilogue to unwind prologue. */
f30432d7
MS
765 }
766
fc378698 767 expand_end_bindings (getdecls (), 1, 0);
f30432d7
MS
768 poplevel (1, 0, 0);
769 pop_momentary ();
770
771 finish_function (lineno, 0, 0);
8d08fdba 772}
8d2733ca
MS
773
774
f30432d7
MS
775void
776expand_start_eh_spec ()
777{
6467930b 778 expand_eh_region_start ();
f30432d7
MS
779}
780
5566b478 781static void
f30432d7
MS
782expand_end_eh_spec (raises)
783 tree raises;
784{
785 tree expr, second_try;
786 rtx check = gen_label_rtx ();
787 rtx cont;
788 rtx ret = gen_reg_rtx (Pmode);
789 rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
790 rtx end = gen_label_rtx ();
791
792 expr = make_node (RTL_EXPR);
793 TREE_TYPE (expr) = void_type_node;
794 RTL_EXPR_RTL (expr) = const0_rtx;
795 TREE_SIDE_EFFECTS (expr) = 1;
796 start_sequence_for_rtl_expr (expr);
797 cont = gen_label_rtx ();
798 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
799 emit_jump (check);
800 emit_label (cont);
801 jumpif (make_tree (integer_type_node, flag), end);
802 do_function_call (Terminate, NULL_TREE, NULL_TREE);
803 assemble_external (TREE_OPERAND (Terminate, 0));
804 emit_barrier ();
805 RTL_EXPR_SEQUENCE (expr) = get_insns ();
806 end_sequence ();
807
808 second_try = expr;
809
810 expr = make_node (RTL_EXPR);
811 TREE_TYPE (expr) = void_type_node;
812 RTL_EXPR_RTL (expr) = const0_rtx;
813 TREE_SIDE_EFFECTS (expr) = 1;
814 start_sequence_for_rtl_expr (expr);
815
816 cont = gen_label_rtx ();
817 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
818 emit_jump (check);
819 emit_label (cont);
820 jumpif (make_tree (integer_type_node, flag), end);
6467930b 821 expand_eh_region_start ();
f30432d7
MS
822 do_function_call (Unexpected, NULL_TREE, NULL_TREE);
823 assemble_external (TREE_OPERAND (Unexpected, 0));
824 emit_barrier ();
6467930b 825 expand_eh_region_end (second_try);
f30432d7
MS
826
827 emit_label (check);
828 emit_move_insn (flag, const1_rtx);
829 cont = gen_label_rtx ();
830 while (raises)
831 {
832 tree exp;
833 tree match_type = TREE_VALUE (raises);
834
835 if (match_type)
836 {
837 /* check TREE_VALUE (raises) here */
838 exp = saved_throw_value;
839 exp = tree_cons (NULL_TREE,
840 build_eh_type_type (match_type),
841 tree_cons (NULL_TREE,
842 saved_throw_type,
843 tree_cons (NULL_TREE, exp, NULL_TREE)));
844 exp = build_function_call (CatchMatch, exp);
845 assemble_external (TREE_OPERAND (CatchMatch, 0));
846
847 jumpif (exp, cont);
848 }
849
850 raises = TREE_CHAIN (raises);
851 }
852 emit_move_insn (flag, const0_rtx);
853 emit_label (cont);
854 emit_indirect_jump (ret);
855 emit_label (end);
856
857 RTL_EXPR_SEQUENCE (expr) = get_insns ();
858 end_sequence ();
859
6467930b 860 expand_eh_region_end (expr);
f30432d7
MS
861}
862
8d2733ca
MS
863/* This is called to expand all the toplevel exception handling
864 finalization for a function. It should only be called once per
865 function. */
6467930b 866
8d08fdba 867void
8d2733ca 868expand_exception_blocks ()
8d08fdba 869{
21451173 870 rtx funcend;
f30432d7 871 rtx insns;
6467930b 872 rtx eh_spec_insns = NULL_RTX;
f30432d7
MS
873
874 start_sequence ();
8d2733ca
MS
875
876 funcend = gen_label_rtx ();
877 emit_jump (funcend);
878 /* expand_null_return (); */
879
f30432d7
MS
880 start_sequence ();
881
882 /* Add all the catch clauses here. */
883 emit_insns (catch_clauses);
884 catch_clauses = NULL_RTX;
8d2733ca
MS
885
886 expand_leftover_cleanups ();
887
f30432d7
MS
888 insns = get_insns ();
889 end_sequence ();
890
6467930b
MS
891 /* Do this after we expand leftover cleanups, so that the expand_eh_region_end
892 that expand_end_eh_spec does will match the right expand_eh_region_start,
f30432d7
MS
893 and make sure it comes out before the terminate protected region. */
894 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
895 {
6467930b
MS
896#if 1
897 {
898 rtx insns;
899 /* New... */
900 start_sequence ();
901 expand_start_eh_spec ();
902 eh_spec_insns = get_insns ();
903 end_sequence ();
904 }
905#endif
906
f30432d7
MS
907 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
908 push_to_sequence (insns);
909
910 /* Now expand any new ones. */
911 expand_leftover_cleanups ();
912
913 insns = get_insns ();
914 end_sequence ();
915 }
916
917 if (insns)
918 {
6467930b 919 /* Is this necessary? */
f30432d7 920 assemble_external (TREE_OPERAND (Terminate, 0));
f30432d7 921
6467930b 922 expand_eh_region_start ();
f30432d7 923 emit_insns (insns);
6467930b
MS
924 expand_eh_region_end (TerminateFunctionCall);
925 expand_leftover_cleanups ();
f30432d7
MS
926 }
927
8d2733ca 928 {
f30432d7
MS
929 /* Mark the end of the stack unwinder. */
930 rtx unwind_insns;
931 start_sequence ();
6467930b
MS
932#if 0
933 end_eh_unwinder ();
934#endif
f30432d7
MS
935 unwind_insns = get_insns ();
936 end_sequence ();
937 if (unwind_insns)
8d2733ca 938 {
f30432d7
MS
939 insns = unwind_insns;
940 emit_insns (insns);
8d2733ca
MS
941 }
942 }
f30432d7 943
8d2733ca 944 emit_label (funcend);
f30432d7
MS
945
946 /* Only if we had previous insns do we want to emit the jump around
947 them. If there weren't any, then insns will remain NULL_RTX. */
948 if (insns)
949 insns = get_insns ();
950 end_sequence ();
951
6467930b
MS
952#if 1
953 if (eh_spec_insns)
954 emit_insns_after (eh_spec_insns, get_insns ());
955#else
956 if (eh_spec_insns)
957 store_after_parms (eh_spec_insns);
958#endif
959
f30432d7 960 emit_insns (insns);
8d08fdba
MS
961}
962
72b7eeff
MS
963tree
964start_anon_func ()
965{
966 static int counter = 0;
e92cc029 967 int old_interface_unknown = interface_unknown;
72b7eeff
MS
968 char name[32];
969 tree params;
970 tree t;
971
972 push_cp_function_context (NULL_TREE);
973 push_to_top_level ();
974
975 /* No need to mangle this. */
976 push_lang_context (lang_name_c);
977
e92cc029
MS
978 interface_unknown = 1;
979
72b7eeff
MS
980 params = void_list_node;
981 /* tcf stands for throw clean funciton. */
982 sprintf (name, "__tcf_%d", counter++);
983 t = build_parse_node (CALL_EXPR, get_identifier (name), params, NULL_TREE);
984 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
985 void_list_node),
986 t, NULL_TREE, NULL_TREE, 0);
987 store_parm_decls ();
988 pushlevel (0);
989 clear_last_expr ();
990 push_momentary ();
991 expand_start_bindings (0);
992 emit_line_note (input_filename, lineno);
993
e92cc029
MS
994 interface_unknown = old_interface_unknown;
995
72b7eeff
MS
996 pop_lang_context ();
997
998 return current_function_decl;
999}
1000
1001void
1002end_anon_func ()
1003{
fc378698 1004 expand_end_bindings (getdecls (), 1, 0);
72b7eeff
MS
1005 poplevel (1, 0, 0);
1006 pop_momentary ();
1007
1008 finish_function (lineno, 0, 0);
1009
1010 pop_from_top_level ();
1011 pop_cp_function_context (NULL_TREE);
1012}
8d2733ca 1013
6467930b 1014/* Expand a throw statement. This follows the following
8d2733ca
MS
1015 algorithm:
1016
1017 1. Allocate space to save the current PC onto the stack.
1018 2. Generate and emit a label and save its address into the
e1cd6e56 1019 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
1020 3. If this is the first call to throw in this function:
1021 generate a label for the throw block
1022 4. jump to the throw block label. */
6467930b 1023
8d08fdba 1024void
8d2733ca
MS
1025expand_throw (exp)
1026 tree exp;
8d08fdba 1027{
8d2733ca 1028 rtx label;
8d08fdba 1029
8d2733ca
MS
1030 if (! doing_eh (1))
1031 return;
8d08fdba 1032
8d2733ca
MS
1033 if (exp)
1034 {
faae18ab 1035 tree throw_type;
72b7eeff 1036 tree cleanup = empty_fndecl, e;
faae18ab 1037
a3b49ccd 1038 /* throw expression */
e92cc029 1039 /* First, decay it. */
f30432d7 1040 exp = decay_conversion (exp);
a3b49ccd 1041
f30432d7
MS
1042 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
1043 {
1044 throw_type = build_eh_type (exp);
1045 exp = build_reinterpret_cast (ptr_type_node, exp);
1046 }
1047 else
1048 {
72b7eeff
MS
1049 rtx cleanup_insns;
1050 tree object;
a50f0918 1051
f30432d7
MS
1052 /* Make a copy of the thrown object. WP 15.1.5 */
1053 exp = build_new (NULL_TREE, TREE_TYPE (exp),
1054 build_tree_list (NULL_TREE, exp),
1055 0);
faae18ab 1056
f30432d7
MS
1057 if (exp == error_mark_node)
1058 error (" in thrown expression");
faae18ab 1059
72b7eeff
MS
1060 object = build_indirect_ref (exp, NULL_PTR);
1061 throw_type = build_eh_type (object);
1062
1063 start_sequence ();
1064 object = build_reinterpret_cast (TREE_TYPE (exp), saved_throw_value);
1065 object = build_indirect_ref (object, NULL_PTR);
c73964b2 1066 cleanup = maybe_build_cleanup_and_delete (object);
72b7eeff
MS
1067 if (cleanup)
1068 expand_expr (cleanup, const0_rtx, VOIDmode, 0);
1069 cleanup_insns = get_insns ();
1070 end_sequence ();
1071
1072 if (cleanup && cleanup_insns)
1073 {
1074 cleanup = start_anon_func ();
1075
c73964b2
MS
1076 expand_expr (maybe_build_cleanup_and_delete (object),
1077 const0_rtx, VOIDmode, 0);
72b7eeff
MS
1078
1079 end_anon_func ();
1080
1081 mark_addressable (cleanup);
1082 }
1083 else
1084 {
1085 cleanup = empty_fndecl;
1086 }
f30432d7 1087 }
faae18ab 1088
be99da77
MS
1089 if (cleanup == empty_fndecl)
1090 assemble_external (empty_fndecl);
1091
f30432d7
MS
1092 e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type);
1093 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff 1094
f30432d7
MS
1095 e = build_modify_expr (saved_throw_value, NOP_EXPR, exp);
1096 e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e);
1097 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff
MS
1098
1099 cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
1100 cleanup = build_modify_expr (saved_cleanup, NOP_EXPR, cleanup);
1101 expand_expr (cleanup, const0_rtx, VOIDmode, 0);
8d2733ca
MS
1102 }
1103 else
a3b49ccd
MS
1104 {
1105 /* rethrow current exception */
8ccc31eb 1106 /* This part is easy, as we don't have to do anything else. */
a3b49ccd 1107 }
8d2733ca 1108
6467930b
MS
1109 /* This is the label that represents where in the code we were, when
1110 we got an exception. This needs to be updated when we rethrow an
1111 exception, so that the matching routine knows to search out. */
1112 label = gen_label_rtx ();
1113 emit_label (label);
8d2733ca 1114
6467930b 1115 expand_internal_throw (label);
f376e137 1116}
8d2733ca
MS
1117
1118/* Build a throw expression. */
6467930b 1119
8d2733ca
MS
1120tree
1121build_throw (e)
1122 tree e;
1123{
db5ae43f
MS
1124 if (e != error_mark_node)
1125 {
fc378698
MS
1126 if (current_template_parms)
1127 return build_min (THROW_EXPR, void_type_node, e);
db5ae43f
MS
1128 e = build1 (THROW_EXPR, void_type_node, e);
1129 TREE_SIDE_EFFECTS (e) = 1;
faae18ab 1130 TREE_USED (e) = 1;
db5ae43f 1131 }
8d2733ca 1132 return e;
8d08fdba 1133}
This page took 0.272736 seconds and 5 git commands to generate.