Posting this pre-patch as an RFC; I wonder what you think about this
approach, as well as the alternatives suggested in the TODO section
below.

I'd also like to ask for opinions on what the C/++ syntax for this
feature should be.  I've had some people likely to use this feature
(some OS developers) express that they prefer

  asm DIALECT (...);

... which would require some amount of target-specific syntax.
Pinski suggested that this be an attribute; something like:

  [[gnu::asm_dialect (DIALECT)]] asm (...);

... which requires no platform-specific syntax (DIALECT can be a
predefined value expanding to the dialect index).  Note that both
approaches require significant parser changes; currently, not every
context that can have an extended-asm stmts can have attributes (at
least in the C FE) and the attributes on extended-asm statements are, of
course, just unused, even if present.

I also wonder how we should dump/parse these in the GIMPLE syntax.
Perhaps there we can just use the first form, omitting DIALECT if it is
negative (i.e. unset).

I've tested this so far by hacking in that each extended-ASM statement
is to be of Intel syntax, and GCC produced:

  $ ./cc1 <<<'int foo(int x) { int y; asm ("mov %0, %1" : "=r" (y) : "r" (x)); 
return y; }' -o - -quiet
          .file   "<stdin>"
          .text
          .globl  foo
          .type   foo, @function
  foo:
  .LFB0:
          .cfi_startproc
          pushq   %rbp
          .cfi_def_cfa_offset 16
          .cfi_offset 6, -16
          movq    %rsp, %rbp
          .cfi_def_cfa_register 6
          movl    %edi, -20(%rbp)
          movl    -20(%rbp), %eax
          .intel_syntax noprefix
  #APP
  # 1 "<stdin>" 1
          mov eax, eax
  # 0 "" 2
  #NO_APP
          .att_syntax
          movl    %eax, -4(%rbp)
          movl    -4(%rbp), %eax
          popq    %rbp
          .cfi_def_cfa 7, 8
          ret
          .cfi_endproc
  .LFE0:
          .size   foo, .-foo
          .ident  "GCC: (GNU) 16.0.0 20251225 (experimental)"
          .section        .note.GNU-stack,"",@progbits

... which seems right :-)

I intend to add this to the GIMPLE, C, C++ and libgccjit FEs.

IMO the use-case for this feature in the C/++ frontends is somewhat
diminished by the recent work LH put into '-masm=intel' (which seems to
have gotten it to the point of being able to process most programs
fine), but it is still unavoidable for the Rust frontends AFAIK, and I
didn't know that any progress was made on '-masm=intel' at time of
writing this patch.

Any and all thoughts are much appreciated.

Have a lovely holiday season, all!
---------- >8 ----------
This patch allows backends to handle extended-ASM statements of
different dialects in the same translation unit, and implements that
mechanism for i386 on targets utilizing GAS.

In essence, this patch allows GIMPLE and RTL (GENERIC pending) to carry
information about which dialect their
gimple_asm_string/ASM_OPERANDS_TEMPLATE is targeting, as an index (the
same index as the one deciding which alternative in {..|..|..} in
templates is picked), and allows the final pass to let the backend know
to switch to and from that selected dialect.  The backend is expected to
update ASSEMBLER_DIALECT and output appropriate directives to switch to
the new syntax (if necessary).

This is was recently requested on the Gcc-help ML[1] and is needed by
the Rust front-end eventually, as Rust allows inline-asm to specify what
syntax is being used (defaulting to Intel syntax)[2].

TODO:

- Carry the dialect as something more type-safe, say an enum (in the
  case of x86, asm_dialect defined in i386-opt.h), with (E)-1, where E
  is the enums type, being reserved for an invalid value,
- Expose this in GENERIC; this is necessary for libgccjit to gain the
  same ability in its interface (needed for rustc_codegen_gcc)
- Perhaps switch to using some ASM_DIALECT RTX to carry the dialect
  rather than changing ASM_OPERANDS.  ASM_DIALECT would be PARALLEL to
  the SETs/ASM_OPERANDs/ASM_INPUTs.  This would mean that memory usage
  is not increased unless a dialect is set (well, in RTX; GIMPLE would
  still be affected), and mean that basic ASM can now get dialect
  switching also (currently the dialect index is simply ignored for
  basic ASM by cfgexpand),
- Allow writing this value out into GIMPLE dumps and reading it back in
  in the GIMPLE FE, and add tests,
