Patchwork [i386] : Fix PR 53811, ICE: in insn_default_length, at config/i386/i386.md:529 (unrecognizable insn) with -mcmodel=large

login
register
mail settings
Submitter Uros Bizjak
Date July 3, 2012, 10:55 a.m.
Message ID <CAFULd4YgQuRkALKE=DG0pHLDO-mjthBoDNt=e1qTT0Rz9+45Lg@mail.gmail.com>
Download mbox | patch
Permalink /patch/168787/
State New
Headers show

Comments

Uros Bizjak - July 3, 2012, 10:55 a.m.
Hello!

Attached patch fixes PR 53811. gcc failed to check if symbol_ref
operands fits sibcall_insn_operand predicate. In case of
-mcmodel=large, we must emit indirect jump for a sibcall.

2012-07-03  Uros Bizjak  <ubizjak@gmail.com>

	PR target/53811
	* config/i386/i386.c (x86_output_mi_thunk): Check if fnaddr satisfies
	sibcall_insn_operand.  Move it to a temporary register if not.

testsuite/ChangLog:

2012-07-03  Uros Bizjak  <ubizjak@gmail.com>

	PR target/53811
	* g++.dg/other/pr53811.C: New test.

Tested on x86_64-pc-linux-gnu, committed to mainline SVN, similar
patch will be committed to 4.7 branch.

Uros.

Patch

Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 189191)
+++ config/i386/i386.c	(working copy)
@@ -32931,7 +32931,19 @@  x86_output_mi_thunk (FILE *file,
 {
   rtx this_param = x86_this_parameter (function);
   rtx this_reg, tmp, fnaddr;
+  unsigned int tmp_regno;
 
+  if (TARGET_64BIT)
+    tmp_regno = R10_REG;
+  else
+    {
+      unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (function));
+      if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0)
+	tmp_regno = AX_REG;
+      else
+	tmp_regno = CX_REG;
+    }
+
   emit_note (NOTE_INSN_PROLOGUE_END);
 
   /* If VCALL_OFFSET, we'll need THIS in a register.  Might as well
@@ -32957,7 +32969,7 @@  x86_output_mi_thunk (FILE *file,
 	{
 	  if (!x86_64_general_operand (delta_rtx, Pmode))
 	    {
-	      tmp = gen_rtx_REG (Pmode, R10_REG);
+	      tmp = gen_rtx_REG (Pmode, tmp_regno);
 	      emit_move_insn (tmp, delta_rtx);
 	      delta_rtx = tmp;
 	    }
@@ -32970,18 +32982,7 @@  x86_output_mi_thunk (FILE *file,
   if (vcall_offset)
     {
       rtx vcall_addr, vcall_mem, this_mem;
-      unsigned int tmp_regno;
 
-      if (TARGET_64BIT)
-	tmp_regno = R10_REG;
-      else
-	{
-	  unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (function));
-	  if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0)
-	    tmp_regno = AX_REG;
-	  else
-	    tmp_regno = CX_REG;
-	}
       tmp = gen_rtx_REG (Pmode, tmp_regno);
 
       this_mem = gen_rtx_MEM (ptr_mode, this_reg);
@@ -33056,6 +33057,15 @@  x86_output_mi_thunk (FILE *file,
     emit_jump_insn (gen_indirect_jump (fnaddr));
   else
     {
+      if (!sibcall_insn_operand (fnaddr, word_mode))
+	{
+	  tmp = gen_rtx_REG (word_mode, tmp_regno);
+	  if (GET_MODE (fnaddr) != word_mode)
+	    fnaddr = gen_rtx_ZERO_EXTEND (word_mode, fnaddr);
+	  emit_move_insn (tmp, fnaddr);
+	  fnaddr = tmp;
+	}
+
       tmp = gen_rtx_MEM (QImode, fnaddr);
       tmp = gen_rtx_CALL (VOIDmode, tmp, const0_rtx);
       tmp = emit_call_insn (tmp);
Index: testsuite/g++.dg/other/pr53811.C
===================================================================
--- testsuite/g++.dg/other/pr53811.C	(revision 0)
+++ testsuite/g++.dg/other/pr53811.C	(working copy)
@@ -0,0 +1,29 @@ 
+// { dg-do compile }
+// { dg-options "-mcmodel=large" { target { { i?86-*-* x86_64-*-* } && lp64 } } }
+
+struct ICCStringClass
+{
+  virtual void *
+  CreateString (const char *fromText) = 0;
+};
+
+struct AGSCCDynamicObject
+{
+  virtual void
+  Unserialize (int index, const char *serializedData, int dataSize) = 0;
+};
+
+
+struct ScriptString:AGSCCDynamicObject, ICCStringClass
+{
+  virtual void *CreateString (const char *fromText);
+};
+
+const char *
+CreateNewScriptString (const char *fromText, bool reAllocate = true);
+
+void *
+ScriptString::CreateString (const char *fromText)
+{
+  return (void *) CreateNewScriptString (fromText);
+}