Skip to content

Commit ec752b8

Browse files
committed
arcv: apex: Validate immediate arguments during expansion.
Add validation for immediate arguments in APEX intrinsic calls that do not support the APEX_XD format. This check is performed during riscv_expand_builtin_direct, where the actual values of the current RTL expression are available. The validation ensures that the argument is a constant integer and falls within the correct range: - For APEX_XI and APEX_XC formats: signed 12-bit [-2048, 2047] - For APEX_XS format: signed 8-bit [-128, 127] Report an error if the value does not meet the previous checks. Signed-off-by: Luis Silva <[email protected]>
1 parent 3816b59 commit ec752b8

File tree

4 files changed

+128
-22
lines changed

4 files changed

+128
-22
lines changed

gcc/config/riscv/arcv-apex.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,13 @@
5151
""
5252
{
5353
const char *str = arcv_apex_get_insn_name (operands[0]);
54+
const char *suffix = arcv_apex_get_insn_suffix (operands[0]);
5455
switch (which_alternative)
5556
{
5657
case 0:
57-
return xasprintf ("%si\t%d ; 'XI' `insn src0`",
58+
return xasprintf ("%s%s\t%d ; 'XI' `insn src0`",
5859
str,
60+
suffix,
5961
(int) INTVAL (operands[1]));
6062
case 1:
6163
return xasprintf ("%s\t%s ; 'XD' `insn src0`",
@@ -96,11 +98,13 @@
9698
""
9799
{
98100
const char *str = arcv_apex_get_insn_name (operands[0]);
101+
const char *suffix = arcv_apex_get_insn_suffix (operands[0]);
99102
switch (which_alternative)
100103
{
101104
case 0:
102-
return xasprintf ("%si\t%s,%d ; 'XS' `insn src0, src1`",
105+
return xasprintf ("%s%s\t%s,%d ; 'XS' `insn src0, src1`",
103106
str,
107+
suffix,
104108
reg_names[REGNO (operands[1])],
105109
(int) INTVAL (operands[2]));
106110
case 1:
@@ -213,11 +217,13 @@
213217
""
214218
{
215219
const char *str = arcv_apex_get_insn_name (operands[1]);
220+
const char *suffix = arcv_apex_get_insn_suffix (operands[1]);
216221
switch (which_alternative)
217222
{
218223
case 0:
219-
return xasprintf ("%si\t%s,%d ; 'XI' `insn des, src0` volatile",
224+
return xasprintf ("%s%s\t%s,%d ; 'XI' `insn des, src0` volatile",
220225
str,
226+
suffix,
221227
reg_names[REGNO (operands[0])],
222228
(int) INTVAL (operands[2]));
223229
case 1:
@@ -262,11 +268,13 @@
262268
""
263269
{
264270
const char *str = arcv_apex_get_insn_name (operands[1]);
271+
const char *suffix = arcv_apex_get_insn_suffix (operands[1]);
265272
switch (which_alternative)
266273
{
267274
case 0:
268-
return xasprintf ("%si\t%s,%d ; 'XI' `insn des, src0`",
275+
return xasprintf ("%s%s\t%s,%d ; 'XI' `insn des, src0`",
269276
str,
277+
suffix,
270278
reg_names[REGNO (operands[0])],
271279
(int) INTVAL (operands[2]));
272280
case 1:
@@ -312,17 +320,20 @@
312320
""
313321
{
314322
const char *str = arcv_apex_get_insn_name (operands[1]);
323+
const char *suffix = arcv_apex_get_insn_suffix (operands[1]);
315324
switch (which_alternative)
316325
{
317326
case 0:
318-
return xasprintf ("%si\t%s,%s,%d ; 'XS' `insn dest, src0, imm/src1` volatile",
327+
return xasprintf ("%s%s\t%s,%s,%d ; 'XS' `insn dest, src0, imm/src1` volatile",
319328
str,
329+
suffix,
320330
reg_names[REGNO (operands[0])],
321331
reg_names[REGNO (operands[2])],
322332
(int) INTVAL (operands[3]));
323333
case 1:
324334
return xasprintf ("%s%s\t%s,%s,%d ; 'XC' `insn dest/src0, imm` volatile",
325335
str,
336+
suffix,
326337
reg_names[REGNO (operands[0])],
327338
reg_names[REGNO (operands[2])],
328339
(int) INTVAL (operands[3]));
@@ -372,17 +383,20 @@
372383
""
373384
{
374385
const char *str = arcv_apex_get_insn_name (operands[1]);
386+
const char *suffix = arcv_apex_get_insn_suffix (operands[1]);
375387
switch (which_alternative)
376388
{
377389
case 0:
378-
return xasprintf ("%si\t%s,%s,%d ; 'XS' `insn dest, src0, imm/src1`",
390+
return xasprintf ("%s%s\t%s,%s,%d ; 'XS' `insn dest, src0, imm/src1`",
379391
str,
392+
suffix,
380393
reg_names[REGNO (operands[0])],
381394
reg_names[REGNO (operands[2])],
382395
(int) INTVAL (operands[3]));
383396
case 1:
384397
return xasprintf ("%s%s\t%s,%s,%d ; 'XC' `insn dest/src0, imm`",
385398
str,
399+
suffix,
386400
reg_names[REGNO (operands[0])],
387401
reg_names[REGNO (operands[2])],
388402
(int) INTVAL (operands[3]));

gcc/config/riscv/riscv-builtins.cc

Lines changed: 97 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ struct arcv_apex_builtin_description {
253253
/* Specifies the instruction format. See "apex_insn_format" enum
254254
for more details. */
255255
unsigned int insn_formats;
256+
257+
/* Suffix added to the instruction name when the format is resolved
258+
(e.g., XS, XI, or XC); set to "i" if resolved, otherwise "". */
259+
const char *insn_suffix;
256260
};
257261

258262
/* The XD-type has 8 function bits encoding up to 256 instructions.
@@ -382,6 +386,73 @@ riscv_expand_builtin_insn (enum insn_code icode, unsigned int n_ops,
382386
return has_target_p ? ops[0].value : const0_rtx;
383387
}
384388

389+
/* Validate the immediate argument passed to an APEX intrinsic.
390+
391+
This function checks if the argument to the intrinsic call is a constant
392+
integer and fits within the required immediate range depending on the
393+
format supported by the given SUBCODE. Only instructions that do not
394+
support APEX_XD are validated here.
395+
396+
- For APEX_XI and APEX_XC formats: the argument must be a
397+
signed 12-bit integer.
398+
- For APEX_XS format: the argument must be a signed 8-bit integer.
399+
400+
Returns false and reports an error if the argument is invalid; true
401+
otherwise. */
402+
403+
static bool
404+
arcv_apex_immediate_argument_valid_p (unsigned int subcode, tree exp)
405+
{
406+
if (!arcv_apex_format_supports_p (subcode, APEX_XD))
407+
{
408+
tree arg;
409+
/* Get the first (and only) argument passed to the intrinsic call. */
410+
if (arcv_apex_format_supports_p (subcode, APEX_XI))
411+
arg = CALL_EXPR_ARG (exp, 0);
412+
else if (arcv_apex_format_supports_p (subcode, APEX_XC)
413+
|| arcv_apex_format_supports_p (subcode, APEX_XS))
414+
arg = CALL_EXPR_ARG (exp, 1);
415+
416+
/* If the argument is NOT a constant integer. */
417+
if (!TREE_CONSTANT (arg) || TREE_CODE (arg) != INTEGER_CST)
418+
{
419+
error ("argument to %qs must be a constant integer",
420+
arcv_apex_builtins[subcode].name);
421+
return false;
422+
}
423+
424+
/* If the current subcode supports the APEX_XI or APEX_XC format, then
425+
the operand must fit within a signed 12-bit immediate. */
426+
if (arcv_apex_format_supports_p (subcode, APEX_XI)
427+
|| arcv_apex_format_supports_p (subcode, APEX_XC))
428+
{
429+
HOST_WIDE_INT val = tree_to_shwi (arg);
430+
/* Check if the value fits within a signed 12-bit immediate. */
431+
if ((val < -2048 || val > 2047))
432+
{
433+
error ("argument value %d is outside the valid range [-2048, 2047]",
434+
val);
435+
return false;
436+
}
437+
}
438+
439+
/* If the current subcode supports the APEX_XS format, then
440+
the operand must fit within a signed 8-bit immediate. */
441+
if (arcv_apex_format_supports_p (subcode, APEX_XS))
442+
{
443+
HOST_WIDE_INT val = tree_to_shwi (arg);
444+
/* Check if the value fits within a signed 8-bit immediate. */
445+
if ((val < -128 || val > 127))
446+
{
447+
error ("argument value %d is outside the valid range [-128, 127]",
448+
val);
449+
return false;
450+
}
451+
}
452+
}
453+
return true;
454+
}
455+
385456
/* Expand a RISCV_BUILTIN_DIRECT or RISCV_BUILTIN_DIRECT_NO_TARGET function;
386457
HAS_TARGET_P says which. EXP is the CALL_EXPR that calls the function
387458
and ICODE is the code of the associated .md pattern. TARGET, if nonnull,
@@ -405,6 +476,9 @@ riscv_expand_builtin_direct (enum insn_code icode, rtx target, tree exp,
405476
rtx const_rtx = GEN_INT (subcode);
406477
/* Add the subcode as an additional input operand to the RTL expression. */
407478
create_input_operand (&ops[opno++], const_rtx, SImode);
479+
/* Validate the immediate argument passed to the APEX intrinsic. */
480+
if (!arcv_apex_immediate_argument_valid_p (subcode, exp))
481+
return const0_rtx;
408482
}
409483

410484
/* Map the arguments to the other operands. */
@@ -528,6 +602,18 @@ arcv_apex_get_insn_name (rtx op)
528602
return arcv_apex_builtins[subcode].insn_name;
529603
}
530604

605+
/* Return the instruction suffix for an APEX subcode operand.
606+
607+
This suffix is used to mark instructions whose format was resolved
608+
(e.g., XS, XI, or XC) rather than explicitly specified via pragma. */
609+
610+
const char*
611+
arcv_apex_get_insn_suffix (rtx op)
612+
{
613+
unsigned int subcode = UINTVAL (op);
614+
return arcv_apex_builtins[subcode].insn_suffix;
615+
}
616+
531617
/* Checks if the APEX builtin instruction identified by the subcode
532618
supports the given instruction format.
533619
@@ -646,10 +732,6 @@ arcv_apex_set_insn_operand_flags (unsigned int insn_format, tree fndecl)
646732
static unsigned int
647733
arcv_apex_resolve_insn_format (unsigned int insn_format, unsigned int opcode)
648734
{
649-
/* Return early if a instruction format was defined by the used. */
650-
if ((insn_format & 0xF) != APEX_NONE)
651-
return insn_format;
652-
653735
/* Extract the operand flags (DEST, SRC0, SRC1) from bits 5–7.
654736
These bits encode the operand signature used for format selection. */
655737
unsigned int insn_operands = insn_format >> 5;
@@ -863,15 +945,21 @@ arcv_apex_init_builtin (tree fndecl, const char *fn_name,
863945

864946
/* Resolve the instruction format:
865947
If the user did not specify an instruction format at pragma level,
866-
infer the concrete format based on opcode and operand flags; otherwise,
867-
leave it as is. */
868-
insn_formats = arcv_apex_resolve_insn_format (insn_formats, opcode);
948+
infer the concrete format based on opcode and operand flags. Mark
949+
the insn. name with an "i" suffix for resolved XS/XI/XC formats;
950+
otherwise, leave it as is. */
951+
const char *insn_suffix = "";
952+
if ((insn_formats & 0xF) == APEX_NONE)
953+
{
954+
insn_formats = arcv_apex_resolve_insn_format (insn_formats, opcode);
955+
insn_suffix = "i";
956+
}
869957

870958
/* Validate the format is allowed for this instruction. */
871959
arcv_apex_validate_insn_format (fn_name, insn_formats, opcode);
872960

873961
/* Print .extInstruction section about APEX instruction. */
874-
arcv_apex_print_insn_section (insn_name, opcode, insn_formats);
962+
arcv_apex_print_insn_section (insn_name, insn_suffix, opcode, insn_formats);
875963

876964
/* Determine the internal instruction code (icode). */
877965
enum insn_code icode = arcv_apex_get_icode (insn_formats);
@@ -883,7 +971,7 @@ arcv_apex_init_builtin (tree fndecl, const char *fn_name,
883971

884972
/* Store APEX insn information. */
885973
arcv_apex_builtins[arcv_apex_builtin_index]
886-
= { icode, fn_name, insn_name, builtin_type, insn_formats };
974+
= { icode, fn_name, insn_name, builtin_type, insn_formats, insn_suffix };
887975

888976
/* Modify the prototype type as built-in. */
889977
fndecl->function_decl.built_in_class = BUILT_IN_MD;

gcc/config/riscv/riscv-protos.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,8 +770,10 @@ extern bool riscv_is_micro_arch (enum riscv_microarchitecture_type);
770770

771771
extern bool arcv_micro_arch_supports_fusion_p (void);
772772

773-
extern void arcv_apex_print_insn_section (const char *, int, unsigned int);
773+
extern void arcv_apex_print_insn_section (const char *, const char *,
774+
int, unsigned int);
774775
extern const char* arcv_apex_get_insn_name (rtx);
776+
extern const char* arcv_apex_get_insn_suffix (rtx);
775777
extern bool arcv_apex_format_supports_p (unsigned int, unsigned int);
776778
extern void arcv_apex_init_builtin (tree, const char *, const char *,
777779
unsigned int, int);

gcc/config/riscv/riscv.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9693,8 +9693,8 @@ riscv_asm_output_variant_cc (FILE *stream, const tree decl, const char *name)
96939693
and source1. */
96949694

96959695
void
9696-
arcv_apex_print_insn_section (const char *insn_name, int opcode,
9697-
unsigned int insn_format)
9696+
arcv_apex_print_insn_section (const char *insn_name, const char *insn_suffix,
9697+
int opcode, unsigned int insn_format)
96989698
{
96999699
/* Extract the operand flags (DEST, SRC0, SRC1) from bits 5–7.
97009700
These bits encode the operand signature used for format selection. */
@@ -9718,7 +9718,8 @@ arcv_apex_print_insn_section (const char *insn_name, int opcode,
97189718
if ((insn_format & (APEX_XS | APEX_XC))
97199719
&& (insn_operands == APEX_DEST_FTYPE_SRC0_SRC1))
97209720
{
9721-
fprintf (asm_out_file, "\t.extInstruction %si,%d", insn_name, opcode);
9721+
fprintf (asm_out_file, "\t.extInstruction %s%s,%d",
9722+
insn_name, insn_suffix, opcode);
97229723
if (insn_format & APEX_XS)
97239724
fputs (",XS", asm_out_file);
97249725
if (insn_format & APEX_XC)
@@ -9729,7 +9730,8 @@ arcv_apex_print_insn_section (const char *insn_name, int opcode,
97299730
/* Print XI format with dest, src0 operands; append ",void" if no dest. */
97309731
if (insn_format & APEX_XI)
97319732
{
9732-
fprintf (asm_out_file, "\t.extInstruction %si,%d,XI", insn_name, opcode);
9733+
fprintf (asm_out_file, "\t.extInstruction %s%s,%d,XI",
9734+
insn_name, insn_suffix, opcode);
97339735
if ((insn_format & APEX_DEST) == 0)
97349736
fputs (",void", asm_out_file);
97359737
fputc ('\n', asm_out_file);
@@ -9739,8 +9741,8 @@ arcv_apex_print_insn_section (const char *insn_name, int opcode,
97399741
if ((insn_format & APEX_XS)
97409742
&& (insn_operands == APEX_VOID_FTYPE_SRC0_SRC1))
97419743
{
9742-
fprintf (asm_out_file, "\t.extInstruction %si,%d,XS,void\n",
9743-
insn_name, opcode);
9744+
fprintf (asm_out_file, "\t.extInstruction %s%s,%d,XS,void\n",
9745+
insn_name, insn_suffix, opcode);
97449746
}
97459747
}
97469748

0 commit comments

Comments
 (0)