- Add new syntax for this to C and C++,
- Add a target hook TARGET_ASSEMBLER_DIALECT_VALID_P, and remove the
  boolean return value from TARGET_SWITCH_ASSEMBLER_DIALECT,
- Make terms consistent (DIALECT_NUM and DIALECT_INDEX used
  sporadically).

[1] 
https://inbox.sourceware.org/gcc-help/cadu2ddljvt_dovpy9zq35junmkzzyzs7j3_w1wty9bcptg_...@mail.gmail.com/
[2] 
https://doc.rust-lang.org/nightly/reference/inline-assembly.html#r-asm.options.supported-options.att_syntax

gcc/ChangeLog:

        * cfgexpand.cc (expand_asm_stmt): Propagate GIMPLE_ASM
        dialect_index into generated ASM_OPERANDS.
        * config/i386/darwin.h (TARGET_SWITCH_ASSEMBLER_DIALECT): Don't
        allow switching dialects on Darwin targets.
        * config/i386/i386.cc (x86_emit_syntax_directive): New function.
        Emits directive that changes assembler syntax.
        (ix86_set_asm_dialect): New function.  Changes active
        ASM_DIALECT.
        * config/i386/i386.h (ix86_set_asm_dialect): Declare.
        (TARGET_SWITCH_ASSEMBLER_DIALECT): Define as
        ix86_set_asm_dialect.
        * target.def: Define TARGET_SWITCH_ASSEMBLER_DIALECT hook.
        * doc/tm.texi: Regenerate.
        * doc/tm.texi.in: Output documentation for
        TARGET_SWITCH_ASSEMBLER_DIALECT.
        * final.cc (final_scan_insn_1): Implement dialect switching, if
        ASM_OPERANDS requires a specific dialect.
        * gimple.cc (gimple_build_asm_1): Initialize dialect_index to
        -1.
        * gimple.h (struct gasm): Add dialect_index field.
        (gimple_asm_dialect_index): New.  Getter for dialect_index.
        (gimple_asm_set_dialect_index): New.  Setter for dialect_index.
        * rtl.def (ASM_OPERANDS): Add dialect index operand.
        * ira.cc (ira_nullify_asm_goto): Copy ASM_OPERANDS_DIALECT_NUM
        from insn.
        * optabs.cc (expand_asm_memory_blockage): Update
        gen_rtx_ASM_OPERANDS calls.
        (expand_asm_reg_clobber_mem_blockage): Ditto.
        * print-rtl.cc (rtx_writer::print_rtx_operand_code_L): Update
        idx check in ASM_OPERANDS case.
        * recog.cc (decode_asm_operands): Allow reading out selected
        dialect index.
        * rtl.h (ASM_OPERANDS_SOURCE_LOCATION): Update operand
        index (6 -> 7).
        (ASM_OPERANDS_DIALECT_NUM): New.  Retrieves the selected dialect
        index for this ASM_OPERANDS.
        (decode_asm_operands): Add DIALECT_NUMBER argument, defaulted to
        nullptr.
---
 gcc/cfgexpand.cc         |  6 +++--
 gcc/config/i386/darwin.h |  1 +
 gcc/config/i386/i386.cc  | 31 ++++++++++++++++++++++++-
 gcc/config/i386/i386.h   |  3 +++
 gcc/doc/tm.texi          | 12 ++++++++++
 gcc/doc/tm.texi.in       |  2 ++
 gcc/final.cc             | 50 +++++++++++++++++++++++++++++++++++++++-
 gcc/gimple.cc            |  1 +
 gcc/gimple.h             | 22 ++++++++++++++++++
 gcc/ira.cc               |  1 +
 gcc/optabs.cc            |  4 ++--
 gcc/print-rtl.cc         |  2 +-
 gcc/recog.cc             |  5 +++-
 gcc/rtl.def              |  6 +++--
 gcc/rtl.h                |  6 +++--
 gcc/target.def           | 17 ++++++++++++++
 16 files changed, 157 insertions(+), 12 deletions(-)

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index 7d1eab4fdac9..05baab35c97a 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -3407,6 +3407,7 @@ expand_asm_stmt (gasm *stmt)
   unsigned noutputs = gimple_asm_noutputs (stmt);
   unsigned ninputs = gimple_asm_ninputs (stmt);
   unsigned nlabels = gimple_asm_nlabels (stmt);
