llvm.org GIT mirror llvm / 9f469a0
ExceptionDemo.cpp: Whitespace. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165795 91177308-0d34-0410-b5e6-96231b3b80d8 NAKAMURA Takumi 7 years ago
1 changed file(s) with 587 addition(s) and 588 deletion(s). Raw diff Collapse all Expand all
99 // Demo program which implements an example LLVM exception implementation, and
1010 // shows several test cases including the handling of foreign exceptions.
1111 // It is run with type info types arguments to throw. A test will
12 // be run for each given type info type. While type info types with the value
12 // be run for each given type info type. While type info types with the value
1313 // of -1 will trigger a foreign C++ exception to be thrown; type info types
14 // <= 6 and >= 1 will cause the associated generated exceptions to be thrown
14 // <= 6 and >= 1 will cause the associated generated exceptions to be thrown
1515 // and caught by generated test functions; and type info types > 6
1616 // will result in exceptions which pass through to the test harness. All other
1717 // type info types are not supported and could cause a crash. In all cases,
18 // the "finally" blocks of every generated test functions will executed
18 // the "finally" blocks of every generated test functions will executed
1919 // regardless of whether or not that test function ignores or catches the
2020 // thrown exception.
2121 //
2424 // ExceptionDemo
2525 //
2626 // causes a usage to be printed to stderr
27 //
27 //
2828 // ExceptionDemo 2 3 7 -1
2929 //
3030 // results in the following cases:
31 // - Value 2 causes an exception with a type info type of 2 to be
31 // - Value 2 causes an exception with a type info type of 2 to be
3232 // thrown and caught by an inner generated test function.
33 // - Value 3 causes an exception with a type info type of 3 to be
33 // - Value 3 causes an exception with a type info type of 3 to be
3434 // thrown and caught by an outer generated test function.
35 // - Value 7 causes an exception with a type info type of 7 to be
35 // - Value 7 causes an exception with a type info type of 7 to be
3636 // thrown and NOT be caught by any generated function.
3737 // - Value -1 causes a foreign C++ exception to be thrown and not be
3838 // caught by any generated function
3939 //
4040 // Cases -1 and 7 are caught by a C++ test harness where the validity of
41 // of a C++ catch(...) clause catching a generated exception with a
42 // type info type of 7 is explained by: example in rules 1.6.4 in
41 // of a C++ catch(...) clause catching a generated exception with a
42 // type info type of 7 is explained by: example in rules 1.6.4 in
4343 // http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
4444 //
45 // This code uses code from the llvm compiler-rt project and the llvm
45 // This code uses code from the llvm compiler-rt project and the llvm
4646 // Kaleidoscope project.
4747 //
4848 //===----------------------------------------------------------------------===//
6262 #include "llvm/Support/Dwarf.h"
6363 #include "llvm/Support/TargetSelect.h"
6464
65 // FIXME: Although all systems tested with (Linux, OS X), do not need this
66 // header file included. A user on ubuntu reported, undefined symbols
65 // FIXME: Although all systems tested with (Linux, OS X), do not need this
66 // header file included. A user on ubuntu reported, undefined symbols
6767 // for stderr, and fprintf, and the addition of this include fixed the
68 // issue for them. Given that LLVM's best practices include the goal
69 // of reducing the number of redundant header files included, the
70 // correct solution would be to find out why these symbols are not
68 // issue for them. Given that LLVM's best practices include the goal
69 // of reducing the number of redundant header files included, the
70 // correct solution would be to find out why these symbols are not
7171 // defined for the system in question, and fix the issue by finding out
7272 // which LLVM header file, if any, would include these symbols.
7373 #include
8080 #define USE_GLOBAL_STR_CONSTS true
8181 #endif
8282
83 // System C++ ABI unwind types from:
83 // System C++ ABI unwind types from:
8484 // http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
8585
8686 extern "C" {
87
87
8888 typedef enum {
8989 _URC_NO_REASON = 0,
9090 _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
9696 _URC_INSTALL_CONTEXT = 7,
9797 _URC_CONTINUE_UNWIND = 8
9898 } _Unwind_Reason_Code;
99
99
100100 typedef enum {
101101 _UA_SEARCH_PHASE = 1,
102102 _UA_CLEANUP_PHASE = 2,
104104 _UA_FORCE_UNWIND = 8,
105105 _UA_END_OF_STACK = 16
106106 } _Unwind_Action;
107
107
108108 struct _Unwind_Exception;
109
109
110110 typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
111111 struct _Unwind_Exception *);
112
112
113113 struct _Unwind_Exception {
114114 uint64_t exception_class;
115115 _Unwind_Exception_Cleanup_Fn exception_cleanup;
116
117 uintptr_t private_1;
118 uintptr_t private_2;
119
116
117 uintptr_t private_1;
118 uintptr_t private_2;
119
120120 // @@@ The IA-64 ABI says that this structure must be double-word aligned.
121 // Taking that literally does not make much sense generically. Instead
121 // Taking that literally does not make much sense generically. Instead
122122 // we provide the maximum alignment required by any type for the machine.
123123 } __attribute__((__aligned__));
124
124
125125 struct _Unwind_Context;
126126 typedef struct _Unwind_Context *_Unwind_Context_t;
127
127
128128 extern const uint8_t *_Unwind_GetLanguageSpecificData (_Unwind_Context_t c);
129129 extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i);
130130 extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n);
131131 extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value);
132132 extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context);
133133 extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context);
134
134
135135 } // extern "C"
136136
137137 //
147147
148148 /// This is our Exception class which relies on a negative offset to calculate
149149 /// pointers to its instances from pointers to its unwindException member.
150 ///
150 ///
151151 /// Note: The above unwind.h defines struct _Unwind_Exception to be aligned
152152 /// on a double word boundary. This is necessary to match the standard:
153153 /// http://refspecs.freestandards.org/abi-eh-1.21.html
154154 struct OurBaseException_t {
155155 struct OurExceptionType_t type;
156
156
157157 // Note: This is properly aligned in unwind.h
158158 struct _Unwind_Exception unwindException;
159159 };
164164 typedef struct _Unwind_Exception OurUnwindException;
165165
166166 //
167 // Various globals used to support typeinfo and generatted exceptions in
167 // Various globals used to support typeinfo and generatted exceptions in
168168 // general
169169 //
170170
172172
173173 int64_t ourBaseFromUnwindOffset;
174174
175 const unsigned char ourBaseExcpClassChars[] =
175 const unsigned char ourBaseExcpClassChars[] =
176176 {'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'};
177177
178178
202202 /// @param retType function return type
203203 /// @param theArgTypes function's ordered argument types
204204 /// @param theArgNames function's ordered arguments needed if use of this
205 /// function corresponds to a function definition. Use empty
205 /// function corresponds to a function definition. Use empty
206206 /// aggregate for function declarations.
207207 /// @param functName function name
208208 /// @param linkage function linkage
223223 llvm::Function::Create(functType, linkage, functName, &module);
224224 if (!ret || declarationOnly)
225225 return(ret);
226
226
227227 namedValues.clear();
228 unsigned i = 0;
228 unsigned i = 0;
229229 for (llvm::Function::arg_iterator argIndex = ret->arg_begin();
230230 i != theArgNames.size();
231231 ++argIndex, ++i) {
232
232
233233 argIndex->setName(theArgNames[i]);
234234 namedValues[theArgNames[i]] = argIndex;
235235 }
236
236
237237 return(ret);
238238 }
239239
249249 const std::string &varName,
250250 llvm::Type *type,
251251 llvm::Constant *initWith = 0) {
252 llvm::BasicBlock &block = function.getEntryBlock();
252 llvm::BasicBlock &block = function.getEntryBlock();
253253 llvm::IRBuilder<> tmp(&block, block.begin());
254254 llvm::AllocaInst *ret = tmp.CreateAlloca(type, 0, varName.c_str());
255
256 if (initWith)
255
256 if (initWith)
257257 tmp.CreateStore(initWith, ret);
258
258
259259 return(ret);
260260 }
261261
265265 //
266266
267267 //
268 // Runtime C Library functions
268 // Runtime C Library functions
269269 //
270270
271271 // Note: using an extern "C" block so that static functions can be used
274274 // Note: Better ways to decide on bit width
275275 //
276276 /// Prints a 32 bit number, according to the format, to stderr.
277 /// @param intToPrint integer to print
277 /// @param intToPrint integer to print
278278 /// @param format printf like format to use when printing
279279 void print32Int(int intToPrint, const char *format) {
280280 if (format) {
291291 // Note: Better ways to decide on bit width
292292 //
293293 /// Prints a 64 bit number, according to the format, to stderr.
294 /// @param intToPrint integer to print
294 /// @param intToPrint integer to print
295295 /// @param format printf like format to use when printing
296296 void print64Int(long int intToPrint, const char *format) {
297297 if (format) {
326326 fprintf(stderr,
327327 "deleteOurException(...).\n");
328328 #endif
329
329
330330 if (expToDelete &&
331331 (expToDelete->exception_class == ourBaseExceptionClass)) {
332
332
333333 free(((char*) expToDelete) + ourBaseFromUnwindOffset);
334334 }
335335 }
336336
337337
338 /// This function is the struct _Unwind_Exception API mandated delete function
339 /// used by foreign exception handlers when deleting our exception
338 /// This function is the struct _Unwind_Exception API mandated delete function
339 /// used by foreign exception handlers when deleting our exception
340340 /// (OurException), instances.
341 /// @param reason @link http://refspecs.freestandards.org/abi-eh-1.21.html
341 /// @param reason @link http://refspecs.freestandards.org/abi-eh-1.21.html
342342 /// @unlink
343343 /// @param expToDelete exception instance to delete
344344 void deleteFromUnwindOurException(_Unwind_Reason_Code reason,
347347 fprintf(stderr,
348348 "deleteFromUnwindOurException(...).\n");
349349 #endif
350
350
351351 deleteOurException(expToDelete);
352352 }
353353
361361 (ret->type).type = type;
362362 (ret->unwindException).exception_class = ourBaseExceptionClass;
363363 (ret->unwindException).exception_cleanup = deleteFromUnwindOurException;
364
364
365365 return(&(ret->unwindException));
366366 }
367367
368368
369 /// Read a uleb128 encoded value and advance pointer
370 /// See Variable Length Data in:
369 /// Read a uleb128 encoded value and advance pointer
370 /// See Variable Length Data in:
371371 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
372372 /// @param data reference variable holding memory pointer to decode from
373373 /// @returns decoded value
376376 uintptr_t shift = 0;
377377 unsigned char byte;
378378 const uint8_t *p = *data;
379
379
380380 do {
381381 byte = *p++;
382382 result |= (byte & 0x7f) << shift;
383383 shift += 7;
384 }
384 }
385385 while (byte & 0x80);
386
386
387387 *data = p;
388
388
389389 return result;
390390 }
391391
392392
393 /// Read a sleb128 encoded value and advance pointer
394 /// See Variable Length Data in:
393 /// Read a sleb128 encoded value and advance pointer
394 /// See Variable Length Data in:
395395 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
396396 /// @param data reference variable holding memory pointer to decode from
397397 /// @returns decoded value
400400 uintptr_t shift = 0;
401401 unsigned char byte;
402402 const uint8_t *p = *data;
403
403
404404 do {
405405 byte = *p++;
406406 result |= (byte & 0x7f) << shift;
407407 shift += 7;
408 }
408 }
409409 while (byte & 0x80);
410
410
411411 *data = p;
412
412
413413 if ((byte & 0x40) && (shift < (sizeof(result) << 3))) {
414414 result |= (~0 << shift);
415415 }
416
416
417417 return result;
418418 }
419419
420420
421 /// Read a pointer encoded value and advance pointer
422 /// See Variable Length Data in:
421 /// Read a pointer encoded value and advance pointer
422 /// See Variable Length Data in:
423423 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
424424 /// @param data reference variable holding memory pointer to decode from
425425 /// @param encoding dwarf encoding type
427427 static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
428428 uintptr_t result = 0;
429429 const uint8_t *p = *data;
430
431 if (encoding == llvm::dwarf::DW_EH_PE_omit)
430
431 if (encoding == llvm::dwarf::DW_EH_PE_omit)
432432 return(result);
433
434 // first get value
433
434 // first get value
435435 switch (encoding & 0x0F) {
436436 case llvm::dwarf::DW_EH_PE_absptr:
437437 result = *((uintptr_t*)p);
469469 p += sizeof(int64_t);
470470 break;
471471 default:
472 // not supported
472 // not supported
473473 abort();
474474 break;
475475 }
476
477 // then add relative offset
476
477 // then add relative offset
478478 switch (encoding & 0x70) {
479479 case llvm::dwarf::DW_EH_PE_absptr:
480 // do nothing
480 // do nothing
481481 break;
482482 case llvm::dwarf::DW_EH_PE_pcrel:
483483 result += (uintptr_t)(*data);
487487 case llvm::dwarf::DW_EH_PE_funcrel:
488488 case llvm::dwarf::DW_EH_PE_aligned:
489489 default:
490 // not supported
490 // not supported
491491 abort();
492492 break;
493493 }
494
495 // then apply indirection
494
495 // then apply indirection
496496 if (encoding & llvm::dwarf::DW_EH_PE_indirect) {
497497 result = *((uintptr_t*)result);
498498 }
499
499
500500 *data = p;
501
501
502502 return result;
503503 }
504504
505505
506 /// Deals with Dwarf actions matching our type infos
507 /// (OurExceptionType_t instances). Returns whether or not a dwarf emitted
508 /// action matches the supplied exception type. If such a match succeeds,
509 /// the resultAction argument will be set with > 0 index value. Only
510 /// corresponding llvm.eh.selector type info arguments, cleanup arguments
506 /// Deals with Dwarf actions matching our type infos
507 /// (OurExceptionType_t instances). Returns whether or not a dwarf emitted
508 /// action matches the supplied exception type. If such a match succeeds,
509 /// the resultAction argument will be set with > 0 index value. Only
510 /// corresponding llvm.eh.selector type info arguments, cleanup arguments
511511 /// are supported. Filters are not supported.
512 /// See Variable Length Data in:
512 /// See Variable Length Data in:
513513 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
514514 /// Also see @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink
515515 /// @param resultAction reference variable which will be set with result
516516 /// @param classInfo our array of type info pointers (to globals)
517 /// @param actionEntry index into above type info array or 0 (clean up).
517 /// @param actionEntry index into above type info array or 0 (clean up).
518518 /// We do not support filters.
519519 /// @param exceptionClass exception class (_Unwind_Exception::exception_class)
520520 /// of thrown exception.
522522 /// @returns whether or not a type info was found. False is returned if only
523523 /// a cleanup was found
524524 static bool handleActionValue(int64_t *resultAction,
525 struct OurExceptionType_t **classInfo,
526 uintptr_t actionEntry,
527 uint64_t exceptionClass,
525 struct OurExceptionType_t **classInfo,
526 uintptr_t actionEntry,
527 uint64_t exceptionClass,
528528 struct _Unwind_Exception *exceptionObject) {
529529 bool ret = false;
530
531 if (!resultAction ||
532 !exceptionObject ||
530
531 if (!resultAction ||
532 !exceptionObject ||
533533 (exceptionClass != ourBaseExceptionClass))
534534 return(ret);
535
535
536536 struct OurBaseException_t *excp = (struct OurBaseException_t*)
537537 (((char*) exceptionObject) + ourBaseFromUnwindOffset);
538538 struct OurExceptionType_t *excpType = &(excp->type);
539539 int type = excpType->type;
540
540
541541 #ifdef DEBUG
542542 fprintf(stderr,
543543 "handleActionValue(...): exceptionObject = <%p>, "
545545 exceptionObject,
546546 excp);
547547 #endif
548
548
549549 const uint8_t *actionPos = (uint8_t*) actionEntry,
550550 *tempActionPos;
551551 int64_t typeOffset = 0,
552552 actionOffset;
553
553
554554 for (int i = 0; true; ++i) {
555555 // Each emitted dwarf action corresponds to a 2 tuple of
556556 // type info address offset, and action offset to the next
558558 typeOffset = readSLEB128(&actionPos);
559559 tempActionPos = actionPos;
560560 actionOffset = readSLEB128(&tempActionPos);
561
561
562562 #ifdef DEBUG
563563 fprintf(stderr,
564564 "handleActionValue(...):typeOffset: <%lld>, "
566566 typeOffset,
567567 actionOffset);
568568 #endif
569 assert((typeOffset >= 0) &&
569 assert((typeOffset >= 0) &&
570570 "handleActionValue(...):filters are not supported.");
571
571
572572 // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector
573573 // argument has been matched.
574574 if ((typeOffset > 0) &&
582582 ret = true;
583583 break;
584584 }
585
585
586586 #ifdef DEBUG
587587 fprintf(stderr,
588588 "handleActionValue(...):actionValue not found.\n");
589589 #endif
590590 if (!actionOffset)
591591 break;
592
592
593593 actionPos += actionOffset;
594594 }
595
595
596596 return(ret);
597597 }
598598
601601 /// See @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink
602602 /// @param version unsupported (ignored), unwind version
603603 /// @param lsda language specific data area
604 /// @param _Unwind_Action actions minimally supported unwind stage
604 /// @param _Unwind_Action actions minimally supported unwind stage
605605 /// (forced specifically not supported)
606606 /// @param exceptionClass exception class (_Unwind_Exception::exception_class)
607607 /// of thrown exception.
608608 /// @param exceptionObject thrown _Unwind_Exception instance.
609609 /// @param context unwind system context
610 /// @returns minimally supported unwinding control indicator
611 static _Unwind_Reason_Code handleLsda(int version,
610 /// @returns minimally supported unwinding control indicator
611 static _Unwind_Reason_Code handleLsda(int version,
612612 const uint8_t *lsda,
613613 _Unwind_Action actions,
614 uint64_t exceptionClass,
614 uint64_t exceptionClass,
615615 struct _Unwind_Exception *exceptionObject,
616616 _Unwind_Context_t context) {
617617 _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND;
618
618
619619 if (!lsda)
620620 return(ret);
621
621
622622 #ifdef DEBUG
623 fprintf(stderr,
623 fprintf(stderr,
624624 "handleLsda(...):lsda is non-zero.\n");
625625 #endif
626
626
627627 // Get the current instruction pointer and offset it before next
628628 // instruction in the current frame which threw the exception.
629629 uintptr_t pc = _Unwind_GetIP(context)-1;
630
631 // Get beginning current frame's code (as defined by the
630
631 // Get beginning current frame's code (as defined by the
632632 // emitted dwarf code)
633633 uintptr_t funcStart = _Unwind_GetRegionStart(context);
634634 uintptr_t pcOffset = pc - funcStart;
635635 struct OurExceptionType_t **classInfo = NULL;
636
636
637637 // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
638638 // dwarf emission
639
639
640640 // Parse LSDA header.
641641 uint8_t lpStartEncoding = *lsda++;
642
642
643643 if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) {
644 readEncodedPointer(&lsda, lpStartEncoding);
645 }
646
644 readEncodedPointer(&lsda, lpStartEncoding);
645 }
646
647647 uint8_t ttypeEncoding = *lsda++;
648648 uintptr_t classInfoOffset;
649
649
650650 if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) {
651651 // Calculate type info locations in emitted dwarf code which
652652 // were flagged by type info arguments to llvm.eh.selector
654654 classInfoOffset = readULEB128(&lsda);
655655 classInfo = (struct OurExceptionType_t**) (lsda + classInfoOffset);
656656 }
657
658 // Walk call-site table looking for range that
659 // includes current PC.
660
657
658 // Walk call-site table looking for range that
659 // includes current PC.
660
661661 uint8_t callSiteEncoding = *lsda++;
662662 uint32_t callSiteTableLength = readULEB128(&lsda);
663663 const uint8_t *callSiteTableStart = lsda;
664 const uint8_t *callSiteTableEnd = callSiteTableStart +
664 const uint8_t *callSiteTableEnd = callSiteTableStart +
665665 callSiteTableLength;
666666 const uint8_t *actionTableStart = callSiteTableEnd;
667667 const uint8_t *callSitePtr = callSiteTableStart;
668
668
669669 bool foreignException = false;
670
670
671671 while (callSitePtr < callSiteTableEnd) {
672 uintptr_t start = readEncodedPointer(&callSitePtr,
672 uintptr_t start = readEncodedPointer(&callSitePtr,
673673 callSiteEncoding);
674 uintptr_t length = readEncodedPointer(&callSitePtr,
674 uintptr_t length = readEncodedPointer(&callSitePtr,
675675 callSiteEncoding);
676 uintptr_t landingPad = readEncodedPointer(&callSitePtr,
676 uintptr_t landingPad = readEncodedPointer(&callSitePtr,
677677 callSiteEncoding);
678
678
679679 // Note: Action value
680680 uintptr_t actionEntry = readULEB128(&callSitePtr);
681
681
682682 if (exceptionClass != ourBaseExceptionClass) {
683683 // We have been notified of a foreign exception being thrown,
684684 // and we therefore need to execute cleanup landing pads
685685 actionEntry = 0;
686686 foreignException = true;
687687 }
688
688
689689 if (landingPad == 0) {
690690 #ifdef DEBUG
691691 fprintf(stderr,
692692 "handleLsda(...): No landing pad found.\n");
693693 #endif
694
694
695695 continue; // no landing pad for this entry
696696 }
697
697
698698 if (actionEntry) {
699699 actionEntry += ((uintptr_t) actionTableStart) - 1;
700700 }
704704 "handleLsda(...):No action table found.\n");
705705 #endif
706706 }
707
707
708708 bool exceptionMatched = false;
709
709
710710 if ((start <= pcOffset) && (pcOffset < (start + length))) {
711711 #ifdef DEBUG
712712 fprintf(stderr,
713713 "handleLsda(...): Landing pad found.\n");
714714 #endif
715715 int64_t actionValue = 0;
716
716
717717 if (actionEntry) {
718718 exceptionMatched = handleActionValue(&actionValue,
719 classInfo,
720 actionEntry,
721 exceptionClass,
719 classInfo,
720 actionEntry,
721 exceptionClass,
722722 exceptionObject);
723723 }
724
724
725725 if (!(actions & _UA_SEARCH_PHASE)) {
726726 #ifdef DEBUG
727727 fprintf(stderr,
728728 "handleLsda(...): installed landing pad "
729729 "context.\n");
730730 #endif
731
731
732732 // Found landing pad for the PC.
733 // Set Instruction Pointer to so we re-enter function
734 // at landing pad. The landing pad is created by the
733 // Set Instruction Pointer to so we re-enter function
734 // at landing pad. The landing pad is created by the
735735 // compiler to take two parameters in registers.
736 _Unwind_SetGR(context,
737 __builtin_eh_return_data_regno(0),
736 _Unwind_SetGR(context,
737 __builtin_eh_return_data_regno(0),
738738 (uintptr_t)exceptionObject);
739
739
740740 // Note: this virtual register directly corresponds
741741 // to the return of the llvm.eh.selector intrinsic
742742 if (!actionEntry || !exceptionMatched) {
743743 // We indicate cleanup only
744 _Unwind_SetGR(context,
745 __builtin_eh_return_data_regno(1),
744 _Unwind_SetGR(context,
745 __builtin_eh_return_data_regno(1),
746746 0);
747747 }
748748 else {
749749 // Matched type info index of llvm.eh.selector intrinsic
750750 // passed here.
751 _Unwind_SetGR(context,
752 __builtin_eh_return_data_regno(1),
751 _Unwind_SetGR(context,
752 __builtin_eh_return_data_regno(1),
753753 actionValue);
754754 }
755
755
756756 // To execute landing pad set here
757757 _Unwind_SetIP(context, funcStart + landingPad);
758758 ret = _URC_INSTALL_CONTEXT;
766766 }
767767 else {
768768 // Note: Only non-clean up handlers are marked as
769 // found. Otherwise the clean up handlers will be
770 // re-found and executed during the clean up
769 // found. Otherwise the clean up handlers will be
770 // re-found and executed during the clean up
771771 // phase.
772772 #ifdef DEBUG
773773 fprintf(stderr,
774774 "handleLsda(...): cleanup handler found.\n");
775775 #endif
776776 }
777
777
778778 break;
779779 }
780780 }
781
781
782782 return(ret);
783783 }
784784
787787 /// dwarf unwind info block. Again see: JITDwarfEmitter.cpp.
788788 /// See @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink
789789 /// @param version unsupported (ignored), unwind version
790 /// @param _Unwind_Action actions minimally supported unwind stage
790 /// @param _Unwind_Action actions minimally supported unwind stage
791791 /// (forced specifically not supported)
792792 /// @param exceptionClass exception class (_Unwind_Exception::exception_class)
793793 /// of thrown exception.
794794 /// @param exceptionObject thrown _Unwind_Exception instance.
795795 /// @param context unwind system context
796 /// @returns minimally supported unwinding control indicator
797 _Unwind_Reason_Code ourPersonality(int version,
796 /// @returns minimally supported unwinding control indicator
797 _Unwind_Reason_Code ourPersonality(int version,
798798 _Unwind_Action actions,
799 uint64_t exceptionClass,
799 uint64_t exceptionClass,
800800 struct _Unwind_Exception *exceptionObject,
801801 _Unwind_Context_t context) {
802802 #ifdef DEBUG
803 fprintf(stderr,
803 fprintf(stderr,
804804 "We are in ourPersonality(...):actions is <%d>.\n",
805805 actions);
806
806
807807 if (actions & _UA_SEARCH_PHASE) {
808808 fprintf(stderr, "ourPersonality(...):In search phase.\n");
809809 }
811811 fprintf(stderr, "ourPersonality(...):In non-search phase.\n");
812812 }
813813 #endif
814
814
815815 const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context);
816
816
817817 #ifdef DEBUG
818 fprintf(stderr,
818 fprintf(stderr,
819819 "ourPersonality(...):lsda = <%p>.\n",
820820 lsda);
821821 #endif
822
822
823823 // The real work of the personality function is captured here
824824 return(handleLsda(version,
825825 lsda,
840840 uint64_t genClass(const unsigned char classChars[], size_t classCharsSize)
841841 {
842842 uint64_t ret = classChars[0];
843
843
844844 for (unsigned i = 1; i < classCharsSize; ++i) {
845845 ret <<= 8;
846846 ret += classChars[i];
847847 }
848
848
849849 return(ret);
850850 }
851851
864864 /// @param module code for module instance
865865 /// @param builder builder instance
866866 /// @param toPrint string to print
867 /// @param useGlobal A value of true (default) indicates a GlobalValue is
868 /// generated, and is used to hold the constant string. A value of
869 /// false indicates that the constant string will be stored on the
867 /// @param useGlobal A value of true (default) indicates a GlobalValue is
868 /// generated, and is used to hold the constant string. A value of
869 /// false indicates that the constant string will be stored on the
870870 /// stack.
871 void generateStringPrint(llvm::LLVMContext &context,
871 void generateStringPrint(llvm::LLVMContext &context,
872872 llvm::Module &module,
873 llvm::IRBuilder<> &builder,
873 llvm::IRBuilder<> &builder,
874874 std::string toPrint,
875875 bool useGlobal = true) {
876876 llvm::Function *printFunct = module.getFunction("printStr");
877
877
878878 llvm::Value *stringVar;
879 llvm::Constant *stringConstant =
879 llvm::Constant *stringConstant =
880880 llvm::ConstantDataArray::getString(context, toPrint);
881
881
882882 if (useGlobal) {
883883 // Note: Does not work without allocation
884 stringVar =
885 new llvm::GlobalVariable(module,
884 stringVar =
885 new llvm::GlobalVariable(module,
886886 stringConstant->getType(),
887 true,
888 llvm::GlobalValue::LinkerPrivateLinkage,
889 stringConstant,
887 true,
888 llvm::GlobalValue::LinkerPrivateLinkage,
889 stringConstant,
890890 "");
891891 }
892892 else {
893893 stringVar = builder.CreateAlloca(stringConstant->getType());
894894 builder.CreateStore(stringConstant, stringVar);
895895 }
896
897 llvm::Value *cast = builder.CreatePointerCast(stringVar,
896
897 llvm::Value *cast = builder.CreatePointerCast(stringVar,
898898 builder.getInt8PtrTy());
899899 builder.CreateCall(printFunct, cast);
900900 }
908908 /// @param printFunct function used to "print" integer
909909 /// @param toPrint string to print
910910 /// @param format printf like formating string for print
911 /// @param useGlobal A value of true (default) indicates a GlobalValue is
912 /// generated, and is used to hold the constant string. A value of
913 /// false indicates that the constant string will be stored on the
911 /// @param useGlobal A value of true (default) indicates a GlobalValue is
912 /// generated, and is used to hold the constant string. A value of
913 /// false indicates that the constant string will be stored on the
914914 /// stack.
915 void generateIntegerPrint(llvm::LLVMContext &context,
915 void generateIntegerPrint(llvm::LLVMContext &context,
916916 llvm::Module &module,
917 llvm::IRBuilder<> &builder,
917 llvm::IRBuilder<> &builder,
918918 llvm::Function &printFunct,
919919 llvm::Value &toPrint,
920 std::string format,
920 std::string format,
921921 bool useGlobal = true) {
922922 llvm::Constant *stringConstant =
923923 llvm::ConstantDataArray::getString(context, format);
924924 llvm::Value *stringVar;
925
925
926926 if (useGlobal) {
927927 // Note: Does not seem to work without allocation
928 stringVar =
929 new llvm::GlobalVariable(module,
928 stringVar =
929 new llvm::GlobalVariable(module,
930930 stringConstant->getType(),
931 true,
932 llvm::GlobalValue::LinkerPrivateLinkage,
933 stringConstant,
931 true,
932 llvm::GlobalValue::LinkerPrivateLinkage,
933 stringConstant,
934934 "");
935935 }
936936 else {
937937 stringVar = builder.CreateAlloca(stringConstant->getType());
938938 builder.CreateStore(stringConstant, stringVar);
939939 }
940
941 llvm::Value *cast = builder.CreateBitCast(stringVar,
940
941 llvm::Value *cast = builder.CreateBitCast(stringVar,
942942 builder.getInt8PtrTy());
943943 builder.CreateCall2(&printFunct, &toPrint, cast);
944944 }
945945
946946
947 /// Generates code to handle finally block type semantics: always runs
948 /// regardless of whether a thrown exception is passing through or the
949 /// parent function is simply exiting. In addition to printing some state
950 /// to stderr, this code will resume the exception handling--runs the
951 /// unwind resume block, if the exception has not been previously caught
952 /// by a catch clause, and will otherwise execute the end block (terminator
953 /// block). In addition this function creates the corresponding function's
947 /// Generates code to handle finally block type semantics: always runs
948 /// regardless of whether a thrown exception is passing through or the
949 /// parent function is simply exiting. In addition to printing some state
950 /// to stderr, this code will resume the exception handling--runs the
951 /// unwind resume block, if the exception has not been previously caught
952 /// by a catch clause, and will otherwise execute the end block (terminator
953 /// block). In addition this function creates the corresponding function's
954954 /// stack storage for the exception pointer and catch flag status.
955955 /// @param context llvm context
956956 /// @param module code for module instance
964964 /// @param exceptionStorage reference to exception pointer storage
965965 /// @param caughtResultStorage reference to landingpad result storage
966966 /// @returns newly created block
967 static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
968 llvm::Module &module,
969 llvm::IRBuilder<> &builder,
967 static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
968 llvm::Module &module,
969 llvm::IRBuilder<> &builder,
970970 llvm::Function &toAddTo,
971971 std::string &blockName,
972972 std::string &functionId,
975975 llvm::Value **exceptionCaughtFlag,
976976 llvm::Value **exceptionStorage,
977977 llvm::Value **caughtResultStorage) {
978 assert(exceptionCaughtFlag &&
978 assert(exceptionCaughtFlag &&
979979 "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
980980 "is NULL");
981 assert(exceptionStorage &&
981 assert(exceptionStorage &&
982982 "ExceptionDemo::createFinallyBlock(...):exceptionStorage "
983983 "is NULL");
984 assert(caughtResultStorage &&
984 assert(caughtResultStorage &&
985985 "ExceptionDemo::createFinallyBlock(...):caughtResultStorage "
986986 "is NULL");
987
987
988988 *exceptionCaughtFlag = createEntryBlockAlloca(toAddTo,
989989 "exceptionCaught",
990990 ourExceptionNotThrownState->getType(),
991991 ourExceptionNotThrownState);
992
992
993993 llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy();
994994 *exceptionStorage = createEntryBlockAlloca(toAddTo,
995995 "exceptionStorage",
10011001 ourCaughtResultType,
10021002 llvm::ConstantAggregateZero::get(
10031003 ourCaughtResultType));
1004
1004
10051005 llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
10061006 blockName,
10071007 &toAddTo);
1008
1008
10091009 builder.SetInsertPoint(ret);
1010
1010
10111011 std::ostringstream bufferToPrint;
10121012 bufferToPrint << "Gen: Executing finally block "
10131013 << blockName << " in " << functionId << "\n";
1014 generateStringPrint(context,
1015 module,
1016 builder,
1014 generateStringPrint(context,
1015 module,
1016 builder,
10171017 bufferToPrint.str(),
10181018 USE_GLOBAL_STR_CONSTS);
1019
1019
10201020 llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
1021 *exceptionCaughtFlag),
1021 *exceptionCaughtFlag),
10221022 &terminatorBlock,
10231023 2);
10241024 theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
10251025 theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
1026
1026
10271027 return(ret);
10281028 }
10291029
10301030
10311031 /// Generates catch block semantics which print a string to indicate type of
1032 /// catch executed, sets an exception caught flag, and executes passed in
1032 /// catch executed, sets an exception caught flag, and executes passed in
10331033 /// end block (terminator block).
10341034 /// @param context llvm context
10351035 /// @param module code for module instance
10401040 /// @param terminatorBlock terminator "end" block
10411041 /// @param exceptionCaughtFlag exception caught/thrown status
10421042 /// @returns newly created block
1043 static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
1044 llvm::Module &module,
1045 llvm::IRBuilder<> &builder,
1043 static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
1044 llvm::Module &module,
1045 llvm::IRBuilder<> &builder,
10461046 llvm::Function &toAddTo,
10471047 std::string &blockName,
10481048 std::string &functionId,
10491049 llvm::BasicBlock &terminatorBlock,
10501050 llvm::Value &exceptionCaughtFlag) {
1051
1051
10521052 llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
10531053 blockName,
10541054 &toAddTo);
1055
1055
10561056 builder.SetInsertPoint(ret);
1057
1057
10581058 std::ostringstream bufferToPrint;
10591059 bufferToPrint << "Gen: Executing catch block "
10601060 << blockName
10611061 << " in "
10621062 << functionId
10631063 << std::endl;
1064 generateStringPrint(context,
1065 module,
1066 builder,
1064 generateStringPrint(context,
1065 module,
1066 builder,
10671067 bufferToPrint.str(),
10681068 USE_GLOBAL_STR_CONSTS);
10691069 builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag);
10701070 builder.CreateBr(&terminatorBlock);
1071
1071
10721072 return(ret);
10731073 }
10741074
10751075
1076 /// Generates a function which invokes a function (toInvoke) and, whose
1077 /// unwind block will "catch" the type info types correspondingly held in the
1078 /// exceptionTypesToCatch argument. If the toInvoke function throws an
1079 /// exception which does not match any type info types contained in
1080 /// exceptionTypesToCatch, the generated code will call _Unwind_Resume
1081 /// with the raised exception. On the other hand the generated code will
1076 /// Generates a function which invokes a function (toInvoke) and, whose
1077 /// unwind block will "catch" the type info types correspondingly held in the
1078 /// exceptionTypesToCatch argument. If the toInvoke function throws an
1079 /// exception which does not match any type info types contained in
1080 /// exceptionTypesToCatch, the generated code will call _Unwind_Resume
1081 /// with the raised exception. On the other hand the generated code will
10821082 /// normally exit if the toInvoke function does not throw an exception.
1083 /// The generated "finally" block is always run regardless of the cause of
1083 /// The generated "finally" block is always run regardless of the cause of
10841084 /// the generated function exit.
10851085 /// The generated function is returned after being verified.
10861086 /// @param module code for module instance
10871087 /// @param builder builder instance
1088 /// @param fpm a function pass manager holding optional IR to IR
1088 /// @param fpm a function pass manager holding optional IR to IR
10891089 /// transformations
10901090 /// @param toInvoke inner function to invoke
10911091 /// @param ourId id used to printing purposes
10931093 /// @param exceptionTypesToCatch array of type info types to "catch"
10941094 /// @returns generated function
10951095 static
1096 llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
1097 llvm::IRBuilder<> &builder,
1096 llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
1097 llvm::IRBuilder<> &builder,
10981098 llvm::FunctionPassManager &fpm,
10991099 llvm::Function &toInvoke,
11001100 std::string ourId,
11011101 unsigned numExceptionsToCatch,
11021102 unsigned exceptionTypesToCatch[]) {
1103
1103
11041104 llvm::LLVMContext &context = module.getContext();
11051105 llvm::Function *toPrint32Int = module.getFunction("print32Int");
1106
1106
11071107 ArgTypes argTypes;
11081108 argTypes.push_back(builder.getInt32Ty());
1109
1109
11101110 ArgNames argNames;
11111111 argNames.push_back("exceptTypeToThrow");
1112
1113 llvm::Function *ret = createFunction(module,
1112
1113 llvm::Function *ret = createFunction(module,
11141114 builder.getVoidTy(),
1115 argTypes,
1116 argNames,
1115 argTypes,
1116 argNames,
11171117 ourId,
1118 llvm::Function::ExternalLinkage,
1119 false,
1118 llvm::Function::ExternalLinkage,
1119 false,
11201120 false);
1121
1121
11221122 // Block which calls invoke
11231123 llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
1124 "entry",
1124 "entry",
11251125 ret);
11261126 // Normal block for invoke
1127 llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context,
1128 "normal",
1127 llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context,
1128 "normal",
11291129 ret);
11301130 // Unwind block for invoke
1131 llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
1132 "exception",
1131 llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
1132 "exception",
11331133 ret);
1134
1134
11351135 // Block which routes exception to correct catch handler block
1136 llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
1137 "exceptionRoute",
1136 llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
1137 "exceptionRoute",
11381138 ret);
1139
1139
11401140 // Foreign exception handler
1141 llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
1142 "externalException",
1141 llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
1142 "externalException",
11431143 ret);
1144
1144
11451145 // Block which calls _Unwind_Resume
1146 llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
1147 "unwindResume",
1146 llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
1147 "unwindResume",
11481148 ret);
1149
1149
11501150 // Clean up block which delete exception if needed
11511151 llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret);
1152
1152
11531153 std::string nextName;
11541154 std::vector catchBlocks(numExceptionsToCatch);
11551155 llvm::Value *exceptionCaughtFlag = NULL;
11561156 llvm::Value *exceptionStorage = NULL;
11571157 llvm::Value *caughtResultStorage = NULL;
1158
1159 // Finally block which will branch to unwindResumeBlock if
1158
1159 // Finally block which will branch to unwindResumeBlock if
11601160 // exception is not caught. Initializes/allocates stack locations.
1161 llvm::BasicBlock *finallyBlock = createFinallyBlock(context,
1162 module,
1163 builder,
1164 *ret,
1165 nextName = "finally",
1161 llvm::BasicBlock *finallyBlock = createFinallyBlock(context,
1162 module,
1163 builder,
1164 *ret,
1165 nextName = "finally",
11661166 ourId,
11671167 *endBlock,
11681168 *unwindResumeBlock,
11701170 &exceptionStorage,
11711171 &caughtResultStorage
11721172 );
1173
1173
11741174 for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
11751175 nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
1176
1176
11771177 // One catch block per type info to be caught
1178 catchBlocks[i] = createCatchBlock(context,
1179 module,
1180 builder,
1178 catchBlocks[i] = createCatchBlock(context,
1179 module,
1180 builder,
11811181 *ret,
1182 nextName,
1182 nextName,
11831183 ourId,
11841184 *finallyBlock,
11851185 *exceptionCaughtFlag);
11861186 }
1187
1187
11881188 // Entry Block
1189
1189
11901190 builder.SetInsertPoint(entryBlock);
1191
1191
11921192 std::vector args;
11931193 args.push_back(namedValues["exceptTypeToThrow"]);
1194 builder.CreateInvoke(&toInvoke,
1195 normalBlock,
1196 exceptionBlock,
1194 builder.CreateInvoke(&toInvoke,
1195 normalBlock,
1196 exceptionBlock,
11971197 args);
1198
1198
11991199 // End Block
1200
1200
12011201 builder.SetInsertPoint(endBlock);
1202
1203 generateStringPrint(context,
1202
1203 generateStringPrint(context,
12041204 module,
1205 builder,
1205 builder,
12061206 "Gen: In end block: exiting in " + ourId + ".\n",
12071207 USE_GLOBAL_STR_CONSTS);
12081208 llvm::Function *deleteOurException = module.getFunction("deleteOurException");
1209
1209
12101210 // Note: function handles NULL exceptions
1211 builder.CreateCall(deleteOurException,
1211 builder.CreateCall(deleteOurException,
12121212 builder.CreateLoad(exceptionStorage));
12131213 builder.CreateRetVoid();
1214
1214
12151215 // Normal Block
1216
1216
12171217 builder.SetInsertPoint(normalBlock);
1218
1219 generateStringPrint(context,
1218
1219 generateStringPrint(context,
12201220 module,
1221 builder,
1221 builder,
12221222 "Gen: No exception in " + ourId + "!\n",
12231223 USE_GLOBAL_STR_CONSTS);
1224
1224
12251225 // Finally block is always called
12261226 builder.CreateBr(finallyBlock);
1227
1227
12281228 // Unwind Resume Block
1229
1229
12301230 builder.SetInsertPoint(unwindResumeBlock);
1231
1231
12321232 builder.CreateResume(builder.CreateLoad(caughtResultStorage));
1233
1233
12341234 // Exception Block
1235
1235
12361236 builder.SetInsertPoint(exceptionBlock);
1237
1237
12381238 llvm::Function *personality = module.getFunction("ourPersonality");
1239
1240 llvm::LandingPadInst *caughtResult =
1239
1240 llvm::LandingPadInst *caughtResult =
12411241 builder.CreateLandingPad(ourCaughtResultType,
12421242 personality,
12431243 numExceptionsToCatch,
12541254 llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);
12551255 llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1);
12561256
1257 // FIXME: Redundant storage which, beyond utilizing value of
1258 // caughtResultStore for unwindException storage, may be alleviated
1257 // FIXME: Redundant storage which, beyond utilizing value of
1258 // caughtResultStore for unwindException storage, may be alleviated
12591259 // altogether with a block rearrangement
12601260 builder.CreateStore(caughtResult, caughtResultStorage);
12611261 builder.CreateStore(unwindException, exceptionStorage);
12621262 builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
1263
1264 // Retrieve exception_class member from thrown exception
1263
1264 // Retrieve exception_class member from thrown exception
12651265 // (_Unwind_Exception instance). This member tells us whether or not
12661266 // the exception is foreign.
1267 llvm::Value *unwindExceptionClass =
1267 llvm::Value *unwindExceptionClass =
12681268 builder.CreateLoad(builder.CreateStructGEP(
1269 builder.CreatePointerCast(unwindException,
1270 ourUnwindExceptionType->getPointerTo()),
1269 builder.CreatePointerCast(unwindException,
1270 ourUnwindExceptionType->getPointerTo()),
12711271 0));
1272
1272
12731273 // Branch to the externalExceptionBlock if the exception is foreign or
12741274 // to a catch router if not. Either way the finally block will be run.
12751275 builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass,
1276 llvm::ConstantInt::get(builder.getInt64Ty(),
1276 llvm::ConstantInt::get(builder.getInt64Ty(),
12771277 ourBaseExceptionClass)),
12781278 exceptionRouteBlock,
12791279 externalExceptionBlock);
1280
1280
12811281 // External Exception Block
1282
1282
12831283 builder.SetInsertPoint(externalExceptionBlock);
1284
1285 generateStringPrint(context,
1284
1285 generateStringPrint(context,
12861286 module,
1287 builder,
1287 builder,
12881288 "Gen: Foreign exception received.\n",
12891289 USE_GLOBAL_STR_CONSTS);
1290
1290
12911291 // Branch to the finally block
12921292 builder.CreateBr(finallyBlock);
1293
1293
12941294 // Exception Route Block
1295
1295
12961296 builder.SetInsertPoint(exceptionRouteBlock);
1297
1298 // Casts exception pointer (_Unwind_Exception instance) to parent
1297
1298 // Casts exception pointer (_Unwind_Exception instance) to parent
12991299 // (OurException instance).
13001300 //
13011301 // Note: ourBaseFromUnwindOffset is usually negative
13031303 builder.CreateConstGEP1_64(unwindException,
13041304 ourBaseFromUnwindOffset),
13051305 ourExceptionType->getPointerTo());
1306
1306
13071307 // Retrieve thrown exception type info type
13081308 //
13091309 // Note: Index is not relative to pointer but instead to structure
13101310 // unlike a true getelementptr (GEP) instruction
13111311 typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0);
1312
1313 llvm::Value *typeInfoThrownType =
1312
1313 llvm::Value *typeInfoThrownType =
13141314 builder.CreateStructGEP(typeInfoThrown, 0);
1315
1316 generateIntegerPrint(context,
1315
1316 generateIntegerPrint(context,
13171317 module,
1318 builder,
1319 *toPrint32Int,
1318 builder,
1319 *toPrint32Int,
13201320 *(builder.CreateLoad(typeInfoThrownType)),
1321 "Gen: Exception type <%d> received (stack unwound) "
1322 " in " +
1323 ourId +
1321 "Gen: Exception type <%d> received (stack unwound) "
1322 " in " +
1323 ourId +
13241324 ".\n",
13251325 USE_GLOBAL_STR_CONSTS);
1326
1326
13271327 // Route to matched type info catch block or run cleanup finally block
1328 llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
1329 finallyBlock,
1328 llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
1329 finallyBlock,
13301330 numExceptionsToCatch);
1331
1331
13321332 unsigned nextTypeToCatch;
1333
1333
13341334 for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
13351335 nextTypeToCatch = i - 1;
13361336 switchToCatchBlock->addCase(llvm::ConstantInt::get(
13401340
13411341 llvm::verifyFunction(*ret);
13421342 fpm.run(*ret);
1343
1343
13441344 return(ret);
13451345 }
13461346
13471347
13481348 /// Generates function which throws either an exception matched to a runtime
1349 /// determined type info type (argument to generated function), or if this
1350 /// runtime value matches nativeThrowType, throws a foreign exception by
1349 /// determined type info type (argument to generated function), or if this
1350 /// runtime value matches nativeThrowType, throws a foreign exception by
13511351 /// calling nativeThrowFunct.
13521352 /// @param module code for module instance
13531353 /// @param builder builder instance
1354 /// @param fpm a function pass manager holding optional IR to IR
1354 /// @param fpm a function pass manager holding optional IR to IR
13551355 /// transformations
13561356 /// @param ourId id used to printing purposes
13571357 /// @param nativeThrowType a runtime argument of this value results in
13601360 /// if the above nativeThrowType matches generated function's arg.
13611361 /// @returns generated function
13621362 static
1363 llvm::Function *createThrowExceptionFunction(llvm::Module &module,
1364 llvm::IRBuilder<> &builder,
1363 llvm::Function *createThrowExceptionFunction(llvm::Module &module,
1364 llvm::IRBuilder<> &builder,
13651365 llvm::FunctionPassManager &fpm,
13661366 std::string ourId,
13671367 int32_t nativeThrowType,
13721372 unwindArgTypes.push_back(builder.getInt32Ty());
13731373 ArgNames unwindArgNames;
13741374 unwindArgNames.push_back("exceptTypeToThrow");
1375
1375
13761376 llvm::Function *ret = createFunction(module,
13771377 builder.getVoidTy(),
13781378 unwindArgTypes,
13811381 llvm::Function::ExternalLinkage,
13821382 false,
13831383 false);
1384
1384
13851385 // Throws either one of our exception or a native C++ exception depending
13861386 // on a runtime argument value containing a type info type.
13871387 llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
1388 "entry",
1388 "entry",
13891389 ret);
13901390 // Throws a foreign exception
13911391 llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context,
1392 "nativeThrow",
1392 "nativeThrow",
13931393 ret);
13941394 // Throws one of our Exceptions
13951395 llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context,
1396 "generatedThrow",
1396 "generatedThrow",
13971397 ret);
13981398 // Retrieved runtime type info type to throw
13991399 llvm::Value *exceptionType = namedValues["exceptTypeToThrow"];
1400
1400
14011401 // nativeThrowBlock block
1402
1402
14031403 builder.SetInsertPoint(nativeThrowBlock);
1404
1404
14051405 // Throws foreign exception
14061406 builder.CreateCall(&nativeThrowFunct, exceptionType);
14071407 builder.CreateUnreachable();
1408
1408
14091409 // entry block
1410
1410
14111411 builder.SetInsertPoint(entryBlock);
1412
1412
14131413 llvm::Function *toPrint32Int = module.getFunction("print32Int");
1414 generateIntegerPrint(context,
1414 generateIntegerPrint(context,
14151415 module,
1416 builder,
1417 *toPrint32Int,
1418 *exceptionType,
1419 "\nGen: About to throw exception type <%d> in " +
1420 ourId +
1416 builder,
1417 *toPrint32Int,
1418 *exceptionType,
1419 "\nGen: About to throw exception type <%d> in " +
1420 ourId +
14211421 ".\n",
14221422 USE_GLOBAL_STR_CONSTS);
1423
1423
14241424 // Switches on runtime type info type value to determine whether or not
1425 // a foreign exception is thrown. Defaults to throwing one of our
1425 // a foreign exception is thrown. Defaults to throwing one of our
14261426 // generated exceptions.
14271427 llvm::SwitchInst *theSwitch = builder.CreateSwitch(exceptionType,
14281428 generatedThrowBlock,
14291429 1);
1430
1431 theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context),
1430
1431 theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context),
14321432 nativeThrowType),
14331433 nativeThrowBlock);
1434
1434
14351435 // generatedThrow block
1436
1436
14371437 builder.SetInsertPoint(generatedThrowBlock);
1438
1438
14391439 llvm::Function *createOurException = module.getFunction("createOurException");
14401440 llvm::Function *raiseOurException = module.getFunction(
14411441 "_Unwind_RaiseException");
1442
1442
14431443 // Creates exception to throw with runtime type info type.
1444 llvm::Value *exception = builder.CreateCall(createOurException,
1444 llvm::Value *exception = builder.CreateCall(createOurException,
14451445 namedValues["exceptTypeToThrow"]);
1446
1446
14471447 // Throw generated Exception
14481448 builder.CreateCall(raiseOurException, exception);
14491449 builder.CreateUnreachable();
1450
1450
14511451 llvm::verifyFunction(*ret);
14521452 fpm.run(*ret);
1453
1453
14541454 return(ret);
14551455 }
14561456
14571457 static void createStandardUtilityFunctions(unsigned numTypeInfos,
1458 llvm::Module &module,
1458 llvm::Module &module,
14591459 llvm::IRBuilder<> &builder);
14601460
1461 /// Creates test code by generating and organizing these functions into the
1461 /// Creates test code by generating and organizing these functions into the
14621462 /// test case. The test case consists of an outer function setup to invoke
1463 /// an inner function within an environment having multiple catch and single
1463 /// an inner function within an environment having multiple catch and single
14641464 /// finally blocks. This inner function is also setup to invoke a throw
1465 /// function within an evironment similar in nature to the outer function's
1465 /// function within an evironment similar in nature to the outer function's
14661466 /// catch and finally blocks. Each of these two functions catch mutually
14671467 /// exclusive subsets (even or odd) of the type info types configured
14681468 /// for this this. All generated functions have a runtime argument which
14731473 /// a supplied a function which in turn will throw a foreign exception.
14741474 /// @param module code for module instance
14751475 /// @param builder builder instance
1476 /// @param fpm a function pass manager holding optional IR to IR
1476 /// @param fpm a function pass manager holding optional IR to IR
14771477 /// transformations
14781478 /// @param nativeThrowFunctName name of external function which will throw
14791479 /// a foreign exception
14801480 /// @returns outermost generated test function.
1481 llvm::Function *createUnwindExceptionTest(llvm::Module &module,
1482 llvm::IRBuilder<> &builder,
1481 llvm::Function *createUnwindExceptionTest(llvm::Module &module,
1482 llvm::IRBuilder<> &builder,
14831483 llvm::FunctionPassManager &fpm,
14841484 std::string nativeThrowFunctName) {
14851485 // Number of type infos to generate
14861486 unsigned numTypeInfos = 6;
1487
1487
14881488 // Initialze intrisics and external functions to use along with exception
14891489 // and type info globals.
14901490 createStandardUtilityFunctions(numTypeInfos,
14911491 module,
14921492 builder);
14931493 llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName);
1494
1495 // Create exception throw function using the value ~0 to cause
1494
1495 // Create exception throw function using the value ~0 to cause
14961496 // foreign exceptions to be thrown.
14971497 llvm::Function *throwFunct = createThrowExceptionFunction(module,
14981498 builder,
15021502 *nativeThrowFunct);
15031503 // Inner function will catch even type infos
15041504 unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
1505 size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
1505 size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
15061506 sizeof(unsigned);
1507
1507
15081508 // Generate inner function.
15091509 llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module,
15101510 builder,
15131513 "innerCatchFunct",
15141514 numExceptionTypesToCatch,
15151515 innerExceptionTypesToCatch);
1516
1516
15171517 // Outer function will catch odd type infos
15181518 unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
1519 numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) /
1519 numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) /
15201520 sizeof(unsigned);
1521
1521
15221522 // Generate outer function
15231523 llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module,
15241524 builder,
15271527 "outerCatchFunct",
15281528 numExceptionTypesToCatch,
15291529 outerExceptionTypesToCatch);
1530
1530
15311531 // Return outer function to run
15321532 return(outerCatchFunct);
15331533 }
15381538 public:
15391539 OurCppRunException(const std::string reason) :
15401540 std::runtime_error(reason) {}
1541
1541
15421542 OurCppRunException (const OurCppRunException &toCopy) :
15431543 std::runtime_error(toCopy) {}
1544
1544
15451545 OurCppRunException &operator = (const OurCppRunException &toCopy) {
15461546 return(reinterpret_cast(
15471547 std::runtime_error::operator=(toCopy)));
15481548 }
1549
1549
15501550 ~OurCppRunException (void) throw () {}
15511551 };
15521552
15611561
15621562 typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
15631563
1564 /// This is a test harness which runs test by executing generated
1564 /// This is a test harness which runs test by executing generated
15651565 /// function with a type info type to throw. Harness wraps the execution
15661566 /// of generated function in a C++ try catch clause.
15671567 /// @param engine execution engine to use for executing generated function.
15711571 /// @param typeToThrow type info type of generated exception to throw, or
15721572 /// indicator to cause foreign exception to be thrown.
15731573 static
1574 void runExceptionThrow(llvm::ExecutionEngine *engine,
1575 llvm::Function *function,
1574 void runExceptionThrow(llvm::ExecutionEngine *engine,
1575 llvm::Function *function,
15761576 int32_t typeToThrow) {
1577
1577
15781578 // Find test's function pointer
1579 OurExceptionThrowFunctType functPtr =
1579 OurExceptionThrowFunctType functPtr =
15801580 reinterpret_cast(
15811581 reinterpret_cast(engine->getPointerToFunction(function)));
1582
1582
15831583 try {
15841584 // Run test
15851585 (*functPtr)(typeToThrow);
15881588 // Catch foreign C++ exception
15891589 fprintf(stderr,
15901590 "\nrunExceptionThrow(...):In C++ catch OurCppRunException "
1591 "with reason: %s.\n",
1591 "with reason: %s.\n",
15921592 exc.what());
15931593 }
15941594 catch (...) {
1595 // Catch all exceptions including our generated ones. This latter
1595 // Catch all exceptions including our generated ones. This latter
15961596 // functionality works according to the example in rules 1.6.4 of
1597 // http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22),
1598 // given that these will be exceptions foreign to C++
1599 // (the _Unwind_Exception::exception_class should be different from
1597 // http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22),
1598 // given that these will be exceptions foreign to C++
1599 // (the _Unwind_Exception::exception_class should be different from
16001600 // the one used by C++).
16011601 fprintf(stderr,
16021602 "\nrunExceptionThrow(...):In C++ catch all.\n");
16091609
16101610 typedef llvm::ArrayRef TypeArray;
16111611
1612 /// This initialization routine creates type info globals and
1612 /// This initialization routine creates type info globals and
16131613 /// adds external function declarations to module.
16141614 /// @param numTypeInfos number of linear type info associated type info types
16151615 /// to create as GlobalVariable instances, starting with the value 1.
16161616 /// @param module code for module instance
16171617 /// @param builder builder instance
16181618 static void createStandardUtilityFunctions(unsigned numTypeInfos,
1619 llvm::Module &module,
1619 llvm::Module &module,
16201620 llvm::IRBuilder<> &builder) {
1621
1621
16221622 llvm::LLVMContext &context = module.getContext();
1623
1623
16241624 // Exception initializations
1625
1625
16261626 // Setup exception catch state
1627 ourExceptionNotThrownState =
1627 ourExceptionNotThrownState =
16281628 llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
1629 ourExceptionThrownState =
1629 ourExceptionThrownState =
16301630 llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
1631 ourExceptionCaughtState =
1631 ourExceptionCaughtState =
16321632 llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
1633
1634
1635
1633
1634
1635
16361636 // Create our type info type
1637 ourTypeInfoType = llvm::StructType::get(context,
1637 ourTypeInfoType = llvm::StructType::get(context,
16381638 TypeArray(builder.getInt32Ty()));
16391639
16401640 llvm::Type *caughtResultFieldTypes[] = {
16471647 TypeArray(caughtResultFieldTypes));
16481648
16491649 // Create OurException type
1650 ourExceptionType = llvm::StructType::get(context,
1650 ourExceptionType = llvm::StructType::get(context,
16511651 TypeArray(ourTypeInfoType));
1652
1652
16531653 // Create portion of _Unwind_Exception type
16541654 //
16551655 // Note: Declaring only a portion of the _Unwind_Exception struct.
16561656 // Does this cause problems?
16571657 ourUnwindExceptionType =
1658 llvm::StructType::get(context,
1658 llvm::StructType::get(context,
16591659 TypeArray(builder.getInt64Ty()));
16601660
16611661 struct OurBaseException_t dummyException;
1662
1662
16631663 // Calculate offset of OurException::unwindException member.
1664 ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
1664 ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
16651665 ((uintptr_t) &(dummyException.unwindException));
1666
1666
16671667 #ifdef DEBUG
16681668 fprintf(stderr,
16691669 "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset "
16701670 "= %lld, sizeof(struct OurBaseException_t) - "
16711671 "sizeof(struct _Unwind_Exception) = %lu.\n",
16721672 ourBaseFromUnwindOffset,
1673 sizeof(struct OurBaseException_t) -
1673 sizeof(struct OurBaseException_t) -
16741674 sizeof(struct _Unwind_Exception));
16751675 #endif
1676
1676
16771677 size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char);
1678
1678
16791679 // Create our _Unwind_Exception::exception_class value
16801680 ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars);
1681
1681
16821682 // Type infos
1683
1683
16841684 std::string baseStr = "typeInfo", typeInfoName;
16851685 std::ostringstream typeInfoNameBuilder;
16861686 std::vector structVals;
1687
1687
16881688 llvm::Constant *nextStruct;
16891689 llvm::GlobalVariable *nextGlobal = NULL;
1690
1690
16911691 // Generate each type info
16921692 //
16931693 // Note: First type info is not used.
16951695 structVals.clear();
16961696 structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i));
16971697 nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals);
1698
1698
16991699 typeInfoNameBuilder.str("");
17001700 typeInfoNameBuilder << baseStr << i;
17011701 typeInfoName = typeInfoNameBuilder.str();
1702
1702
17031703 // Note: Does not seem to work without allocation
1704 nextGlobal =
1705 new llvm::GlobalVariable(module,
1706 ourTypeInfoType,
1707 true,
1708 llvm::GlobalValue::ExternalLinkage,
1709 nextStruct,
1704 nextGlobal =
1705 new llvm::GlobalVariable(module,
1706 ourTypeInfoType,
1707 true,
1708 llvm::GlobalValue::ExternalLinkage,
1709 nextStruct,
17101710 typeInfoName);
1711
1711
17121712 ourTypeInfoNames.push_back(typeInfoName);
17131713 ourTypeInfoNamesIndex[i] = typeInfoName;
17141714 }
1715
1715
17161716 ArgNames argNames;
17171717 ArgTypes argTypes;
17181718 llvm::Function *funct = NULL;
1719
1719
17201720 // print32Int
1721
1721
17221722 llvm::Type *retType = builder.getVoidTy();
1723
1723
17241724 argTypes.clear();
17251725 argTypes.push_back(builder.getInt32Ty());
17261726 argTypes.push_back(builder.getInt8PtrTy());
1727
1727
17281728 argNames.clear();
1729
1730 createFunction(module,
1731 retType,
1732 argTypes,
1733 argNames,
1734 "print32Int",
1735 llvm::Function::ExternalLinkage,
1736 true,
1729
1730 createFunction(module,
1731 retType,
1732 argTypes,
1733 argNames,
1734 "print32Int",
1735 llvm::Function::ExternalLinkage,
1736 true,
17371737 false);
1738
1738
17391739 // print64Int
1740
1740
17411741 retType = builder.getVoidTy();
1742
1742
17431743 argTypes.clear();
17441744 argTypes.push_back(builder.getInt64Ty());
17451745 argTypes.push_back(builder.getInt8PtrTy());
1746
1746
17471747 argNames.clear();
1748
1749 createFunction(module,
1750 retType,
1751 argTypes,
1752 argNames,
1753 "print64Int",
1754 llvm::Function::ExternalLinkage,
1755 true,
1748
1749 createFunction(module,
1750 retType,
1751 argTypes,
1752 argNames,
1753 "print64Int",
1754 llvm::Function::ExternalLinkage,
1755 true,
17561756 false);
1757
1757
17581758 // printStr
1759
1759
17601760 retType = builder.getVoidTy();
1761
1761
17621762 argTypes.clear();
17631763 argTypes.push_back(builder.getInt8PtrTy());
1764
1764
17651765 argNames.clear();
1766
1767 createFunction(module,
1768 retType,
1769 argTypes,
1770 argNames,
1771 "printStr",
1772 llvm::Function::ExternalLinkage,
1773 true,
1766
1767 createFunction(module,
1768 retType,
1769 argTypes,
1770 argNames,
1771 "printStr",
1772 llvm::Function::ExternalLinkage,
1773 true,
17741774 false);
1775
1775
17761776 // throwCppException
1777
1777
17781778 retType = builder.getVoidTy();
1779
1779
17801780 argTypes.clear();
17811781 argTypes.push_back(builder.getInt32Ty());
1782
1782
17831783 argNames.clear();
1784
1785 createFunction(module,
1786 retType,
1787 argTypes,
1788 argNames,
1789 "throwCppException",
1790 llvm::Function::ExternalLinkage,
1791 true,
1784
1785 createFunction(module,
1786 retType,
1787 argTypes,
1788 argNames,
1789 "throwCppException",
1790 llvm::Function::ExternalLinkage,
1791 true,
17921792 false);
1793
1793
17941794 // deleteOurException
1795
1795
17961796 retType = builder.getVoidTy();
1797
1797
17981798 argTypes.clear();
17991799 argTypes.push_back(builder.getInt8PtrTy());
1800
1800
18011801 argNames.clear();
1802
1803 createFunction(module,
1804 retType,
1805 argTypes,
1806 argNames,
1807 "deleteOurException",
1808 llvm::Function::ExternalLinkage,
1809 true,
1802
1803 createFunction(module,
1804 retType,
1805 argTypes,
1806 argNames,
1807 "deleteOurException",
1808 llvm::Function::ExternalLinkage,
1809 true,
18101810 false);
1811
1811
18121812 // createOurException
1813
1813
18141814 retType = builder.getInt8PtrTy();
1815
1815
18161816 argTypes.clear();
18171817 argTypes.push_back(builder.getInt32Ty());
1818
1818
18191819 argNames.clear();
1820
1821 createFunction(module,
1822 retType,
1823 argTypes,
1824 argNames,
1825 "createOurException",
1826 llvm::Function::ExternalLinkage,
1827 true,
1820
1821 createFunction(module,
1822 retType,
1823 argTypes,
1824 argNames,
1825 "createOurException",
1826 llvm::Function::ExternalLinkage,
1827 true,
18281828 false);
1829
1829
18301830 // _Unwind_RaiseException
1831
1831
18321832 retType = builder.getInt32Ty();
1833
1833
18341834 argTypes.clear();
18351835 argTypes.push_back(builder.getInt8PtrTy());
1836
1836
18371837 argNames.clear();
1838
1839 funct = createFunction(module,
1840 retType,
1841 argTypes,
1842 argNames,
1843 "_Unwind_RaiseException",
1844 llvm::Function::ExternalLinkage,
1845 true,
1838
1839 funct = createFunction(module,
1840 retType,
1841 argTypes,
1842 argNames,
1843 "_Unwind_RaiseException",
1844 llvm::Function::ExternalLinkage,
1845 true,
18461846 false);
1847
1847
18481848 funct->addFnAttr(llvm::Attribute::NoReturn);
1849
1849
18501850 // _Unwind_Resume
1851
1851
18521852 retType = builder.getInt32Ty();
1853
1853
18541854 argTypes.clear();
18551855 argTypes.push_back(builder.getInt8PtrTy());
1856
1856
18571857 argNames.clear();
1858
1859 funct = createFunction(module,
1860 retType,
1861 argTypes,
1862 argNames,
1863 "_Unwind_Resume",
1864 llvm::Function::ExternalLinkage,
1865 true,
1858
1859 funct = createFunction(module,
1860 retType,
1861 argTypes,
1862 argNames,
1863 "_Unwind_Resume",
1864 llvm::Function::ExternalLinkage,
1865 true,
18661866 false);
1867
1867
18681868 funct->addFnAttr(llvm::Attribute::NoReturn);
1869
1869
18701870 // ourPersonality
1871
1871
18721872 retType = builder.getInt32Ty();
1873
1873
18741874 argTypes.clear();
18751875 argTypes.push_back(builder.getInt32Ty());
18761876 argTypes.push_back(builder.getInt32Ty());
18771877 argTypes.push_back(builder.getInt64Ty());
18781878 argTypes.push_back(builder.getInt8PtrTy());
18791879 argTypes.push_back(builder.getInt8PtrTy());
1880
1880
18811881 argNames.clear();
1882
1883 createFunction(module,
1884 retType,
1885 argTypes,
1886 argNames,
1887 "ourPersonality",
1888 llvm::Function::ExternalLinkage,
1889 true,
1882
1883 createFunction(module,
1884 retType,
1885 argTypes,
1886 argNames,
1887 "ourPersonality",
1888 llvm::Function::ExternalLinkage,
1889 true,
18901890 false);
1891
1891
18921892 // llvm.eh.typeid.for intrinsic
1893
1893
18941894 getDeclaration(&module, llvm::Intrinsic::eh_typeid_for);
18951895 }
18961896
19001900 //===----------------------------------------------------------------------===//
19011901
19021902 /// Demo main routine which takes the type info types to throw. A test will
1903 /// be run for each given type info type. While type info types with the value
1903 /// be run for each given type info type. While type info types with the value
19041904 /// of -1 will trigger a foreign C++ exception to be thrown; type info types
19051905 /// <= 6 and >= 1 will be caught by test functions; and type info types > 6
19061906 /// will result in exceptions which pass through to the test harness. All other
19191919 " for a full test.\n\n");
19201920 return(0);
19211921 }
1922
1922
19231923 // If not set, exception handling will not be turned on
19241924 llvm::TargetOptions Opts;
19251925 Opts.JITExceptionHandling = true;
1926
1926
19271927 llvm::InitializeNativeTarget();
19281928 llvm::LLVMContext &context = llvm::getGlobalContext();
19291929 llvm::IRBuilder<> theBuilder(context);
1930
1930
19311931 // Make the module, which holds all the code.
19321932 llvm::Module *module = new llvm::Module("my cool jit", context);
1933
1933
19341934 // Build engine with JIT
19351935 llvm::EngineBuilder factory(module);
19361936 factory.setEngineKind(llvm::EngineKind::JIT);
19371937 factory.setAllocateGVsWithCode(false);
19381938 factory.setTargetOptions(Opts);
19391939 llvm::ExecutionEngine *executionEngine = factory.create();
1940
1940
19411941 {
19421942 llvm::FunctionPassManager fpm(module);
1943
1944 // Set up the optimizer pipeline.
1943
1944 // Set up the optimizer pipeline.
19451945 // Start with registering info about how the
19461946 // target lays out data structures.
19471947 fpm.add(new llvm::DataLayout(*executionEngine->getDataLayout()));
1948
1948
19491949 // Optimizations turned on
19501950 #ifdef ADD_OPT_PASSES
1951
1951
19521952 // Basic AliasAnslysis support for GVN.
19531953 fpm.add(llvm::createBasicAliasAnalysisPass());
1954
1954
19551955 // Promote allocas to registers.
19561956 fpm.add(llvm::createPromoteMemoryToRegisterPass());
1957
1957
19581958 // Do simple "peephole" optimizations and bit-twiddling optzns.
19591959 fpm.add(llvm::createInstructionCombiningPass());
1960
1960
19611961 // Reassociate expressions.
19621962 fpm.add(llvm::createReassociatePass());
1963
1963
19641964 // Eliminate Common SubExpressions.
19651965 fpm.add(llvm::createGVNPass());
1966
1967 // Simplify the control flow graph (deleting unreachable
1966
1967 // Simplify the control flow graph (deleting unreachable
19681968 // blocks, etc).
19691969 fpm.add(llvm::createCFGSimplificationPass());
19701970 #endif // ADD_OPT_PASSES
1971
1971
19721972 fpm.doInitialization();
1973
1973
19741974 // Generate test code using function throwCppException(...) as
19751975 // the function which throws foreign exceptions.
1976 llvm::Function *toRun =
1977 createUnwindExceptionTest(*module,
1978 theBuilder,
1976 llvm::Function *toRun =
1977 createUnwindExceptionTest(*module,
1978 theBuilder,
19791979 fpm,
19801980 "throwCppException");
1981
1981
19821982 fprintf(stderr, "\nBegin module dump:\n\n");
1983
1983
19841984 module->dump();
1985
1985
19861986 fprintf(stderr, "\nEnd module dump:\n");
1987
1987
19881988 fprintf(stderr, "\n\nBegin Test:\n");
1989
1989
19901990 for (int i = 1; i < argc; ++i) {
19911991 // Run test for each argument whose value is the exception
19921992 // type to throw.
1993 runExceptionThrow(executionEngine,
1994 toRun,
1993 runExceptionThrow(executionEngine,
1994 toRun,
19951995 (unsigned) strtoul(argv[i], NULL, 10));
19961996 }
1997
1997
19981998 fprintf(stderr, "\nEnd Test:\n\n");
1999 }
2000
1999 }
2000
20012001 delete executionEngine;
2002
2002
20032003 return 0;
20042004 }
2005