setjmp was called. */
gcc_assert (get_stack_depth () >= setjmp_stack_depth);
while (get_stack_depth () > setjmp_stack_depth)
- pop_frame (NULL, NULL, ctxt);
+ pop_frame (NULL, NULL, ctxt, false);
gcc_assert (get_stack_depth () == setjmp_stack_depth);
If OUT_RESULT is non-null, copy any return value from the frame
into *OUT_RESULT.
+ If EVAL_RETURN_SVALUE is false, then don't evaluate the return value.
+ This is for use when unwinding frames e.g. due to longjmp, to suppress
+ erroneously reporting uninitialized return values.
+
Purge the frame region and all its descendent regions.
Convert any pointers that point into such regions into
POISON_KIND_POPPED_STACK svalues. */
void
region_model::pop_frame (tree result_lvalue,
const svalue **out_result,
- region_model_context *ctxt)
+ region_model_context *ctxt,
+ bool eval_return_svalue)
{
gcc_assert (m_current_frame);
tree fndecl = m_current_frame->get_function ()->decl;
tree result = DECL_RESULT (fndecl);
const svalue *retval = NULL;
- if (result && TREE_TYPE (result) != void_type_node)
+ if (result
+ && TREE_TYPE (result) != void_type_node
+ && eval_return_svalue)
{
retval = get_rvalue (result, ctxt);
if (out_result)
if (result_lvalue && retval)
{
+ gcc_assert (eval_return_svalue);
+
/* Compute result_dst_reg using RESULT_LVALUE *after* popping
the frame, but before poisoning pointers into the old frame. */
const region *result_dst_reg = get_lvalue (result_lvalue, ctxt);
function * get_current_function () const;
void pop_frame (tree result_lvalue,
const svalue **out_result,
- region_model_context *ctxt);
+ region_model_context *ctxt,
+ bool eval_return_svalue = true);
int get_stack_depth () const;
const frame_region *get_frame_at_index (int index) const;
--- /dev/null
+/* Reduced from an ICE seen in qemu's target/i386/tcg/translate.c */
+
+typedef long int __jmp_buf[8];
+struct __jmp_buf_tag {
+ __jmp_buf __jmpbuf;
+};
+typedef struct __jmp_buf_tag sigjmp_buf[1];
+
+extern int __sigsetjmp(sigjmp_buf env, int savesigs);
+extern void siglongjmp(sigjmp_buf env, int val);
+
+typedef struct DisasContextBase {
+ int num_insns;
+} DisasContextBase;
+
+typedef struct DisasContext {
+ DisasContextBase base;
+ sigjmp_buf jmpbuf;
+} DisasContext;
+
+extern int translator_ldub(DisasContextBase *base, int);
+
+int advance_pc(DisasContext *s, int num_bytes) {
+ if (s->base.num_insns > 1) {
+ siglongjmp(s->jmpbuf, 2);
+ }
+ return 0;
+}
+
+static inline int x86_ldub_code(DisasContext *s) {
+ return translator_ldub(&s->base, advance_pc(s, 1));
+}
+
+static void disas_insn(DisasContext *s) {
+ int b;
+ __sigsetjmp(s->jmpbuf, 0);
+ b = x86_ldub_code(s);
+}