+  int dialect_index = gimple_asm_dialect_index (stmt);
   unsigned i;
   bool error_seen = false;
 
@@ -3826,7 +3827,7 @@ expand_asm_stmt (gasm *stmt)
                                    : GET_MODE (output_rvec[0])),
                                   ggc_strdup (str),
                                   "", 0, argvec, constraintvec,
-                                  labelvec, locus);
+                                  labelvec, dialect_index, locus);
   MEM_VOLATILE_P (body) = gimple_asm_volatile_p (stmt);
 
   for (i = 0; i < ninputs; ++i)
@@ -3914,7 +3915,8 @@ expand_asm_stmt (gasm *stmt)
              src = gen_rtx_ASM_OPERANDS (GET_MODE (o),
                                          ASM_OPERANDS_TEMPLATE (obody),
                                          constraints[i], i, argvec,
-                                         constraintvec, labelvec, locus);
+                                         constraintvec, labelvec,
+                                         dialect_index, locus);
              MEM_VOLATILE_P (src) = gimple_asm_volatile_p (stmt);
            }
          XVECEXP (body, 0, i) = gen_rtx_SET (o, src);
diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h
index f4037b133a5d..da3cef8fdb0b 100644
--- a/gcc/config/i386/darwin.h
+++ b/gcc/config/i386/darwin.h
@@ -134,6 +134,7 @@ along with GCC; see the file COPYING3.  If not see
 /* The Darwin assembler mostly follows AT&T syntax.  */
 #undef ASSEMBLER_DIALECT
 #define ASSEMBLER_DIALECT ASM_ATT
+#undef TARGET_SWITCH_ASSEMBLER_DIALECT
 
 /* Define macro used to output shift-double opcodes when the shift
    count is in %cl.  Some assemblers require %cl as an argument;
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 80a4228bbb9a..5070bacf6273 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -23714,6 +23714,22 @@ x86_output_mi_thunk (FILE *file, tree thunk_fndecl, 
HOST_WIDE_INT delta,
   flag_force_indirect_call = saved_flag_force_indirect_call;
 }
 
+static void
+x86_emit_syntax_directive (asm_dialect new_dialect)
+{
+  switch (new_dialect)
+    {
+    case ASM_INTEL:
+      fputs ("\t.intel_syntax noprefix\n", asm_out_file);
+      break;
+    case ASM_ATT:
+      fputs ("\t.att_syntax\n", asm_out_file);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+}
+
 static void
 x86_file_start (void)
 {
@@ -23728,7 +23744,20 @@ x86_file_start (void)
   if (X86_FILE_START_FLTUSED)
     fputs ("\t.global\t__fltused\n", asm_out_file);
   if (ix86_asm_dialect == ASM_INTEL)
-    fputs ("\t.intel_syntax noprefix\n", asm_out_file);
+    x86_emit_syntax_directive (ASM_INTEL);
+}
+
+bool
+ix86_set_asm_dialect (int new_dialect)
+{
+  auto new_dialect_as_enum = static_cast<asm_dialect> (new_dialect);
+  if (new_dialect_as_enum != ASM_INTEL
+      && new_dialect_as_enum != ASM_ATT)
+    return false;
+  if (ix86_asm_dialect != new_dialect_as_enum)
+    x86_emit_syntax_directive (new_dialect_as_enum);
+  ix86_asm_dialect = new_dialect_as_enum;
+  return true;
 }
 
 int
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index d914dc92e455..66a8eb289889 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -541,6 +541,9 @@ extern unsigned char ix86_prefetch_sse;
 #define TARGET_PREFETCH_SSE    ix86_prefetch_sse
 
 #define ASSEMBLER_DIALECT      (ix86_asm_dialect)
+bool ix86_set_asm_dialect (int new_dialect);
+#define TARGET_SWITCH_ASSEMBLER_DIALECT \
+                               ix86_set_asm_dialect
 
 #define TARGET_SSE_MATH                ((ix86_fpmath & FPMATH_SSE) != 0)
 #define TARGET_MIX_SSE_I387 \
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 2ddb11846ee1..c0748a66d9e0 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -9912,6 +9912,18 @@ if the syntax variant are larger and involve such things 
as different
 opcodes or operand order.
 @end defmac
 
+@deftypefn {Target Hook} bool TARGET_SWITCH_ASSEMBLER_DIALECT (int 
@var{dialect})
+If defined, this hook switches the assembler dialect, including the value
+of @code{ASSEMBLER_DIALECT}, to @var{dialect}, and return @code{true}.
+
+If the value of @var{dialect} is not valid for the given target,
+or the dialect could not be switched for some other reason, returns
+@code{false}.  In that case, there shall be no side-effects.
+
+The hook may also emit extra code into @var{asm_out_file} to inform the
+assembler about the change in dialect.
+@end deftypefn
+
 @defmac ASM_OUTPUT_REG_PUSH (@var{stream}, @var{regno})
 A C expression to output to @var{stream} some assembler code
 which will push hard register number @var{regno} onto the stack.
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 253965bdafc2..98a75a5cbb01 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -6445,6 +6445,8 @@ if the syntax variant are larger and involve such things 
as different
 opcodes or operand order.
 @end defmac
 
+@hook TARGET_SWITCH_ASSEMBLER_DIALECT
+
 @defmac ASM_OUTPUT_REG_PUSH (@var{stream}, @var{regno})
 A C expression to output to @var{stream} some assembler code
 which will push hard register number @var{regno} onto the stack.
diff --git a/gcc/final.cc b/gcc/final.cc
index afcb0bb9efbc..535802557883 100644
--- a/gcc/final.cc
+++ b/gcc/final.cc
@@ -2627,12 +2627,13 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int 
optimize_p ATTRIBUTE_UNUSED,
            const char *string;
            location_t loc;
            expanded_location expanded;
+           int new_dialect = -1;
 
            /* There's no telling what that did to the condition codes.  */
            CC_STATUS_INIT;
 
            /* Get out the operand values.  */
-           string = decode_asm_operands (body, ops, NULL, NULL, NULL, &loc);
+           string = decode_asm_operands (body, ops, NULL, NULL, NULL, &loc, 
&new_dialect);
            /* Inhibit dying on what would otherwise be compiler bugs.  */
            insn_noperands = noperands;
            this_is_asm_operands = insn;
@@ -2645,6 +2646,41 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int 
optimize_p ATTRIBUTE_UNUSED,
            /* Output the insn using them.  */
            if (string[0])
              {
+#ifdef ASSEMBLER_DIALECT
+               auto original_dialect = dialect_number;
+               auto can_switch_dialects = 
!!targetm.asm_out.switch_assembler_dialect;
+#else
+               auto can_switch_dialects = false;
+#endif
+
+               if (new_dialect >= 0)
+                 {
+                   if (!can_switch_dialects)
+                     {
+                       /* Don't support switching at all.  */
+                       error_at (loc,
+                                 "this target does not support switching"
+                                 " assembler dialects");
+                       /* We can't, give up.  */
+                       new_dialect = -1;
+                     }
+                   else if (!targetm.asm_out.switch_assembler_dialect 
(new_dialect))
+                     {
+                       /* We couldn't switch, this indicates an invalid
+                          dialect number.
+
+                          TODO(arsen): We should, instead, check this much
+                          earlier and reject.  */
+                       error_at (loc,
+                                 "dialect %d does not exist on this target",
+                                 new_dialect);
+                       new_dialect = -1;
+                     }
+                   else
+                     /* The dialect got switched.  Reload.  */
+                     dialect_number = ASSEMBLER_DIALECT;
+                 }
+
                app_enable ();
                if (expanded.file && expanded.line)
                  fprintf (asm_out_file, "%s %i \"%s\" 1\n",
@@ -2654,6 +2690,18 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int 
optimize_p ATTRIBUTE_UNUSED,
                if (expanded.file && expanded.line)
                  fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START);
 #endif
+
+#ifdef ASSEMBLER_DIALECT
+               /* If we did switch dialects, we need to switch back.  The rest
+                  of the code should be unaffected.  Note that new_dialect is
+                  necessarily -1 if the switch did not happen.  */
+               app_disable ();
+               if (new_dialect >= 0)
+                 {
+                   targetm.asm_out.switch_assembler_dialect (original_dialect);
+                   dialect_number = ASSEMBLER_DIALECT;
+                 }
+#endif
              }
 
            if (targetm.asm_out.final_postscan_insn)
diff --git a/gcc/gimple.cc b/gcc/gimple.cc
index b968a45aaa06..9cf62c868e06 100644
--- a/gcc/gimple.cc
+++ b/gcc/gimple.cc
@@ -662,6 +662,7 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, 
unsigned noutputs,
         gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
                               ninputs + noutputs + nclobbers + nlabels));
 
+  p->dialect_index = -1;  /* Default to no switching.  */
   p->ni = ninputs;
   p->no = noutputs;
   p->nc = nclobbers;
diff --git a/gcc/gimple.h b/gcc/gimple.h
index b421850625e0..be924df0de1f 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -581,6 +581,10 @@ struct GTY((tag("GSS_ASM")))
   unsigned char nl;
 
   /* [ WORD 12 ]
+     Dialect index.  */
+  unsigned dialect_index;
+
+  /* [ WORD 13 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
@@ -4134,6 +4138,24 @@ gimple_asm_nlabels (const gasm *asm_stmt)
   return asm_stmt->nl;
 }
 
+/* Return the index of the assembler dialect to use for this GIMPLE_ASM.  -1
+   means default dialect.  */
+
+inline unsigned
+gimple_asm_dialect_index (const gasm *asm_stmt)
+{
+  return asm_stmt->dialect_index;
+}
+
+/* Set dialect index of ASM_STMT to dialect.  */
+
+inline void
+gimple_asm_set_dialect_index (gasm *asm_stmt, int dialect)
+{
+  /* TODO(arsen): add a hook to verify this value.  */
+  asm_stmt->dialect_index = dialect;
+}
+
 /* Return input operand INDEX of GIMPLE_ASM ASM_STMT.  */
 
 inline tree
diff --git a/gcc/ira.cc b/gcc/ira.cc
index 3e15966558ed..6f57c6df0ad9 100644
--- a/gcc/ira.cc
+++ b/gcc/ira.cc
@@ -6033,6 +6033,7 @@ ira_nullify_asm_goto (rtx_insn *insn)
                                         rtvec_alloc (0),
                                         rtvec_alloc (0),
                                         ASM_OPERANDS_LABEL_VEC (tmp),
+                                        ASM_OPERANDS_DIALECT_NUM (tmp),
                                         ASM_OPERANDS_SOURCE_LOCATION(tmp));
 }
 
diff --git a/gcc/optabs.cc b/gcc/optabs.cc
index 8dea94975c15..695627e45fd9 100644
--- a/gcc/optabs.cc
+++ b/gcc/optabs.cc
@@ -7477,7 +7477,7 @@ expand_asm_memory_blockage (void)
 
   asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, "", "", 0,
                                 rtvec_alloc (0), rtvec_alloc (0),
-                                rtvec_alloc (0), UNKNOWN_LOCATION);
+                                rtvec_alloc (0), -1, UNKNOWN_LOCATION);
   MEM_VOLATILE_P (asm_op) = 1;
 
   clob = gen_rtx_SCRATCH (VOIDmode);
@@ -7513,7 +7513,7 @@ expand_asm_reg_clobber_mem_blockage (HARD_REG_SET regs)
 
   asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, "", "", 0,
                                 rtvec_alloc (0), rtvec_alloc (0),
-                                rtvec_alloc (0), UNKNOWN_LOCATION);
+                                rtvec_alloc (0), -1, UNKNOWN_LOCATION);
   MEM_VOLATILE_P (asm_op) = 1;
 
   rtvec v = rtvec_alloc (num_of_regs + 2);
diff --git a/gcc/print-rtl.cc b/gcc/print-rtl.cc
index 033f7e7aab0d..9818665485c2 100644
--- a/gcc/print-rtl.cc
+++ b/gcc/print-rtl.cc
@@ -460,7 +460,7 @@ rtx_writer::print_rtx_operand_code_L (const_rtx in_rtx, int 
idx)
        }
 #endif
     }
-  else if (idx == 6 && GET_CODE (in_rtx) == ASM_OPERANDS)
+  else if (idx == 7 && GET_CODE (in_rtx) == ASM_OPERANDS)
     {
 #ifndef GENERATOR_FILE
       if (ASM_OPERANDS_SOURCE_LOCATION (in_rtx) != UNKNOWN_LOCATION)
diff --git a/gcc/recog.cc b/gcc/recog.cc
index bfa10df9e4bf..d09637ba392d 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -2123,7 +2123,7 @@ asm_noperands (const_rtx body)
 const char *
 decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
                     const char **constraints, machine_mode *modes,
-                    location_t *loc)
+                    location_t *loc, int *dialect_number)
 {
   int nbase = 0, n, i;
   rtx asmop;
@@ -2193,6 +2193,9 @@ decode_asm_operands (rtx body, rtx *operands, rtx 
**operand_locs,
       gcc_unreachable ();
     }
 
+  if (dialect_number)
+    *dialect_number = ASM_OPERANDS_DIALECT_NUM (asmop);
+
   n = ASM_OPERANDS_INPUT_LENGTH (asmop);
   for (i = 0; i < n; i++)
     {
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 15ae7d10fcc1..729ac014b9ec 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -215,8 +215,10 @@ DEF_RTL_EXPR(ASM_INPUT, "asm_input", "sL", RTX_EXTRA)
      Each element is an ASM_INPUT containing a constraint string
      and whose mode indicates the mode of the input operand.
    6th is a vector of labels that may be branched to by the asm.
-   7th is the source line number.  */
-DEF_RTL_EXPR(ASM_OPERANDS, "asm_operands", "ssiEEEL", RTX_EXTRA)
+   7th is a nonnegative dialect number that should be switched to (and from)
+   when emitting this asm (or -1 if the active dialect is to be kept).
+   8th is the source line number.  */
+DEF_RTL_EXPR(ASM_OPERANDS, "asm_operands", "ssiEEEiL", RTX_EXTRA)
 
 /* A machine-specific operation.
    1st operand is a vector of operands being used by the operation so that
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 9684b45f2a5b..3e33336a0802 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2635,7 +2635,8 @@ do {                                                      
                \
 #define ASM_OPERANDS_LABEL_VEC(RTX) XCVEC (RTX, 5, ASM_OPERANDS)
 #define ASM_OPERANDS_LABEL_LENGTH(RTX) XCVECLEN (RTX, 5, ASM_OPERANDS)
 #define ASM_OPERANDS_LABEL(RTX, N) XCVECEXP (RTX, 5, N, ASM_OPERANDS)
-#define ASM_OPERANDS_SOURCE_LOCATION(RTX) XCLOC (RTX, 6, ASM_OPERANDS)
+#define ASM_OPERANDS_DIALECT_NUM(RTX) XCINT (RTX, 6, ASM_OPERANDS)
+#define ASM_OPERANDS_SOURCE_LOCATION(RTX) XCLOC (RTX, 7, ASM_OPERANDS)
 #define ASM_INPUT_SOURCE_LOCATION(RTX) XCLOC (RTX, 1, ASM_INPUT)
 
 /* 1 if RTX is a mem that is statically allocated in read-only memory.  */
@@ -3854,7 +3855,8 @@ extern void reginfo_cc_finalize (void);
 extern rtx extract_asm_operands (rtx);
 extern int asm_noperands (const_rtx);
 extern const char *decode_asm_operands (rtx, rtx *, rtx **, const char **,
-                                       machine_mode *, location_t *);
+                                       machine_mode *, location_t *,
+                                       int * = nullptr);
 extern void get_referenced_operands (const char *, bool *, unsigned int);
 
 extern enum reg_class reg_preferred_class (int);
diff --git a/gcc/target.def b/gcc/target.def
index d695f38fbcc1..cb19ee209bb6 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -926,6 +926,23 @@ then prepends the @code{USER_LABEL_PREFIX}, if any.",
  tree, (const char *name),
  default_mangle_assembler_name)
 
+/* Switch to assembler dialect DIALECT, and emit the necessary code for the
+   switch.  DIALECT will be nonnegative.  Returns true on success, or false if
+   the DIALECT value is invalid.  */
+DEFHOOK
+(switch_assembler_dialect,
+ "If defined, this hook switches the assembler dialect, including the value\n\
+of @code{ASSEMBLER_DIALECT}, to @var{dialect}, and return @code{true}.\n\
+\n\
+If the value of @var{dialect} is not valid for the given target,\n\
+or the dialect could not be switched for some other reason, returns\n\
+@code{false}.  In that case, there shall be no side-effects.\n\
+\n\
+The hook may also emit extra code into @var{asm_out_file} to inform the\n\
+assembler about the change in dialect.",
+ bool, (int dialect),
+ NULL)
+
 HOOK_VECTOR_END (asm_out)
 
 /* Functions relating to instruction scheduling.  All of these
-- 
2.52.0

Reply via email to