}
}
}
+ else if (output != error_mark_node && strstr (constraint, "-"))
+ {
+ error_at (loc, "%<-%> modifier used inside of a function");
+ output = error_mark_node;
+ }
TREE_VALUE (tail) = output;
}
}
}
}
+ else if (input != error_mark_node && strstr (constraint, "-"))
+ {
+ error_at (loc, "%<-%> modifier used inside of a function");
+ input = error_mark_node;
+ }
TREE_VALUE (tail) = input;
}
(define_constraint "i"
"Matches a general integer constant."
(and (match_test "CONSTANT_P (op)")
- (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+ (match_test "!flag_pic || raw_constraint_p || LEGITIMATE_PIC_OPERAND_P (op)")))
(define_constraint "s"
"Matches a symbolic integer constant."
(and (match_test "CONSTANT_P (op)")
(match_test "!CONST_SCALAR_INT_P (op)")
- (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+ (match_test "!flag_pic || raw_constraint_p || LEGITIMATE_PIC_OPERAND_P (op)")))
(define_constraint ":"
"Defines a symbol."
(define_constraint "n"
"Matches a non-symbolic integer constant."
(and (match_test "CONST_SCALAR_INT_P (op)")
- (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+ (match_test "!flag_pic || raw_constraint_p || LEGITIMATE_PIC_OPERAND_P (op)")))
(define_constraint "E"
"Matches a floating-point constant."
}
}
}
+ else if (operand != error_mark_node && strstr (constraint, "-"))
+ {
+ error_at (loc, "%<-%> modifier used inside of a function");
+ operand = error_mark_node;
+ }
TREE_VALUE (t) = operand;
}
}
}
}
+ else if (operand != error_mark_node && strstr (constraint, "-"))
+ {
+ error_at (loc, "%<-%> modifier used inside of a function");
+ operand = error_mark_node;
+ }
TREE_VALUE (t) = operand;
}
@dots{})
@end smallexample
@end ifset
+
+@cindex @samp{-} in constraint
+@item -
+Says that the selected following constraints within the same alternative
+should be matched differently. Normally in PIC code symbolic operands
+in constraints like @samp{i}, @samp{s} or @samp{n} are not allowed at all
+or severely restricted. The @samp{-} modifier, which is only allowed
+outside of functions, allows symbolic operands even in PIC code. This
+modifier is usually used together with the @code{cc} operand modifier.
+
+@smallexample
+extern void foo (void), bar (void);
+int v;
+extern int w;
+asm (".globl %cc0, %cc2; .text; %cc0: call %cc1; ret; .data; %cc2: .word %cc3"
+ :: ":" (foo), "-s" (&bar), ":" (&w), "-i" (&v));
+@end smallexample
+
+This asm declaration tells the compiler it defines function @code{foo} and
+variable @code{w} and uses function @code{bar} and variable @code{v}. This
+will compile even with PIC, but it is up to the user to ensure it will
+assemble correctly and have the expected behavior.
@end table
@node Machine Constraints
int which_alternative;
+/* True for inline asm operands with - constraint modifier. */
+bool raw_constraint_p;
+
/* Nonzero after end of reload pass.
Set to 1 or 0 by toplev.cc.
Controls the significance of (SUBREG (MEM)). */
switch (c)
{
case ',':
+ raw_constraint_p = false;
constraint++;
continue;
result = 1;
break;
+ case '-':
+ raw_constraint_p = true;
+ constraint++;
+ continue;
+
case '<':
case '>':
/* ??? Before auto-inc-dec, auto inc/dec insns are not supposed
constraint++;
while (--len && *constraint && *constraint != ',');
if (len)
- return 0;
+ {
+ raw_constraint_p = false;
+ return 0;
+ }
}
+ raw_constraint_p = false;
/* For operands without < or > constraints reject side-effects. */
if (AUTO_INC_DEC && !incdec_ok && result && MEM_P (op))
case ',':
c = '\0';
break;
+ case '-':
+ raw_constraint_p = true;
+ break;
case '#':
/* Ignore rest of this alternative as far as
}
while (p += len, c);
+ raw_constraint_p = false;
constraints[opno] = p;
/* If this operand did not win somehow,
this alternative loses. */
matched. */
extern int which_alternative;
+/* True for inline asm operands with - constraint modifier. */
+extern bool raw_constraint_p;
+
/* The following vectors hold the results from insn_extract. */
struct recog_data_d
case 'E': case 'F': case 'G': case 'H':
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L': case 'M':
- case 'N': case 'O': case 'P': case ',':
+ case 'N': case 'O': case 'P': case ',': case '-':
break;
case '0': case '1': case '2': case '3': case '4':
case 'E': case 'F': case 'G': case 'H':
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L': case 'M':
- case 'N': case 'O': case 'P': case ',':
+ case 'N': case 'O': case 'P': case ',': case '-':
break;
case ':':
/* { dg-options "-O0" } */
extern int v[42], w;
+int x[42], y;
void foo (void);
+void bar (void) {}
-asm ("# %cc0: %cc1:" :: ":" (foo), ":" (v), ":" (&w));
+asm ("# %cc0: %cc1: %cc2: %cc3 %cc4 %cc5" :: ":" (foo), ":" (v), ":" (&w), "-i" (bar), "-s" (x), "-s" (&y));
--- /dev/null
+/* PR c/41045 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-fpic" { target fpic } } */
+
+struct S { char a; long long b; int c; };
+enum E { E0, E1 = sizeof (struct S) + 15 };
+int v[42];
+void foo (void) {}
+
+asm ("# %0 %1 %2 %cc3 %cc4 %% %="
+ :: "i" (sizeof (struct S)),
+ "i" (__builtin_offsetof (struct S, c)),
+ "i" (E1),
+ "-s" (foo),
+ "-i" (v));
--- /dev/null
+/* PR c/41045 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+void
+foo (void)
+{
+ int m;
+ asm ("" : "=-m" (m)); /* { dg-error "'-' modifier used inside of a function" } */
+ asm ("" : : "-m" (m)); /* { dg-error "'-' modifier used inside of a function" } */
+ asm ("" : : "-i" (32)); /* { dg-error "'-' modifier used inside of a function" } */
+ asm ("" : : "-s" (foo)); /* { dg-error "'-' modifier used inside of a function" } */
+}