1 # This file contains code related to translating exception handling.
5 # This generates code that goes before a leave instruction to ensure the
6 # correct stuff is removed from the exception stack and any finally blocks are
8 .sub handler_leave_code
13 .local int try_start, try_length, try_end, i, num_handlers, mark, flags
14 .local int finallys_walked, handler_start, handler_length, handler_end
15 .local string pir_output, tmp
19 num_handlers = elements ehs
23 if i >= num_handlers goto EH_LOOP_END
26 # Get info about handler.
27 flags = eh.get_flags()
28 try_start = eh.get_try_offset()
29 try_length = eh.get_try_length()
30 try_end = try_start + try_length
31 handler_start = eh.get_handler_offset()
32 handler_length = eh.get_handler_length()
33 handler_end = handler_start + handler_length
35 # See if we've got to the block we're leaving for. If so, we know the
36 # mark to pop to and we've found all finally blocks we need to call.
37 if dest < try_start goto EH_LOOP_NEXT
38 if pc < try_start goto EH_LOOP_NEXT
39 if dest > try_end goto EH_LOOP_NEXT
44 # Now check if the current try or handler contains the location we're
45 # leaving from. If it does, then we now find stuff we ain't walked
48 if pc < try_start goto TRY_WALKED_OVER
49 if pc >= try_end goto TRY_WALKED_OVER
52 if pc < handler_start goto CATCH_WALKED_OVER
53 if pc >= handler_end goto CATCH_WALKED_OVER
57 # If this is a finally handler we need to check if it's one that has
58 # not yet been walked over, and if so emit a call to it.
59 if flags != 2 goto NOT_FINALLY
60 if finallys_walked != 0 goto NOT_FINALLY
61 pir_output = concat "$P1000000 = null\nsaved_ehs["
63 pir_output = concat tmp
64 pir_output = concat "] = $P1000000\n"
65 pir_output = concat "bsr FINALLY_"
67 pir_output = concat tmp
68 pir_output = concat "\n"
76 pir_output = concat "popmark "
77 pir_output = concat tmp
78 pir_output = concat "\npushmark "
79 pir_output = concat tmp
80 pir_output = concat "\n"
82 # Return generated code.
87 # This generates the code that terminates a finally block.
92 .local string pir_output, tmp
94 .local int num_handlers, i, found, flags
95 .local int handler_start, handler_length, handler_end
97 # Look for the entry in the handlers table that relates to the current
99 num_handlers = elements ehs
103 if i >= num_handlers goto EH_LOOP_END
105 flags = eh.get_flags()
106 if flags != 2 goto EH_LOOP_NEXT
107 handler_start = eh.get_handler_offset()
108 if pc < handler_start goto EH_LOOP_NEXT
109 handler_length = eh.get_handler_length()
110 handler_end = handler_start + handler_length
111 if pc > handler_end goto EH_LOOP_NEXT
119 # If we didn't find the current finally block, we're shafted.
120 if found >= 0 goto NOT_SHAFTED
122 ex["_message"] = "Failed to find finally handler for an endfinally"
126 # Now just generate the code.
127 pir_output = "$P1000000 = saved_ehs["
129 pir_output = concat tmp
130 pir_output = concat "]\nif null $P1000000 goto FINALLY_RET_"
132 pir_output = concat tmp
133 pir_output = concat "\nthrow $P1000000\nFINALLY_RET_"
134 pir_output = concat tmp
135 pir_output = concat ": ret\n"
137 # Return produced PIR.
142 # This gets info from a class type and class id from an exception handler.
143 .sub class_info_from_ehtype
145 .param int class_type
147 .local pmc ex, classes, pclass
148 .local string pclass_ns, tmp
150 # Find out what type of class we have.
152 if class_type == 2 goto DEF
153 if class_type == 1 goto REF
155 ex["_message"] = "Unknown class type."
158 # A type in this file.
160 dec class_id # Because row 2 = element 0 here, thanks to the global class
161 classes = assembly.get_classes()
162 pclass = classes[class_id]
163 pclass_ns = pclass.get_fullname()
166 # A type in another file.
168 classes = assembly.get_typerefs()
169 pclass = classes[class_id]
170 pclass_ns = pclass.get_namespace()
171 pclass_ns = clone pclass_ns
172 if pclass_ns == "" goto NO_NS
173 pclass_ns = concat "."
176 pclass_ns = concat tmp
178 # Return class and its namespace.
180 .return (pclass, pclass_ns)
187 # vim: expandtab shiftwidth=4 ft=pir: