]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: improve diagnostics for bogus JSON tuning inputs [PR124094]
authorDavid Malcolm <dmalcolm@redhat.com>
Sat, 28 Feb 2026 04:35:46 +0000 (23:35 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Sat, 28 Feb 2026 04:35:46 +0000 (23:35 -0500)
Use json-diagnostic.{h,cc} to improve the diagnostics issued
for malformed and invalid JSON tuning inputs: report the
file/line/column and, if possible, the JSON Pointer of the
problematic input.

Before
------

$ ./xgcc -B. -S test.c -muser-provided-CPU=malformed.json
cc1: error: error parsing JSON data: expected ':'; got number

$ ./xgcc -B. -S test.c -muser-provided-CPU=unsigned-3.json
cc1: warning: JSON tuning file does not contain version information; compatibility cannot be verified
cc1: error: key ‘tune_params.sve_width’ value 5000000000 is out of range for ‘uint’ type [0, 4294967295]
cc1: error: validation failed for the provided JSON data

After
-----

$ ./xgcc -B. -S test.c -muser-provided-CPU=malformed.json
malformed.json:3:17: error: error parsing JSON data: expected ':'; got number
    3 |     "sve_width" 128
      |                 ^~~

$ ./xgcc -B. -S test.c -muser-provided-CPU=unsigned-3.json
cc1: warning: JSON tuning file does not contain version information; compatibility cannot be verified
unsigned-3.json: In JSON value ‘/tune_params/sve_width’
unsigned-3.json:3:18: error: key ‘tune_params.sve_width’ value 5000000000 is out of range for ‘uint’ type [0, 4294967295]
    3 |     "sve_width": 5000000000
      |                  ^~~~~~~~~~
cc1: error: validation failed for the provided JSON data

gcc/ChangeLog:
PR target/124094
* config/aarch64/aarch64-generate-json-tuning-routines.py
(generate_field_code): Add "ctxt, " arg to function call when
operation is "parse".
(generate_function): Add "gcc_json_context &ctxt, " param to
function decl when operation is "parse".
* config/aarch64/aarch64-json-tunings-parser-generated.inc:
Regenerate, passing around a gcc_json_context &.
* config/aarch64/aarch64-json-tunings-parser.cc: Include
"json-diagnostic.h".
(WARNING_OPT) New macro.
(PARSE_INTEGER_FIELD): Add "ctxt" param and pass it around.
(PARSE_UNSIGNED_INTEGER_FIELD): Likewise.
(PARSE_BOOLEAN_FIELD): Likewise.
(PARSE_STRING_FIELD): Likewise.
(PARSE_OBJECT): Likewise.
(PARSE_ARRAY_FIELD): Likewise.
(PARSE_ENUM_FIELD): Likewise.
(parse_func_type): Likewise.
(parse_object_helper): Likewise.  Use json_error rather than error.
(inform_about_wrong_kind_of_json_value): New.
(extract_string): Add "ctxt" param.  Replace "warning" with a pair
of calls to json_warning and
inform_about_wrong_kind_of_json_value, tweaking wording
accordingly.
(extract_integer): Likewise.
(extract_unsigned_integer): Likewise.
(parse_enum_field): Likewise.
(validate_and_traverse): Replace "warning" and "error" with
"json_warning" and "json_error".
(check_version_compatibility): Use WARNING_OPT.  Add
auto_diagnostic_group to group the error and note.
(aarch64_load_tuning_params_from_json_string): Add "js_filename"
param.  Use gcc_json_context to capture location info.  Use it
when reporting errors to get file/line/column info.  Replace check
on root being non-null with assertion, as this is guaranteed if
error is non-null.  Replace warning with json_warning.
(aarch64_load_tuning_params_from_json): Pass data_filename to
aarch64_load_tuning_params_from_json_string for use when reporting
diagnostics.
(selftest::test_json_integers): Add a placeholder filename.
(selftest::test_json_boolean): Likewise.
(selftest::test_json_strings): Likewise.
(selftest::test_json_enums): Likewise.

gcc/testsuite/ChangeLog:
PR target/124094
* gcc.target/aarch64/aarch64-json-tunings/boolean-2.c: Add options
-fdiagnostics-show-caret -fdiagnostics-show-line-numbers.  Replace
dg-error with a pair of dg-regexps to verify that we report the
filename and JSON Pointer of where the error occurs, and then
the filename and location within the JSON file.  Verify that we
quote and underline the pertinent part of the JSON file.
* gcc.target/aarch64/aarch64-json-tunings/empty-brackets.c: Likewise.
* gcc.target/aarch64/aarch64-json-tunings/enum-2.c: Likewise.
* gcc.target/aarch64/aarch64-json-tunings/integer-2.c: Likewise.
* gcc.target/aarch64/aarch64-json-tunings/integer-3.c: Likewise.
* gcc.target/aarch64/aarch64-json-tunings/string-2.c: Likewise.
* gcc.target/aarch64/aarch64-json-tunings/unidentified-key.c: Likewise.
* gcc.target/aarch64/aarch64-json-tunings/unsigned-2.c: Likewise.
* gcc.target/aarch64/aarch64-json-tunings/unsigned-3.c: Likewise.
* gcc.target/aarch64/aarch64-json-tunings/malformed.c: New test,
to verify behavior on a malformed JSON input file.
* gcc.target/aarch64/aarch64-json-tunings/malformed.json: New
test file.  This is malformed JSON, due to a missing ':" between
key and value.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
14 files changed:
gcc/config/aarch64/aarch64-generate-json-tuning-routines.py
gcc/config/aarch64/aarch64-json-tunings-parser-generated.inc
gcc/config/aarch64/aarch64-json-tunings-parser.cc
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/boolean-2.c
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/empty-brackets.c
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/enum-2.c
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/integer-2.c
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/integer-3.c
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/malformed.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/malformed.json [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/string-2.c
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/unidentified-key.c
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/unsigned-2.c
gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/unsigned-3.c

index a4f9e4ece71a3eefdfcb82c050f1ac5d99dcb20f..9253cf58cdfa1ad276fc7e2a5bb6570b2346115b 100755 (executable)
@@ -85,15 +85,20 @@ def generate_field_code(
 ) -> List[str]:
     lines = []
 
+    if operation == 'parse':
+        ctxt = 'ctxt, '
+    else:
+        ctxt = ''
+
     if isinstance(value, str):
         macro = get_macro(operation.upper(), value)
         if value == "enum":
             enum_mapping = f"{key}_mappings"
             lines.append(
-                f'{indent}{macro} ({obj_name}, "{key}", {struct_name}.{key}, {enum_mapping});'
+                f'{indent}{macro} ({ctxt}{obj_name}, "{key}", {struct_name}.{key}, {enum_mapping});'
             )
         else:
-            lines.append(f'{indent}{macro} ({obj_name}, "{key}", {struct_name}.{key});')
+            lines.append(f'{indent}{macro} ({ctxt}{obj_name}, "{key}", {struct_name}.{key});')
 
     elif isinstance(value, dict):
         # Nested object - find function name based on current context + key
@@ -102,7 +107,7 @@ def generate_field_code(
         func_name = function_map.get(child_path_key, f"{operation.lower()}_{key}")
         macro_name = f"{operation.upper()}_OBJECT"
         lines.append(
-            f'{indent}{macro_name} ({obj_name}, "{key}", {struct_name}.{key}, {func_name});'
+            f'{indent}{macro_name} ({ctxt}{obj_name}, "{key}", {struct_name}.{key}, {func_name});'
         )
 
     elif isinstance(value, list) and len(value) > 0:
@@ -117,11 +122,11 @@ def generate_field_code(
 
             if operation.lower() == "serialize":
                 lines.append(
-                    f'{indent}{macro_name} ({obj_name}, "{key}", {struct_name}.{key}, ARRAY_SIZE ({struct_name}.{key}), {func_name});'
+                    f'{indent}{macro_name} ({ctxt}{obj_name}, "{key}", {struct_name}.{key}, ARRAY_SIZE ({struct_name}.{key}), {func_name});'
                 )
             else:
                 lines.append(
-                    f'{indent}{macro_name} ({obj_name}, "{key}", {struct_name}.{key}, {func_name});'
+                    f'{indent}{macro_name} ({ctxt}{obj_name}, "{key}", {struct_name}.{key}, {func_name});'
                 )
         else:
             raise ValueError(f"Arrays of non-object types are not yet supported: {key}")
@@ -175,7 +180,7 @@ def generate_function(
 
     if operation.lower() == "parse":
         lines.append("static void")
-        lines.append(f"parse_{full_name} (const json::object *jo, T &{local_name})")
+        lines.append(f"parse_{full_name} (gcc_json_context &ctxt, const json::object &jo, T &{local_name})")
         lines.append("{")
 
         for key, value in schema.items():
index 7943dea6ececb36f48d084bd3f793bd5be2d7a82..1a615ac7d2036f0ccf32b2329e1e44a925b0eeff 100644 (file)
@@ -38,339 +38,339 @@ static const enum_mapping<aarch64_ldp_stp_policy> stp_policy_model_mappings[] =
 
 template <typename T>
 static void
-parse_insn_extra_cost_alu (const json::object *jo, T &alu)
+parse_insn_extra_cost_alu (gcc_json_context &ctxt, const json::object &jo, T &alu)
 {
-  PARSE_INTEGER_FIELD (jo, "arith", alu.arith);
-  PARSE_INTEGER_FIELD (jo, "logical", alu.logical);
-  PARSE_INTEGER_FIELD (jo, "shift", alu.shift);
-  PARSE_INTEGER_FIELD (jo, "shift_reg", alu.shift_reg);
-  PARSE_INTEGER_FIELD (jo, "arith_shift", alu.arith_shift);
-  PARSE_INTEGER_FIELD (jo, "arith_shift_reg", alu.arith_shift_reg);
-  PARSE_INTEGER_FIELD (jo, "log_shift", alu.log_shift);
-  PARSE_INTEGER_FIELD (jo, "log_shift_reg", alu.log_shift_reg);
-  PARSE_INTEGER_FIELD (jo, "extend", alu.extend);
-  PARSE_INTEGER_FIELD (jo, "extend_arith", alu.extend_arith);
-  PARSE_INTEGER_FIELD (jo, "bfi", alu.bfi);
-  PARSE_INTEGER_FIELD (jo, "bfx", alu.bfx);
-  PARSE_INTEGER_FIELD (jo, "clz", alu.clz);
-  PARSE_INTEGER_FIELD (jo, "rev", alu.rev);
-  PARSE_INTEGER_FIELD (jo, "non_exec", alu.non_exec);
-  PARSE_BOOLEAN_FIELD (jo, "non_exec_costs_exec", alu.non_exec_costs_exec);
+  PARSE_INTEGER_FIELD (ctxt, jo, "arith", alu.arith);
+  PARSE_INTEGER_FIELD (ctxt, jo, "logical", alu.logical);
+  PARSE_INTEGER_FIELD (ctxt, jo, "shift", alu.shift);
+  PARSE_INTEGER_FIELD (ctxt, jo, "shift_reg", alu.shift_reg);
+  PARSE_INTEGER_FIELD (ctxt, jo, "arith_shift", alu.arith_shift);
+  PARSE_INTEGER_FIELD (ctxt, jo, "arith_shift_reg", alu.arith_shift_reg);
+  PARSE_INTEGER_FIELD (ctxt, jo, "log_shift", alu.log_shift);
+  PARSE_INTEGER_FIELD (ctxt, jo, "log_shift_reg", alu.log_shift_reg);
+  PARSE_INTEGER_FIELD (ctxt, jo, "extend", alu.extend);
+  PARSE_INTEGER_FIELD (ctxt, jo, "extend_arith", alu.extend_arith);
+  PARSE_INTEGER_FIELD (ctxt, jo, "bfi", alu.bfi);
+  PARSE_INTEGER_FIELD (ctxt, jo, "bfx", alu.bfx);
+  PARSE_INTEGER_FIELD (ctxt, jo, "clz", alu.clz);
+  PARSE_INTEGER_FIELD (ctxt, jo, "rev", alu.rev);
+  PARSE_INTEGER_FIELD (ctxt, jo, "non_exec", alu.non_exec);
+  PARSE_BOOLEAN_FIELD (ctxt, jo, "non_exec_costs_exec", alu.non_exec_costs_exec);
 }
 
 template <typename T>
 static void
-parse_insn_extra_cost_mult_element (const json::object *jo, T &mult_element)
+parse_insn_extra_cost_mult_element (gcc_json_context &ctxt, const json::object &jo, T &mult_element)
 {
-  PARSE_INTEGER_FIELD (jo, "simple", mult_element.simple);
-  PARSE_INTEGER_FIELD (jo, "flag_setting", mult_element.flag_setting);
-  PARSE_INTEGER_FIELD (jo, "extend", mult_element.extend);
-  PARSE_INTEGER_FIELD (jo, "add", mult_element.add);
-  PARSE_INTEGER_FIELD (jo, "extend_add", mult_element.extend_add);
-  PARSE_INTEGER_FIELD (jo, "idiv", mult_element.idiv);
+  PARSE_INTEGER_FIELD (ctxt, jo, "simple", mult_element.simple);
+  PARSE_INTEGER_FIELD (ctxt, jo, "flag_setting", mult_element.flag_setting);
+  PARSE_INTEGER_FIELD (ctxt, jo, "extend", mult_element.extend);
+  PARSE_INTEGER_FIELD (ctxt, jo, "add", mult_element.add);
+  PARSE_INTEGER_FIELD (ctxt, jo, "extend_add", mult_element.extend_add);
+  PARSE_INTEGER_FIELD (ctxt, jo, "idiv", mult_element.idiv);
 }
 
 template <typename T>
 static void
-parse_insn_extra_cost_ldst (const json::object *jo, T &ldst)
+parse_insn_extra_cost_ldst (gcc_json_context &ctxt, const json::object &jo, T &ldst)
 {
-  PARSE_INTEGER_FIELD (jo, "load", ldst.load);
-  PARSE_INTEGER_FIELD (jo, "load_sign_extend", ldst.load_sign_extend);
-  PARSE_INTEGER_FIELD (jo, "ldrd", ldst.ldrd);
-  PARSE_INTEGER_FIELD (jo, "ldm_1st", ldst.ldm_1st);
-  PARSE_INTEGER_FIELD (jo, "ldm_regs_per_insn_1st", ldst.ldm_regs_per_insn_1st);
-  PARSE_INTEGER_FIELD (jo, "ldm_regs_per_insn_subsequent", ldst.ldm_regs_per_insn_subsequent);
-  PARSE_INTEGER_FIELD (jo, "loadf", ldst.loadf);
-  PARSE_INTEGER_FIELD (jo, "loadd", ldst.loadd);
-  PARSE_INTEGER_FIELD (jo, "load_unaligned", ldst.load_unaligned);
-  PARSE_INTEGER_FIELD (jo, "store", ldst.store);
-  PARSE_INTEGER_FIELD (jo, "strd", ldst.strd);
-  PARSE_INTEGER_FIELD (jo, "stm_1st", ldst.stm_1st);
-  PARSE_INTEGER_FIELD (jo, "stm_regs_per_insn_1st", ldst.stm_regs_per_insn_1st);
-  PARSE_INTEGER_FIELD (jo, "stm_regs_per_insn_subsequent", ldst.stm_regs_per_insn_subsequent);
-  PARSE_INTEGER_FIELD (jo, "storef", ldst.storef);
-  PARSE_INTEGER_FIELD (jo, "stored", ldst.stored);
-  PARSE_INTEGER_FIELD (jo, "store_unaligned", ldst.store_unaligned);
-  PARSE_INTEGER_FIELD (jo, "loadv", ldst.loadv);
-  PARSE_INTEGER_FIELD (jo, "storev", ldst.storev);
+  PARSE_INTEGER_FIELD (ctxt, jo, "load", ldst.load);
+  PARSE_INTEGER_FIELD (ctxt, jo, "load_sign_extend", ldst.load_sign_extend);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ldrd", ldst.ldrd);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ldm_1st", ldst.ldm_1st);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ldm_regs_per_insn_1st", ldst.ldm_regs_per_insn_1st);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ldm_regs_per_insn_subsequent", ldst.ldm_regs_per_insn_subsequent);
+  PARSE_INTEGER_FIELD (ctxt, jo, "loadf", ldst.loadf);
+  PARSE_INTEGER_FIELD (ctxt, jo, "loadd", ldst.loadd);
+  PARSE_INTEGER_FIELD (ctxt, jo, "load_unaligned", ldst.load_unaligned);
+  PARSE_INTEGER_FIELD (ctxt, jo, "store", ldst.store);
+  PARSE_INTEGER_FIELD (ctxt, jo, "strd", ldst.strd);
+  PARSE_INTEGER_FIELD (ctxt, jo, "stm_1st", ldst.stm_1st);
+  PARSE_INTEGER_FIELD (ctxt, jo, "stm_regs_per_insn_1st", ldst.stm_regs_per_insn_1st);
+  PARSE_INTEGER_FIELD (ctxt, jo, "stm_regs_per_insn_subsequent", ldst.stm_regs_per_insn_subsequent);
+  PARSE_INTEGER_FIELD (ctxt, jo, "storef", ldst.storef);
+  PARSE_INTEGER_FIELD (ctxt, jo, "stored", ldst.stored);
+  PARSE_INTEGER_FIELD (ctxt, jo, "store_unaligned", ldst.store_unaligned);
+  PARSE_INTEGER_FIELD (ctxt, jo, "loadv", ldst.loadv);
+  PARSE_INTEGER_FIELD (ctxt, jo, "storev", ldst.storev);
 }
 
 template <typename T>
 static void
-parse_insn_extra_cost_fp_element (const json::object *jo, T &fp_element)
+parse_insn_extra_cost_fp_element (gcc_json_context &ctxt, const json::object &jo, T &fp_element)
 {
-  PARSE_INTEGER_FIELD (jo, "div", fp_element.div);
-  PARSE_INTEGER_FIELD (jo, "mult", fp_element.mult);
-  PARSE_INTEGER_FIELD (jo, "mult_addsub", fp_element.mult_addsub);
-  PARSE_INTEGER_FIELD (jo, "fma", fp_element.fma);
-  PARSE_INTEGER_FIELD (jo, "addsub", fp_element.addsub);
-  PARSE_INTEGER_FIELD (jo, "fpconst", fp_element.fpconst);
-  PARSE_INTEGER_FIELD (jo, "neg", fp_element.neg);
-  PARSE_INTEGER_FIELD (jo, "compare", fp_element.compare);
-  PARSE_INTEGER_FIELD (jo, "widen", fp_element.widen);
-  PARSE_INTEGER_FIELD (jo, "narrow", fp_element.narrow);
-  PARSE_INTEGER_FIELD (jo, "toint", fp_element.toint);
-  PARSE_INTEGER_FIELD (jo, "fromint", fp_element.fromint);
-  PARSE_INTEGER_FIELD (jo, "roundint", fp_element.roundint);
+  PARSE_INTEGER_FIELD (ctxt, jo, "div", fp_element.div);
+  PARSE_INTEGER_FIELD (ctxt, jo, "mult", fp_element.mult);
+  PARSE_INTEGER_FIELD (ctxt, jo, "mult_addsub", fp_element.mult_addsub);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fma", fp_element.fma);
+  PARSE_INTEGER_FIELD (ctxt, jo, "addsub", fp_element.addsub);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fpconst", fp_element.fpconst);
+  PARSE_INTEGER_FIELD (ctxt, jo, "neg", fp_element.neg);
+  PARSE_INTEGER_FIELD (ctxt, jo, "compare", fp_element.compare);
+  PARSE_INTEGER_FIELD (ctxt, jo, "widen", fp_element.widen);
+  PARSE_INTEGER_FIELD (ctxt, jo, "narrow", fp_element.narrow);
+  PARSE_INTEGER_FIELD (ctxt, jo, "toint", fp_element.toint);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fromint", fp_element.fromint);
+  PARSE_INTEGER_FIELD (ctxt, jo, "roundint", fp_element.roundint);
 }
 
 template <typename T>
 static void
-parse_insn_extra_cost_vect (const json::object *jo, T &vect)
+parse_insn_extra_cost_vect (gcc_json_context &ctxt, const json::object &jo, T &vect)
 {
-  PARSE_INTEGER_FIELD (jo, "alu", vect.alu);
-  PARSE_INTEGER_FIELD (jo, "mult", vect.mult);
-  PARSE_INTEGER_FIELD (jo, "movi", vect.movi);
-  PARSE_INTEGER_FIELD (jo, "dup", vect.dup);
-  PARSE_INTEGER_FIELD (jo, "extract", vect.extract);
+  PARSE_INTEGER_FIELD (ctxt, jo, "alu", vect.alu);
+  PARSE_INTEGER_FIELD (ctxt, jo, "mult", vect.mult);
+  PARSE_INTEGER_FIELD (ctxt, jo, "movi", vect.movi);
+  PARSE_INTEGER_FIELD (ctxt, jo, "dup", vect.dup);
+  PARSE_INTEGER_FIELD (ctxt, jo, "extract", vect.extract);
 }
 
 template <typename T>
 static void
-parse_addr_cost_addr_scale_costs (const json::object *jo, T &addr_scale_costs)
+parse_addr_cost_addr_scale_costs (gcc_json_context &ctxt, const json::object &jo, T &addr_scale_costs)
 {
-  PARSE_INTEGER_FIELD (jo, "hi", addr_scale_costs.hi);
-  PARSE_INTEGER_FIELD (jo, "si", addr_scale_costs.si);
-  PARSE_INTEGER_FIELD (jo, "di", addr_scale_costs.di);
-  PARSE_INTEGER_FIELD (jo, "ti", addr_scale_costs.ti);
+  PARSE_INTEGER_FIELD (ctxt, jo, "hi", addr_scale_costs.hi);
+  PARSE_INTEGER_FIELD (ctxt, jo, "si", addr_scale_costs.si);
+  PARSE_INTEGER_FIELD (ctxt, jo, "di", addr_scale_costs.di);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ti", addr_scale_costs.ti);
 }
 
 template <typename T>
 static void
-parse_regmove_cost (const json::object *jo, T &regmove_cost)
+parse_regmove_cost (gcc_json_context &ctxt, const json::object &jo, T &regmove_cost)
 {
-  PARSE_INTEGER_FIELD (jo, "GP2GP", regmove_cost.GP2GP);
-  PARSE_INTEGER_FIELD (jo, "GP2FP", regmove_cost.GP2FP);
-  PARSE_INTEGER_FIELD (jo, "FP2GP", regmove_cost.FP2GP);
-  PARSE_INTEGER_FIELD (jo, "FP2FP", regmove_cost.FP2FP);
+  PARSE_INTEGER_FIELD (ctxt, jo, "GP2GP", regmove_cost.GP2GP);
+  PARSE_INTEGER_FIELD (ctxt, jo, "GP2FP", regmove_cost.GP2FP);
+  PARSE_INTEGER_FIELD (ctxt, jo, "FP2GP", regmove_cost.FP2GP);
+  PARSE_INTEGER_FIELD (ctxt, jo, "FP2FP", regmove_cost.FP2FP);
 }
 
 template <typename T>
 static void
-parse_vec_costs_advsimd (const json::object *jo, T &advsimd)
+parse_vec_costs_advsimd (gcc_json_context &ctxt, const json::object &jo, T &advsimd)
 {
-  PARSE_INTEGER_FIELD (jo, "int_stmt_cost", advsimd.int_stmt_cost);
-  PARSE_INTEGER_FIELD (jo, "fp_stmt_cost", advsimd.fp_stmt_cost);
-  PARSE_INTEGER_FIELD (jo, "ld2_st2_permute_cost", advsimd.ld2_st2_permute_cost);
-  PARSE_INTEGER_FIELD (jo, "ld3_st3_permute_cost", advsimd.ld3_st3_permute_cost);
-  PARSE_INTEGER_FIELD (jo, "ld4_st4_permute_cost", advsimd.ld4_st4_permute_cost);
-  PARSE_INTEGER_FIELD (jo, "permute_cost", advsimd.permute_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_i8_cost", advsimd.reduc_i8_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_i16_cost", advsimd.reduc_i16_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_i32_cost", advsimd.reduc_i32_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_i64_cost", advsimd.reduc_i64_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_f16_cost", advsimd.reduc_f16_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_f32_cost", advsimd.reduc_f32_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_f64_cost", advsimd.reduc_f64_cost);
-  PARSE_INTEGER_FIELD (jo, "store_elt_extra_cost", advsimd.store_elt_extra_cost);
-  PARSE_INTEGER_FIELD (jo, "vec_to_scalar_cost", advsimd.vec_to_scalar_cost);
-  PARSE_INTEGER_FIELD (jo, "scalar_to_vec_cost", advsimd.scalar_to_vec_cost);
-  PARSE_INTEGER_FIELD (jo, "align_load_cost", advsimd.align_load_cost);
-  PARSE_INTEGER_FIELD (jo, "unalign_load_cost", advsimd.unalign_load_cost);
-  PARSE_INTEGER_FIELD (jo, "unalign_store_cost", advsimd.unalign_store_cost);
-  PARSE_INTEGER_FIELD (jo, "store_cost", advsimd.store_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "int_stmt_cost", advsimd.int_stmt_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fp_stmt_cost", advsimd.fp_stmt_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ld2_st2_permute_cost", advsimd.ld2_st2_permute_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ld3_st3_permute_cost", advsimd.ld3_st3_permute_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ld4_st4_permute_cost", advsimd.ld4_st4_permute_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "permute_cost", advsimd.permute_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_i8_cost", advsimd.reduc_i8_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_i16_cost", advsimd.reduc_i16_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_i32_cost", advsimd.reduc_i32_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_i64_cost", advsimd.reduc_i64_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_f16_cost", advsimd.reduc_f16_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_f32_cost", advsimd.reduc_f32_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_f64_cost", advsimd.reduc_f64_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "store_elt_extra_cost", advsimd.store_elt_extra_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "vec_to_scalar_cost", advsimd.vec_to_scalar_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "scalar_to_vec_cost", advsimd.scalar_to_vec_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "align_load_cost", advsimd.align_load_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "unalign_load_cost", advsimd.unalign_load_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "unalign_store_cost", advsimd.unalign_store_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "store_cost", advsimd.store_cost);
 }
 
 template <typename T>
 static void
-parse_vec_costs_sve (const json::object *jo, T &sve)
+parse_vec_costs_sve (gcc_json_context &ctxt, const json::object &jo, T &sve)
 {
-  PARSE_INTEGER_FIELD (jo, "int_stmt_cost", sve.int_stmt_cost);
-  PARSE_INTEGER_FIELD (jo, "fp_stmt_cost", sve.fp_stmt_cost);
-  PARSE_INTEGER_FIELD (jo, "ld2_st2_permute_cost", sve.ld2_st2_permute_cost);
-  PARSE_INTEGER_FIELD (jo, "ld3_st3_permute_cost", sve.ld3_st3_permute_cost);
-  PARSE_INTEGER_FIELD (jo, "ld4_st4_permute_cost", sve.ld4_st4_permute_cost);
-  PARSE_INTEGER_FIELD (jo, "permute_cost", sve.permute_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_i8_cost", sve.reduc_i8_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_i16_cost", sve.reduc_i16_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_i32_cost", sve.reduc_i32_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_i64_cost", sve.reduc_i64_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_f16_cost", sve.reduc_f16_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_f32_cost", sve.reduc_f32_cost);
-  PARSE_INTEGER_FIELD (jo, "reduc_f64_cost", sve.reduc_f64_cost);
-  PARSE_INTEGER_FIELD (jo, "store_elt_extra_cost", sve.store_elt_extra_cost);
-  PARSE_INTEGER_FIELD (jo, "vec_to_scalar_cost", sve.vec_to_scalar_cost);
-  PARSE_INTEGER_FIELD (jo, "scalar_to_vec_cost", sve.scalar_to_vec_cost);
-  PARSE_INTEGER_FIELD (jo, "align_load_cost", sve.align_load_cost);
-  PARSE_INTEGER_FIELD (jo, "unalign_load_cost", sve.unalign_load_cost);
-  PARSE_INTEGER_FIELD (jo, "unalign_store_cost", sve.unalign_store_cost);
-  PARSE_INTEGER_FIELD (jo, "store_cost", sve.store_cost);
-  PARSE_INTEGER_FIELD (jo, "clast_cost", sve.clast_cost);
-  PARSE_INTEGER_FIELD (jo, "fadda_f16_cost", sve.fadda_f16_cost);
-  PARSE_INTEGER_FIELD (jo, "fadda_f32_cost", sve.fadda_f32_cost);
-  PARSE_INTEGER_FIELD (jo, "fadda_f64_cost", sve.fadda_f64_cost);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "gather_load_x32_cost", sve.gather_load_x32_cost);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "gather_load_x64_cost", sve.gather_load_x64_cost);
-  PARSE_INTEGER_FIELD (jo, "gather_load_x32_init_cost", sve.gather_load_x32_init_cost);
-  PARSE_INTEGER_FIELD (jo, "gather_load_x64_init_cost", sve.gather_load_x64_init_cost);
-  PARSE_INTEGER_FIELD (jo, "scatter_store_elt_cost", sve.scatter_store_elt_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "int_stmt_cost", sve.int_stmt_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fp_stmt_cost", sve.fp_stmt_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ld2_st2_permute_cost", sve.ld2_st2_permute_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ld3_st3_permute_cost", sve.ld3_st3_permute_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "ld4_st4_permute_cost", sve.ld4_st4_permute_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "permute_cost", sve.permute_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_i8_cost", sve.reduc_i8_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_i16_cost", sve.reduc_i16_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_i32_cost", sve.reduc_i32_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_i64_cost", sve.reduc_i64_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_f16_cost", sve.reduc_f16_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_f32_cost", sve.reduc_f32_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "reduc_f64_cost", sve.reduc_f64_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "store_elt_extra_cost", sve.store_elt_extra_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "vec_to_scalar_cost", sve.vec_to_scalar_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "scalar_to_vec_cost", sve.scalar_to_vec_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "align_load_cost", sve.align_load_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "unalign_load_cost", sve.unalign_load_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "unalign_store_cost", sve.unalign_store_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "store_cost", sve.store_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "clast_cost", sve.clast_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fadda_f16_cost", sve.fadda_f16_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fadda_f32_cost", sve.fadda_f32_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fadda_f64_cost", sve.fadda_f64_cost);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "gather_load_x32_cost", sve.gather_load_x32_cost);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "gather_load_x64_cost", sve.gather_load_x64_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "gather_load_x32_init_cost", sve.gather_load_x32_init_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "gather_load_x64_init_cost", sve.gather_load_x64_init_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "scatter_store_elt_cost", sve.scatter_store_elt_cost);
 }
 
 template <typename T>
 static void
-parse_vec_costs_issue_info_scalar (const json::object *jo, T &scalar)
+parse_vec_costs_issue_info_scalar (gcc_json_context &ctxt, const json::object &jo, T &scalar)
 {
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "loads_stores_per_cycle", scalar.loads_stores_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "stores_per_cycle", scalar.stores_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "general_ops_per_cycle", scalar.general_ops_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "fp_simd_load_general_ops", scalar.fp_simd_load_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "fp_simd_store_general_ops", scalar.fp_simd_store_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "loads_stores_per_cycle", scalar.loads_stores_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "stores_per_cycle", scalar.stores_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "general_ops_per_cycle", scalar.general_ops_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "fp_simd_load_general_ops", scalar.fp_simd_load_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "fp_simd_store_general_ops", scalar.fp_simd_store_general_ops);
 }
 
 template <typename T>
 static void
-parse_vec_costs_issue_info_advsimd (const json::object *jo, T &advsimd)
+parse_vec_costs_issue_info_advsimd (gcc_json_context &ctxt, const json::object &jo, T &advsimd)
 {
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "loads_stores_per_cycle", advsimd.loads_stores_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "stores_per_cycle", advsimd.stores_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "general_ops_per_cycle", advsimd.general_ops_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "fp_simd_load_general_ops", advsimd.fp_simd_load_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "fp_simd_store_general_ops", advsimd.fp_simd_store_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "ld2_st2_general_ops", advsimd.ld2_st2_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "ld3_st3_general_ops", advsimd.ld3_st3_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "ld4_st4_general_ops", advsimd.ld4_st4_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "loads_stores_per_cycle", advsimd.loads_stores_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "stores_per_cycle", advsimd.stores_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "general_ops_per_cycle", advsimd.general_ops_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "fp_simd_load_general_ops", advsimd.fp_simd_load_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "fp_simd_store_general_ops", advsimd.fp_simd_store_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "ld2_st2_general_ops", advsimd.ld2_st2_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "ld3_st3_general_ops", advsimd.ld3_st3_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "ld4_st4_general_ops", advsimd.ld4_st4_general_ops);
 }
 
 template <typename T>
 static void
-parse_vec_costs_issue_info_sve (const json::object *jo, T &sve)
+parse_vec_costs_issue_info_sve (gcc_json_context &ctxt, const json::object &jo, T &sve)
 {
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "loads_stores_per_cycle", sve.loads_stores_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "stores_per_cycle", sve.stores_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "general_ops_per_cycle", sve.general_ops_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "fp_simd_load_general_ops", sve.fp_simd_load_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "fp_simd_store_general_ops", sve.fp_simd_store_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "ld2_st2_general_ops", sve.ld2_st2_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "ld3_st3_general_ops", sve.ld3_st3_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "ld4_st4_general_ops", sve.ld4_st4_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "pred_ops_per_cycle", sve.pred_ops_per_cycle);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "while_pred_ops", sve.while_pred_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "int_cmp_pred_ops", sve.int_cmp_pred_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "fp_cmp_pred_ops", sve.fp_cmp_pred_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "gather_scatter_pair_general_ops", sve.gather_scatter_pair_general_ops);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "gather_scatter_pair_pred_ops", sve.gather_scatter_pair_pred_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "loads_stores_per_cycle", sve.loads_stores_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "stores_per_cycle", sve.stores_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "general_ops_per_cycle", sve.general_ops_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "fp_simd_load_general_ops", sve.fp_simd_load_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "fp_simd_store_general_ops", sve.fp_simd_store_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "ld2_st2_general_ops", sve.ld2_st2_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "ld3_st3_general_ops", sve.ld3_st3_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "ld4_st4_general_ops", sve.ld4_st4_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "pred_ops_per_cycle", sve.pred_ops_per_cycle);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "while_pred_ops", sve.while_pred_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "int_cmp_pred_ops", sve.int_cmp_pred_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "fp_cmp_pred_ops", sve.fp_cmp_pred_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "gather_scatter_pair_general_ops", sve.gather_scatter_pair_general_ops);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "gather_scatter_pair_pred_ops", sve.gather_scatter_pair_pred_ops);
 }
 
 template <typename T>
 static void
-parse_branch_costs (const json::object *jo, T &branch_costs)
+parse_branch_costs (gcc_json_context &ctxt, const json::object &jo, T &branch_costs)
 {
-  PARSE_INTEGER_FIELD (jo, "predictable", branch_costs.predictable);
-  PARSE_INTEGER_FIELD (jo, "unpredictable", branch_costs.unpredictable);
-  PARSE_INTEGER_FIELD (jo, "br_mispredict_factor", branch_costs.br_mispredict_factor);
+  PARSE_INTEGER_FIELD (ctxt, jo, "predictable", branch_costs.predictable);
+  PARSE_INTEGER_FIELD (ctxt, jo, "unpredictable", branch_costs.unpredictable);
+  PARSE_INTEGER_FIELD (ctxt, jo, "br_mispredict_factor", branch_costs.br_mispredict_factor);
 }
 
 template <typename T>
 static void
-parse_approx_modes (const json::object *jo, T &approx_modes)
+parse_approx_modes (gcc_json_context &ctxt, const json::object &jo, T &approx_modes)
 {
-  PARSE_INTEGER_FIELD (jo, "division", approx_modes.division);
-  PARSE_INTEGER_FIELD (jo, "sqrt", approx_modes.sqrt);
-  PARSE_INTEGER_FIELD (jo, "recip_sqrt", approx_modes.recip_sqrt);
+  PARSE_INTEGER_FIELD (ctxt, jo, "division", approx_modes.division);
+  PARSE_INTEGER_FIELD (ctxt, jo, "sqrt", approx_modes.sqrt);
+  PARSE_INTEGER_FIELD (ctxt, jo, "recip_sqrt", approx_modes.recip_sqrt);
 }
 
 template <typename T>
 static void
-parse_memmov_cost (const json::object *jo, T &memmov_cost)
+parse_memmov_cost (gcc_json_context &ctxt, const json::object &jo, T &memmov_cost)
 {
-  PARSE_INTEGER_FIELD (jo, "load_int", memmov_cost.load_int);
-  PARSE_INTEGER_FIELD (jo, "store_int", memmov_cost.store_int);
-  PARSE_INTEGER_FIELD (jo, "load_fp", memmov_cost.load_fp);
-  PARSE_INTEGER_FIELD (jo, "store_fp", memmov_cost.store_fp);
-  PARSE_INTEGER_FIELD (jo, "load_pred", memmov_cost.load_pred);
-  PARSE_INTEGER_FIELD (jo, "store_pred", memmov_cost.store_pred);
+  PARSE_INTEGER_FIELD (ctxt, jo, "load_int", memmov_cost.load_int);
+  PARSE_INTEGER_FIELD (ctxt, jo, "store_int", memmov_cost.store_int);
+  PARSE_INTEGER_FIELD (ctxt, jo, "load_fp", memmov_cost.load_fp);
+  PARSE_INTEGER_FIELD (ctxt, jo, "store_fp", memmov_cost.store_fp);
+  PARSE_INTEGER_FIELD (ctxt, jo, "load_pred", memmov_cost.load_pred);
+  PARSE_INTEGER_FIELD (ctxt, jo, "store_pred", memmov_cost.store_pred);
 }
 
 template <typename T>
 static void
-parse_prefetch (const json::object *jo, T &prefetch)
+parse_prefetch (gcc_json_context &ctxt, const json::object &jo, T &prefetch)
 {
-  PARSE_INTEGER_FIELD (jo, "num_slots", prefetch.num_slots);
-  PARSE_INTEGER_FIELD (jo, "l1_cache_size", prefetch.l1_cache_size);
-  PARSE_INTEGER_FIELD (jo, "l1_cache_line_size", prefetch.l1_cache_line_size);
-  PARSE_INTEGER_FIELD (jo, "l2_cache_size", prefetch.l2_cache_size);
-  PARSE_BOOLEAN_FIELD (jo, "prefetch_dynamic_strides", prefetch.prefetch_dynamic_strides);
-  PARSE_INTEGER_FIELD (jo, "minimum_stride", prefetch.minimum_stride);
-  PARSE_INTEGER_FIELD (jo, "default_opt_level", prefetch.default_opt_level);
+  PARSE_INTEGER_FIELD (ctxt, jo, "num_slots", prefetch.num_slots);
+  PARSE_INTEGER_FIELD (ctxt, jo, "l1_cache_size", prefetch.l1_cache_size);
+  PARSE_INTEGER_FIELD (ctxt, jo, "l1_cache_line_size", prefetch.l1_cache_line_size);
+  PARSE_INTEGER_FIELD (ctxt, jo, "l2_cache_size", prefetch.l2_cache_size);
+  PARSE_BOOLEAN_FIELD (ctxt, jo, "prefetch_dynamic_strides", prefetch.prefetch_dynamic_strides);
+  PARSE_INTEGER_FIELD (ctxt, jo, "minimum_stride", prefetch.minimum_stride);
+  PARSE_INTEGER_FIELD (ctxt, jo, "default_opt_level", prefetch.default_opt_level);
 }
 
 template <typename T>
 static void
-parse_insn_extra_cost (const json::object *jo, T &insn_extra_cost)
+parse_insn_extra_cost (gcc_json_context &ctxt, const json::object &jo, T &insn_extra_cost)
 {
-  PARSE_OBJECT (jo, "alu", insn_extra_cost.alu, parse_insn_extra_cost_alu);
-  PARSE_ARRAY_FIELD (jo, "mult", insn_extra_cost.mult, parse_insn_extra_cost_mult_element);
-  PARSE_OBJECT (jo, "ldst", insn_extra_cost.ldst, parse_insn_extra_cost_ldst);
-  PARSE_ARRAY_FIELD (jo, "fp", insn_extra_cost.fp, parse_insn_extra_cost_fp_element);
-  PARSE_OBJECT (jo, "vect", insn_extra_cost.vect, parse_insn_extra_cost_vect);
+  PARSE_OBJECT (ctxt, jo, "alu", insn_extra_cost.alu, parse_insn_extra_cost_alu);
+  PARSE_ARRAY_FIELD (ctxt, jo, "mult", insn_extra_cost.mult, parse_insn_extra_cost_mult_element);
+  PARSE_OBJECT (ctxt, jo, "ldst", insn_extra_cost.ldst, parse_insn_extra_cost_ldst);
+  PARSE_ARRAY_FIELD (ctxt, jo, "fp", insn_extra_cost.fp, parse_insn_extra_cost_fp_element);
+  PARSE_OBJECT (ctxt, jo, "vect", insn_extra_cost.vect, parse_insn_extra_cost_vect);
 }
 
 template <typename T>
 static void
-parse_addr_cost (const json::object *jo, T &addr_cost)
+parse_addr_cost (gcc_json_context &ctxt, const json::object &jo, T &addr_cost)
 {
-  PARSE_OBJECT (jo, "addr_scale_costs", addr_cost.addr_scale_costs, parse_addr_cost_addr_scale_costs);
-  PARSE_INTEGER_FIELD (jo, "pre_modify", addr_cost.pre_modify);
-  PARSE_INTEGER_FIELD (jo, "post_modify", addr_cost.post_modify);
-  PARSE_INTEGER_FIELD (jo, "post_modify_ld3_st3", addr_cost.post_modify_ld3_st3);
-  PARSE_INTEGER_FIELD (jo, "post_modify_ld4_st4", addr_cost.post_modify_ld4_st4);
-  PARSE_INTEGER_FIELD (jo, "register_offset", addr_cost.register_offset);
-  PARSE_INTEGER_FIELD (jo, "register_sextend", addr_cost.register_sextend);
-  PARSE_INTEGER_FIELD (jo, "register_zextend", addr_cost.register_zextend);
-  PARSE_INTEGER_FIELD (jo, "imm_offset", addr_cost.imm_offset);
+  PARSE_OBJECT (ctxt, jo, "addr_scale_costs", addr_cost.addr_scale_costs, parse_addr_cost_addr_scale_costs);
+  PARSE_INTEGER_FIELD (ctxt, jo, "pre_modify", addr_cost.pre_modify);
+  PARSE_INTEGER_FIELD (ctxt, jo, "post_modify", addr_cost.post_modify);
+  PARSE_INTEGER_FIELD (ctxt, jo, "post_modify_ld3_st3", addr_cost.post_modify_ld3_st3);
+  PARSE_INTEGER_FIELD (ctxt, jo, "post_modify_ld4_st4", addr_cost.post_modify_ld4_st4);
+  PARSE_INTEGER_FIELD (ctxt, jo, "register_offset", addr_cost.register_offset);
+  PARSE_INTEGER_FIELD (ctxt, jo, "register_sextend", addr_cost.register_sextend);
+  PARSE_INTEGER_FIELD (ctxt, jo, "register_zextend", addr_cost.register_zextend);
+  PARSE_INTEGER_FIELD (ctxt, jo, "imm_offset", addr_cost.imm_offset);
 }
 
 template <typename T>
 static void
-parse_vec_costs_issue_info (const json::object *jo, T &issue_info)
+parse_vec_costs_issue_info (gcc_json_context &ctxt, const json::object &jo, T &issue_info)
 {
-  PARSE_OBJECT (jo, "scalar", issue_info.scalar, parse_vec_costs_issue_info_scalar);
-  PARSE_OBJECT (jo, "advsimd", issue_info.advsimd, parse_vec_costs_issue_info_advsimd);
-  PARSE_OBJECT (jo, "sve", issue_info.sve, parse_vec_costs_issue_info_sve);
+  PARSE_OBJECT (ctxt, jo, "scalar", issue_info.scalar, parse_vec_costs_issue_info_scalar);
+  PARSE_OBJECT (ctxt, jo, "advsimd", issue_info.advsimd, parse_vec_costs_issue_info_advsimd);
+  PARSE_OBJECT (ctxt, jo, "sve", issue_info.sve, parse_vec_costs_issue_info_sve);
 }
 
 template <typename T>
 static void
-parse_vec_costs (const json::object *jo, T &vec_costs)
+parse_vec_costs (gcc_json_context &ctxt, const json::object &jo, T &vec_costs)
 {
-  PARSE_INTEGER_FIELD (jo, "scalar_int_stmt_cost", vec_costs.scalar_int_stmt_cost);
-  PARSE_INTEGER_FIELD (jo, "scalar_fp_stmt_cost", vec_costs.scalar_fp_stmt_cost);
-  PARSE_INTEGER_FIELD (jo, "scalar_load_cost", vec_costs.scalar_load_cost);
-  PARSE_INTEGER_FIELD (jo, "scalar_store_cost", vec_costs.scalar_store_cost);
-  PARSE_INTEGER_FIELD (jo, "cond_taken_branch_cost", vec_costs.cond_taken_branch_cost);
-  PARSE_INTEGER_FIELD (jo, "cond_not_taken_branch_cost", vec_costs.cond_not_taken_branch_cost);
-  PARSE_OBJECT (jo, "advsimd", vec_costs.advsimd, parse_vec_costs_advsimd);
-  PARSE_OBJECT (jo, "sve", vec_costs.sve, parse_vec_costs_sve);
-  PARSE_OBJECT (jo, "issue_info", vec_costs.issue_info, parse_vec_costs_issue_info);
+  PARSE_INTEGER_FIELD (ctxt, jo, "scalar_int_stmt_cost", vec_costs.scalar_int_stmt_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "scalar_fp_stmt_cost", vec_costs.scalar_fp_stmt_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "scalar_load_cost", vec_costs.scalar_load_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "scalar_store_cost", vec_costs.scalar_store_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "cond_taken_branch_cost", vec_costs.cond_taken_branch_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "cond_not_taken_branch_cost", vec_costs.cond_not_taken_branch_cost);
+  PARSE_OBJECT (ctxt, jo, "advsimd", vec_costs.advsimd, parse_vec_costs_advsimd);
+  PARSE_OBJECT (ctxt, jo, "sve", vec_costs.sve, parse_vec_costs_sve);
+  PARSE_OBJECT (ctxt, jo, "issue_info", vec_costs.issue_info, parse_vec_costs_issue_info);
 }
 
 template <typename T>
 static void
-parse_tunings (const json::object *jo, T &tunings)
+parse_tunings (gcc_json_context &ctxt, const json::object &jo, T &tunings)
 {
-  PARSE_OBJECT (jo, "insn_extra_cost", tunings.insn_extra_cost, parse_insn_extra_cost);
-  PARSE_OBJECT (jo, "addr_cost", tunings.addr_cost, parse_addr_cost);
-  PARSE_OBJECT (jo, "regmove_cost", tunings.regmove_cost, parse_regmove_cost);
-  PARSE_OBJECT (jo, "vec_costs", tunings.vec_costs, parse_vec_costs);
-  PARSE_OBJECT (jo, "branch_costs", tunings.branch_costs, parse_branch_costs);
-  PARSE_OBJECT (jo, "approx_modes", tunings.approx_modes, parse_approx_modes);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "sve_width", tunings.sve_width);
-  PARSE_OBJECT (jo, "memmov_cost", tunings.memmov_cost, parse_memmov_cost);
-  PARSE_INTEGER_FIELD (jo, "issue_rate", tunings.issue_rate);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "fusible_ops", tunings.fusible_ops);
-  PARSE_STRING_FIELD (jo, "function_align", tunings.function_align);
-  PARSE_STRING_FIELD (jo, "jump_align", tunings.jump_align);
-  PARSE_STRING_FIELD (jo, "loop_align", tunings.loop_align);
-  PARSE_INTEGER_FIELD (jo, "int_reassoc_width", tunings.int_reassoc_width);
-  PARSE_INTEGER_FIELD (jo, "fp_reassoc_width", tunings.fp_reassoc_width);
-  PARSE_INTEGER_FIELD (jo, "fma_reassoc_width", tunings.fma_reassoc_width);
-  PARSE_INTEGER_FIELD (jo, "vec_reassoc_width", tunings.vec_reassoc_width);
-  PARSE_INTEGER_FIELD (jo, "min_div_recip_mul_sf", tunings.min_div_recip_mul_sf);
-  PARSE_INTEGER_FIELD (jo, "min_div_recip_mul_df", tunings.min_div_recip_mul_df);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "max_case_values", tunings.max_case_values);
-  PARSE_ENUM_FIELD (jo, "autoprefetcher_model", tunings.autoprefetcher_model, autoprefetcher_model_mappings);
-  PARSE_UNSIGNED_INTEGER_FIELD (jo, "extra_tuning_flags", tunings.extra_tuning_flags);
-  PARSE_OBJECT (jo, "prefetch", tunings.prefetch, parse_prefetch);
-  PARSE_ENUM_FIELD (jo, "ldp_policy_model", tunings.ldp_policy_model, ldp_policy_model_mappings);
-  PARSE_ENUM_FIELD (jo, "stp_policy_model", tunings.stp_policy_model, stp_policy_model_mappings);
+  PARSE_OBJECT (ctxt, jo, "insn_extra_cost", tunings.insn_extra_cost, parse_insn_extra_cost);
+  PARSE_OBJECT (ctxt, jo, "addr_cost", tunings.addr_cost, parse_addr_cost);
+  PARSE_OBJECT (ctxt, jo, "regmove_cost", tunings.regmove_cost, parse_regmove_cost);
+  PARSE_OBJECT (ctxt, jo, "vec_costs", tunings.vec_costs, parse_vec_costs);
+  PARSE_OBJECT (ctxt, jo, "branch_costs", tunings.branch_costs, parse_branch_costs);
+  PARSE_OBJECT (ctxt, jo, "approx_modes", tunings.approx_modes, parse_approx_modes);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "sve_width", tunings.sve_width);
+  PARSE_OBJECT (ctxt, jo, "memmov_cost", tunings.memmov_cost, parse_memmov_cost);
+  PARSE_INTEGER_FIELD (ctxt, jo, "issue_rate", tunings.issue_rate);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "fusible_ops", tunings.fusible_ops);
+  PARSE_STRING_FIELD (ctxt, jo, "function_align", tunings.function_align);
+  PARSE_STRING_FIELD (ctxt, jo, "jump_align", tunings.jump_align);
+  PARSE_STRING_FIELD (ctxt, jo, "loop_align", tunings.loop_align);
+  PARSE_INTEGER_FIELD (ctxt, jo, "int_reassoc_width", tunings.int_reassoc_width);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fp_reassoc_width", tunings.fp_reassoc_width);
+  PARSE_INTEGER_FIELD (ctxt, jo, "fma_reassoc_width", tunings.fma_reassoc_width);
+  PARSE_INTEGER_FIELD (ctxt, jo, "vec_reassoc_width", tunings.vec_reassoc_width);
+  PARSE_INTEGER_FIELD (ctxt, jo, "min_div_recip_mul_sf", tunings.min_div_recip_mul_sf);
+  PARSE_INTEGER_FIELD (ctxt, jo, "min_div_recip_mul_df", tunings.min_div_recip_mul_df);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "max_case_values", tunings.max_case_values);
+  PARSE_ENUM_FIELD (ctxt, jo, "autoprefetcher_model", tunings.autoprefetcher_model, autoprefetcher_model_mappings);
+  PARSE_UNSIGNED_INTEGER_FIELD (ctxt, jo, "extra_tuning_flags", tunings.extra_tuning_flags);
+  PARSE_OBJECT (ctxt, jo, "prefetch", tunings.prefetch, parse_prefetch);
+  PARSE_ENUM_FIELD (ctxt, jo, "ldp_policy_model", tunings.ldp_policy_model, ldp_policy_model_mappings);
+  PARSE_ENUM_FIELD (ctxt, jo, "stp_policy_model", tunings.stp_policy_model, stp_policy_model_mappings);
 }
\ No newline at end of file
index afad1a6517014fe798a2fd96f15a6faa1f8ee8bd..b2cfcfd3c028dddf5d58af906c2cd5bc9b762130 100644 (file)
@@ -27,6 +27,7 @@
 #include "tm.h"
 #include "diagnostic-core.h"
 #include "json-parsing.h"
+#include "json-diagnostic.h"
 #include "aarch64-json-schema.h"
 #include "aarch64-json-tunings-parser.h"
 #include "aarch64-protos.h"
 #include "selftest.h"
 #include "version.h"
 
-#define PARSE_INTEGER_FIELD(obj, key, member)                                  \
+#define WARNING_OPT (0)
+
+#define PARSE_INTEGER_FIELD(ctxt, obj, key, member)                            \
   {                                                                            \
-    const json::value *val = obj->get (key);                                   \
+    const json::value *val = obj.get (key);                                    \
     if (val)                                                                   \
-      member = extract_integer (val);                                          \
+      member = extract_integer (ctxt, *val, WARNING_OPT);                      \
   }
 
-#define PARSE_UNSIGNED_INTEGER_FIELD(obj, key, member)                         \
+#define PARSE_UNSIGNED_INTEGER_FIELD(ctxt, obj, key, member)                   \
   {                                                                            \
-    const json::value *val = obj->get (key);                                   \
+    const json::value *val = obj.get (key);                                    \
     if (val)                                                                   \
-      member = extract_unsigned_integer (val);                                 \
+      member = extract_unsigned_integer (ctxt, *val, WARNING_OPT);             \
   }
 
-#define PARSE_BOOLEAN_FIELD(obj, key, member)                                  \
+#define PARSE_BOOLEAN_FIELD(ctxt, obj, key, member)                             \
   {                                                                            \
-    const json::value *val = obj->get (key);                                   \
+    const json::value *val = obj.get (key);                                    \
     if (val)                                                                   \
-      member = extract_boolean (val);                                          \
+      member = extract_boolean (ctxt, *val, WARNING_OPT);                      \
   }
 
-#define PARSE_STRING_FIELD(obj, key, member)                                   \
+#define PARSE_STRING_FIELD(ctxt, obj, key, member)                             \
   {                                                                            \
-    const json::value *val = obj->get (key);                                   \
+    const json::value *val = obj.get (key);                                    \
     if (val)                                                                   \
-      member = extract_string (val);                                           \
+      member = extract_string (ctxt, *val, WARNING_OPT);                       \
   }
 
-#define PARSE_OBJECT(obj, key, member, parse_func)                             \
+#define PARSE_OBJECT(ctxt, obj, key, member, parse_func)                       \
   {                                                                            \
-    const json::value *field_value = obj->get (key);                           \
+    const json::value *field_value = obj.get (key);                            \
     if (field_value)                                                           \
       if (auto *field_obj = dyn_cast<const json::object *> (field_value))      \
-       parse_object_helper (field_obj, (member), (parse_func));               \
+       parse_object_helper (ctxt, *field_obj, (member), (parse_func));        \
   }
 
-#define PARSE_ARRAY_FIELD(obj, key, member, parse_func)                        \
+#define PARSE_ARRAY_FIELD(ctxt, obj, key, member, parse_func)                  \
   {                                                                            \
-    const json::value *field_value = obj->get (key);                           \
+    const json::value *field_value = obj.get (key);                            \
     if (field_value)                                                           \
       if (auto *field_array = dyn_cast<const json::array *> (field_value))     \
        for (size_t i = 0; i < field_array->size (); ++i)                      \
            const json::value *elem = field_array->get (i);                    \
            if (elem)                                                          \
              if (auto *array_obj = dyn_cast<const json::object *> (elem))     \
-               parse_func (array_obj, member[i]);                             \
+               parse_func (ctxt, *array_obj, member[i]);                      \
          }                                                                    \
   }
 
-#define PARSE_ENUM_FIELD(obj, key, member, mappings)                           \
-  parse_enum_field (obj, key, member, mappings,                                \
-                   sizeof (mappings) / sizeof (mappings[0]))
+#define PARSE_ENUM_FIELD(ctxt, obj, key, member, mappings)                     \
+  parse_enum_field (ctxt, obj, key, member, mappings,                          \
+                   sizeof (mappings) / sizeof (mappings[0]), WARNING_OPT)
 
 /* Type alias for parse function pointer.  */
 template <typename T>
 using parse_func_type
-  = void (*) (const json::object *,
+  = void (*) (gcc_json_context &,
+             const json::object &,
              std::remove_const_t<std::remove_pointer_t<T>> &);
 
 /* Parse JSON object into non-pointer member type.  */
 template <typename T>
 static std::enable_if_t<!std::is_pointer<T>::value>
-parse_object_helper (const json::object *field_obj, T &member,
+parse_object_helper (gcc_json_context &ctxt,
+                    const json::object &field_obj, T &member,
                     parse_func_type<T> parse_func)
 {
-  parse_func (field_obj, member);
+  parse_func (ctxt, field_obj, member);
 }
 
 /* Parse JSON object into a const pointer member by creating a temp copy.  */
 template <typename T>
 static std::enable_if_t<std::is_pointer<T>::value
                        && std::is_const<std::remove_pointer_t<T>>::value>
-parse_object_helper (const json::object *field_obj, T &member,
+parse_object_helper (gcc_json_context &ctxt,
+                    const json::object &field_obj, T &member,
                     parse_func_type<T> parse_func)
 {
   /* Use static storage for the non-const copy.
@@ -117,8 +123,9 @@ parse_object_helper (const json::object *field_obj, T &member,
   static bool already_initialized = false;
   if (already_initialized)
     {
-      error ("static storage conflict - multiple pointer members of the "
-            "same type cannot be parsed");
+      json_error (ctxt, field_obj,
+                 "static storage conflict - multiple pointer members of "
+                 "the same type cannot be parsed");
       return;
     }
   already_initialized = true;
@@ -127,60 +134,113 @@ parse_object_helper (const json::object *field_obj, T &member,
     warning (0, "JSON tuning overrides an unspecified structure in the base "
                "tuning; fields not provided in JSON will default to 0");
   static NonConstType new_obj = member ? *member : NonConstType{};
-  parse_func (field_obj, new_obj);
+  parse_func (ctxt, field_obj, new_obj);
   member = &new_obj;
 }
 
+/* Issue a note about the kind of json value we encountered.  */
+
+static void
+inform_about_wrong_kind_of_json_value (gcc_json_context &ctxt,
+                                      const json::value &val)
+{
+  switch (val.get_kind ())
+    {
+    default:
+      gcc_unreachable ();
+    case json::JSON_OBJECT:
+      json_note (ctxt, val, "...but got an object instead");
+      break;
+    case json::JSON_ARRAY:
+      json_note (ctxt, val, "...but got an array instead");
+      break;
+    case json::JSON_INTEGER:
+      json_note (ctxt, val, "...but got an integer instead");
+      break;
+    case json::JSON_FLOAT:
+      json_note (ctxt, val, "...but got a floating-point value instead");
+      break;
+    case json::JSON_STRING:
+      json_note (ctxt, val, "...but got a string instead");
+      break;
+    case json::JSON_TRUE:
+      json_note (ctxt, val, "...but got %qs instead", "true");
+      break;
+    case json::JSON_FALSE:
+      json_note (ctxt, val, "...but got %qs instead", "false");
+      break;
+    case json::JSON_NULL:
+      json_note (ctxt, val, "...but got %qs instead", "null");
+      break;
+    }
+}
+
 /* Extract string value from JSON, returning allocated C string.  */
 char *
-extract_string (const json::value *val)
+extract_string (gcc_json_context &ctxt,
+               const json::value &val,
+               diagnostics::option_id warning_opt)
 {
-  if (auto *string_val = dyn_cast<const json::string *> (val))
+  if (auto *string_val = dyn_cast<const json::string *> (&val))
     return xstrdup (string_val->get_string ());
-  warning (0, "expected a string but got something else or NULL");
+  auto_diagnostic_group d;
+  if (json_warning (ctxt, val, warning_opt, "expected a string..."))
+    inform_about_wrong_kind_of_json_value (ctxt, val);
   return nullptr;
 }
 
 /* Extract signed integer value from JSON.  */
 int
-extract_integer (const json::value *val)
+extract_integer (gcc_json_context &ctxt,
+                const json::value &val,
+                diagnostics::option_id warning_opt)
 {
-  if (auto *int_val = dyn_cast<const json::integer_number *> (val))
+  if (auto *int_val = dyn_cast<const json::integer_number *> (&val))
     {
       long value = int_val->get ();
       gcc_assert (value >= INT_MIN && value <= INT_MAX);
       return static_cast<int> (value);
     }
-  warning (0, "expected an integer value but got something else or NULL");
+  auto_diagnostic_group d;
+  if (json_warning (ctxt, val, warning_opt, "expected an integer value..."))
+    inform_about_wrong_kind_of_json_value (ctxt, val);
   return 0;
 }
 
 /* Extract unsigned integer value from JSON.  */
 unsigned int
-extract_unsigned_integer (const json::value *val)
+extract_unsigned_integer (gcc_json_context &ctxt,
+                         const json::value &val,
+                         diagnostics::option_id warning_opt)
 {
-  if (auto *int_val = dyn_cast<const json::integer_number *> (val))
+  if (auto *int_val = dyn_cast<const json::integer_number *> (&val))
     {
       long value = int_val->get ();
       gcc_assert (value >= 0 && value <= UINT_MAX);
       return static_cast<unsigned int> (value);
     }
-  warning (0,
-          "expected an unsigned integer value but got something else or NULL");
+  auto_diagnostic_group d;
+  if (json_warning (ctxt, val, warning_opt,
+                   "expected an unsigned integer value..."))
+    inform_about_wrong_kind_of_json_value (ctxt, val);
   return 0;
 }
 
 /* Extract boolean value from JSON literal.  */
 bool
-extract_boolean (const json::value *val)
+extract_boolean (gcc_json_context &ctxt,
+                const json::value &val,
+                diagnostics::option_id warning_opt)
 {
-  if (auto *literal_val = dyn_cast<const json::literal *> (val))
+  if (auto *literal_val = dyn_cast<const json::literal *> (&val))
     {
       json::kind kind = literal_val->get_kind ();
       if (kind == json::JSON_TRUE || kind == json::JSON_FALSE)
        return (kind == json::JSON_TRUE);
     }
-  warning (0, "expected a boolean value but got something else or NULL");
+  auto_diagnostic_group d;
+  if (json_warning (ctxt, val, warning_opt, "expected a boolean value..."))
+    inform_about_wrong_kind_of_json_value (ctxt, val);
   return false;
 }
 
@@ -193,18 +253,21 @@ template <typename EnumType> struct enum_mapping
 /* Parse JSON string field into enum value using string-to-enum mappings.  */
 template <typename EnumType>
 static void
-parse_enum_field (const json::object *jo, const std::string &key,
+parse_enum_field (gcc_json_context &ctxt,
+                 const json::object &jo, const std::string &key,
                  EnumType &enum_var, const enum_mapping<EnumType> *mappings,
-                 size_t num_mappings)
+                 size_t num_mappings,
+                 diagnostics::option_id warning_opt)
 {
-  const json::value *field_value = jo->get (key.c_str ());
+  const json::value *field_value = jo.get (key.c_str ());
   if (!field_value)
     return;
 
   auto *string_val = dyn_cast<const json::string *> (field_value);
   if (!string_val)
     {
-      warning (0, "expected string for enum field %s", key.c_str ());
+      json_warning (ctxt, *field_value, warning_opt,
+                   "expected string for enum field %s", key.c_str ());
       enum_var = mappings[0].value;
       return;
     }
@@ -219,8 +282,9 @@ parse_enum_field (const json::object *jo, const std::string &key,
        }
     }
 
-  warning (0, "%s not recognized, defaulting to %qs", key.c_str (),
-          mappings[0].name);
+  json_warning (ctxt, *field_value, 0,
+               "%s not recognized, defaulting to %qs", key.c_str (),
+               mappings[0].name);
   enum_var = mappings[0].value;
 }
 
@@ -230,7 +294,8 @@ parse_enum_field (const json::object *jo, const std::string &key,
 /* Validate the user provided JSON data against the present schema.
    Checks for correct types, fields, and expected format.  */
 static bool
-validate_and_traverse (const json::object *json_obj,
+validate_and_traverse (gcc_json_context &ctxt,
+                      const json::object *json_obj,
                       const json::object *schema_obj,
                       const std::string &parent_key = "")
 {
@@ -244,8 +309,9 @@ validate_and_traverse (const json::object *json_obj,
       const json::value *schema_value = schema_obj->get (key.c_str ());
       if (!schema_value)
        {
-         warning (0, "key %qs is not a tuning parameter, skipping",
-                  full_key.c_str ());
+         json_warning (ctxt, *json_value, WARNING_OPT,
+                       "key %qs is not a tuning parameter, skipping",
+                       full_key.c_str ());
          continue;
        }
 
@@ -253,13 +319,15 @@ validate_and_traverse (const json::object *json_obj,
        {
          if (auto *sub_json_obj = dyn_cast<const json::object *> (json_value))
            {
-             if (!validate_and_traverse (sub_json_obj, sub_schema_obj,
+             if (!validate_and_traverse (ctxt, sub_json_obj, sub_schema_obj,
                                          full_key))
                return false;
            }
          else
            {
-             error ("key %qs expected to be an object", full_key.c_str ());
+             json_error (ctxt, *json_value,
+                         "key %qs expected to be an object",
+                         full_key.c_str ());
              return false;
            }
        }
@@ -267,7 +335,8 @@ validate_and_traverse (const json::object *json_obj,
        {
          if (json_value->get_kind () != json::JSON_ARRAY)
            {
-             error ("key %qs expected to be an array", full_key.c_str ());
+             json_error (ctxt, *json_value,
+                         "key %qs expected to be an array", full_key.c_str ());
              return false;
            }
        }
@@ -280,8 +349,9 @@ validate_and_traverse (const json::object *json_obj,
            {
              if (json_value->get_kind () != json::JSON_INTEGER)
                {
-                 error ("key %qs expected to be an integer",
-                        full_key.c_str ());
+                 json_error (ctxt, *json_value,
+                             "key %qs expected to be an integer",
+                             full_key.c_str ());
                  return false;
                }
              // Check if the value is valid for signed integer
@@ -291,9 +361,10 @@ validate_and_traverse (const json::object *json_obj,
                  long value = int_val->get ();
                  if (value > INT_MAX || value < INT_MIN)
                    {
-                     error ("key %qs value %ld is out of range for %<int%> "
-                            "type [%d, %d]",
-                            full_key.c_str (), value, INT_MIN, INT_MAX);
+                     json_error (ctxt, *json_value,
+                                 "key %qs value %ld is out of range for "
+                                 "%<int%> type [%d, %d]",
+                                 full_key.c_str (), value, INT_MIN, INT_MAX);
                      return false;
                    }
                }
@@ -302,8 +373,9 @@ validate_and_traverse (const json::object *json_obj,
            {
              if (json_value->get_kind () != json::JSON_INTEGER)
                {
-                 error ("key %qs expected to be an unsigned integer",
-                        full_key.c_str ());
+                 json_error (ctxt, *json_value,
+                             "key %qs expected to be an unsigned integer",
+                             full_key.c_str ());
                  return false;
                }
              // Check if the value is valid for unsigned integer
@@ -313,9 +385,10 @@ validate_and_traverse (const json::object *json_obj,
                  long value = int_val->get ();
                  if (value < 0 || value > UINT_MAX)
                    {
-                     error ("key %qs value %ld is out of range for %<uint%> "
-                            "type [0, %u]",
-                            full_key.c_str (), value, UINT_MAX);
+                     json_error (ctxt, *json_value,
+                                 "key %qs value %ld is out of range for "
+                                 "%<uint%> type [0, %u]",
+                                 full_key.c_str (), value, UINT_MAX);
                      return false;
                    }
                }
@@ -324,7 +397,9 @@ validate_and_traverse (const json::object *json_obj,
            {
              if (json_value->get_kind () != json::JSON_STRING)
                {
-                 error ("key %qs expected to be a string", full_key.c_str ());
+                 json_error (ctxt, *json_value,
+                             "key %qs expected to be a string",
+                             full_key.c_str ());
                  return false;
                }
            }
@@ -333,8 +408,9 @@ validate_and_traverse (const json::object *json_obj,
              if (json_value->get_kind () != json::JSON_TRUE
                  && json_value->get_kind () != json::JSON_FALSE)
                {
-                 error ("key %qs expected to be a boolean (true/false)",
-                        full_key.c_str ());
+                 json_error (ctxt, *json_value,
+                             "key %qs expected to be a boolean (true/false)",
+                             full_key.c_str ());
                  return false;
                }
            }
@@ -342,20 +418,24 @@ validate_and_traverse (const json::object *json_obj,
            {
              if (json_value->get_kind () != json::JSON_STRING)
                {
-                 error ("key %qs expected to be an enum (string)",
-                        full_key.c_str ());
+                 json_error (ctxt, *json_value,
+                             "key %qs expected to be an enum (string)",
+                             full_key.c_str ());
                  return false;
                }
            }
          else
            {
-             error ("key %qs has unsupported type", full_key.c_str ());
+             json_error (ctxt, *json_value,
+                         "key %qs has unsupported type", full_key.c_str ());
              return false;
            }
        }
       else
        {
-         error ("key %qs has unexpected format in schema", full_key.c_str ());
+         json_error (ctxt, *json_value,
+                     "key %qs has unexpected format in schema",
+                     full_key.c_str ());
          return false;
        }
     }
@@ -413,13 +493,15 @@ check_version_compatibility (const json::object *root_obj)
 
   if (json_gcc_major_version == -1)
     {
-      warning (0, "JSON tuning file does not contain version information; "
-                 "compatibility cannot be verified");
+      warning (WARNING_OPT,
+              "JSON tuning file does not contain version information; "
+              "compatibility cannot be verified");
       return true;
     }
 
   if (json_gcc_major_version != GCC_major_version)
     {
+      auto_diagnostic_group d;
       error ("JSON tuning file was created with GCC version %d "
             "but current GCC version is %d",
             json_gcc_major_version, GCC_major_version);
@@ -433,31 +515,32 @@ check_version_compatibility (const json::object *root_obj)
 
 /* Main routine for setting up the parsing of JSON data.  */
 static void
-aarch64_load_tuning_params_from_json_string (const char *json_string,
+aarch64_load_tuning_params_from_json_string (const char *js_filename,
+                                            const char *json_string,
                                             const char *schema_string,
                                             struct tune_params *tune)
 {
   /* Try parsing the JSON string.  */
+  gcc_json_context ctxt (js_filename);
   json::parser_result_t data_result
     = json::parse_utf8_string (strlen (json_string), json_string, true,
-                              nullptr);
+                              &ctxt);
 
   if (auto json_err = data_result.m_err.get ())
     {
-      error ("error parsing JSON data: %s", json_err->get_msg ());
+      location_t js_loc = ctxt.make_location_for_range (json_err->get_range ());
+      error_at (js_loc, "error parsing JSON data: %s", json_err->get_msg ());
       return;
     }
 
-  const std::unique_ptr<json::value> &root = data_result.m_val;
-  if (!root)
-    {
-      error ("JSON parsing returned null data");
-      return;
-    }
-  auto *root_obj = dyn_cast<const json::object *> (root.get ());
+  const json::value* root = data_result.m_val.get ();
+  gcc_assert (root);
+
+  auto *root_obj = dyn_cast<const json::object *> (root);
   if (!root_obj)
     {
-      warning (0, "no JSON object found in the provided data");
+      json_warning (ctxt, *root, WARNING_OPT,
+                   "no JSON object found in the provided data");
       return;
     }
 
@@ -479,24 +562,26 @@ aarch64_load_tuning_params_from_json_string (const char *json_string,
   const json::value *tune_params_value = root_obj->get ("tune_params");
   if (!tune_params_value)
     {
-      warning (0, "key %<tune_params%> not found in JSON data");
+      json_warning (ctxt, *root_obj, WARNING_OPT,
+                   "key %<tune_params%> not found in JSON data");
       return;
     }
 
   auto *jo = dyn_cast<const json::object *> (tune_params_value);
   if (!jo)
     {
-      error ("key %<tune_params%> is not a JSON object");
+      json_error (ctxt, *tune_params_value,
+                 "key %<tune_params%> is not a JSON object");
       return;
     }
 
-  if (!validate_and_traverse (root_obj, schema_obj))
+  if (!validate_and_traverse (ctxt, root_obj, schema_obj))
     {
       error ("validation failed for the provided JSON data");
       return;
     }
 
-  parse_tunings (jo, *tune);
+  parse_tunings (ctxt, *jo, *tune);
 
   /* dispatch_constraints are not represented in JSON tunings.  If the JSON
      sets DISPATCH_SCHED in extra_tuning_flags but the base model does not
@@ -525,8 +610,9 @@ aarch64_load_tuning_params_from_json (const char *data_filename,
       error ("cannot read JSON data in %s", data_filename);
       return;
     }
-  aarch64_load_tuning_params_from_json_string (
-    (const char *) json_data->data (), schema_json, tune);
+  aarch64_load_tuning_params_from_json_string
+    (data_filename,
+     (const char *) json_data->data (), schema_json, tune);
 }
 
 #if CHECKING_P
@@ -550,7 +636,8 @@ test_json_integers ()
 
   tune_params params;
 
-  aarch64_load_tuning_params_from_json_string (test_json, schema_json, &params);
+  aarch64_load_tuning_params_from_json_string
+    ("test.json", test_json, schema_json, &params);
 
   ASSERT_EQ (params.sve_width, 256);
   ASSERT_EQ (params.issue_rate, 4);
@@ -577,7 +664,8 @@ test_json_boolean ()
   tune_params params;
   params.insn_extra_cost = &default_cost_table;
 
-  aarch64_load_tuning_params_from_json_string (test_json, schema_json, &params);
+  aarch64_load_tuning_params_from_json_string
+    ("test.json", test_json, schema_json, &params);
 
   ASSERT_EQ (params.insn_extra_cost->alu.non_exec_costs_exec, false);
 }
@@ -598,7 +686,8 @@ test_json_strings ()
 
   tune_params params;
 
-  aarch64_load_tuning_params_from_json_string (test_json, schema_json, &params);
+  aarch64_load_tuning_params_from_json_string
+    ("test.json", test_json, schema_json, &params);
 
   ASSERT_STREQ (params.function_align, "16");
   ASSERT_STREQ (params.jump_align, "2");
@@ -621,7 +710,8 @@ test_json_enums ()
 
   tune_params params;
 
-  aarch64_load_tuning_params_from_json_string (test_json, schema_json, &params);
+  aarch64_load_tuning_params_from_json_string
+    ("test.json", test_json, schema_json, &params);
 
   ASSERT_EQ (params.autoprefetcher_model, tune_params::AUTOPREFETCHER_OFF);
   ASSERT_EQ (params.ldp_policy_model, AARCH64_LDP_STP_POLICY_NEVER);
index aef632f1d042340113acb66cbf48422bf89d45e9..0ed8f71b775d022cb40b43756e7a9853809eb17a 100644 (file)
@@ -1,8 +1,16 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/boolean-2.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
 
 /* { dg-warning "JSON tuning file does not contain version information" "" { target *-*-* } 0 } */
-/* { dg-error "key .* expected to be a boolean"  "" { target *-*-* } 0 } */
+
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/boolean-2.json: In JSON value '/tune_params/insn_extra_cost/alu/non_exec_costs_exec'" } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/boolean-2.json:5:32: error: key .* expected to be a boolean \\\(true/false\\\)"  } */
+/* { dg-begin-multiline-output "" }
+    5 |         "non_exec_costs_exec": 0
+      |                                ^
+   { dg-end-multiline-output "" } */
+
 /* { dg-error "validation failed for the provided JSON data"  "" { target *-*-* } 0 } */
 
-int main () {}
\ No newline at end of file
+int main () {}
index 4df72dbaf7ab4d5a809a39d273f8735cd0d2ab4e..cbbe8afe760ec9a688e905bad10bf45d811d6d59 100644 (file)
@@ -1,7 +1,12 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/empty-brackets.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
 
 /* { dg-warning "JSON tuning file does not contain version information" "" { target *-*-* } 0 } */
-/* { dg-warning "key 'tune_params' not found in JSON data"  "" { target *-*-* } 0 } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/empty-brackets.json:1:1: warning: key 'tune_params' not found in JSON data" } */
+/* { dg-begin-multiline-output "" }
+    1 | {}
+      | ^~
+   { dg-end-multiline-output "" } */
 
-int main () {}
\ No newline at end of file
+int main () {}
index c53bc5292d52f74b07c03c0de41fc965cd464380..30e0fd47d79467d183b5d1f25582a591cb26e3f3 100644 (file)
@@ -1,8 +1,21 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/enum-2.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
 
 /* { dg-warning "JSON tuning file does not contain version information" "" { target *-*-* } 0 } */
-/* { dg-warning "autoprefetcher_model not recognized, defaulting to 'AUTOPREFETCHER_OFF'"  "" { target *-*-* } 0 } */
-/* { dg-warning "ldp_policy_model not recognized, defaulting to 'AARCH64_LDP_STP_POLICY_DEFAULT'"  "" { target *-*-* } 0 } */
 
-int main () {}
\ No newline at end of file
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/enum-2.json: In JSON value '/tune_params/autoprefetcher_model'" } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/enum-2.json:3:29: warning: autoprefetcher_model not recognized, defaulting to 'AUTOPREFETCHER_OFF'" } */
+/* { dg-begin-multiline-output "" }
+    3 |     "autoprefetcher_model": "null",
+      |                             ^~~~~~
+   { dg-end-multiline-output "" } */
+
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/enum-2.json: In JSON value '/tune_params/ldp_policy_model'" } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/enum-2.json:4:25: warning: ldp_policy_model not recognized, defaulting to 'AARCH64_LDP_STP_POLICY_DEFAULT'" } */
+/* { dg-begin-multiline-output "" }
+    4 |     "ldp_policy_model": "null",
+      |                         ^~~~~~
+   { dg-end-multiline-output "" } */
+
+int main () {}
index 093c86048ce9590536ea0d9469bdbce3697ac5ab..4e9de75a7aa7d0a6aca4d8b1217aa61e94210d96 100644 (file)
@@ -1,8 +1,16 @@
 /* { dg-do compile } */
-/* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/integer-2.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/integer-2.json -fdump-tuning-model=temp.json " } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
 
 /* { dg-warning "JSON tuning file does not contain version information" "" { target *-*-* } 0 } */
-/* { dg-error "key .* value .* is out of range for 'int' type"  "" { target *-*-* } 0 } */
+
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/integer-2.json: In JSON value '/tune_params/int_reassoc_width'" } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/integer-2.json:3:26: error: key .* value .* is out of range for 'int' type \\\[.*, .*\\\]" } */
+/* { dg-begin-multiline-output "" }
+    3 |     "int_reassoc_width": 12097307449014
+      |                          ^~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
 /* { dg-error "validation failed for the provided JSON data"  "" { target *-*-* } 0 } */
 
-int main () {}
\ No newline at end of file
+int main () {}
index 438685c6002c60385ce67615ec12a449d6b64632..bab713b35d03fdd2e90d6623f497402350ca09dc 100644 (file)
@@ -1,8 +1,17 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/integer-3.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
 
 /* { dg-warning "JSON tuning file does not contain version information" "" { target *-*-* } 0 } */
-/* { dg-error "key .* expected to be an integer"  "" { target *-*-* } 0 } */
+
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/integer-3.json: In JSON value '/tune_params/issue_rate'" } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/integer-3.json:3:19: error: key .* expected to be an integer" } */
+/* { dg-begin-multiline-output "" }
+    3 |     "issue_rate": "10"
+      |                   ^~~~
+   { dg-end-multiline-output "" } */
+
+
 /* { dg-error "validation failed for the provided JSON data"  "" { target *-*-* } 0 } */
 
-int main () {}
\ No newline at end of file
+int main () {}
diff --git a/gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/malformed.c b/gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/malformed.c
new file mode 100644 (file)
index 0000000..f4d6bc0
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/malformed.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
+
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/malformed.json:3:17: error: error parsing JSON data: expected ':'; got number" } */
+/* { dg-begin-multiline-output "" }
+    3 |     "sve_width" 128
+      |                 ^~~
+   { dg-end-multiline-output "" } */
+
+int main () {}
diff --git a/gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/malformed.json b/gcc/testsuite/gcc.target/aarch64/aarch64-json-tunings/malformed.json
new file mode 100644 (file)
index 0000000..541b721
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "tune_params": {
+    "sve_width" 128
+  }
+}
index ad3ea1422bade22c302883229bd550ca2c44900f..ae6e265c514acdacfcb56371109472c87d92a160 100644 (file)
@@ -1,8 +1,16 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/string-2.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
 
 /* { dg-warning "JSON tuning file does not contain version information" "" { target *-*-* } 0 } */
-/* { dg-error "key .* expected to be a string"  "" { target *-*-* } 0 } */
+
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/string-2.json: In JSON value '/tune_params/function_align'" } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/string-2.json:3:23: error: key .* expected to be a string"  "" { target *-*-* } 0 } */
+/* { dg-begin-multiline-output "" }
+    3 |     "function_align": 16
+      |                       ^~
+   { dg-end-multiline-output "" } */
+
 /* { dg-error "validation failed for the provided JSON data"  "" { target *-*-* } 0 } */
 
-int main () {}
\ No newline at end of file
+int main () {}
index bafbda8a1ef578ff12c002e81662ee1039c4f5c5..27bfacc40203d3379b56ca92a62361a622d51c01 100644 (file)
@@ -1,7 +1,15 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/unidentified-key.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
 
 /* { dg-warning "JSON tuning file does not contain version information" "" { target *-*-* } 0 } */
-/* { dg-warning "key .* is not a tuning parameter, skipping"  "" { target *-*-* } 0 } */
 
-int main () {}
\ No newline at end of file
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/unidentified-key.json: In JSON value '/tune_params/unidentified_key'" } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/unidentified-key.json:3:25: warning: key .* is not a tuning parameter, skipping"  "" { target *-*-* } 0 } */
+
+/* { dg-begin-multiline-output "" }
+    3 |     "unidentified_key": "10"
+      |                         ^~~~
+   { dg-end-multiline-output "" } */
+
+int main () {}
index ce1989d8e31df74d70b22ae142195b9b9766aa80..88848e406cc0a151d0629a9273435f418efea0b2 100644 (file)
@@ -1,8 +1,16 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/unsigned-2.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
 
 /* { dg-warning "JSON tuning file does not contain version information" "" { target *-*-* } 0 } */
-/* { dg-error "key .* value .* is out of range for 'uint' type"  "" { target *-*-* } 0 } */
+
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/unsigned-2.json: In JSON value '/tune_params/sve_width'" } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/unsigned-2.json:3:18: error: key .* value .* is out of range for 'uint' type \\\[.*, .*\\\]" } */
+/* { dg-begin-multiline-output "" }
+    3 |     "sve_width": -128,
+      |                  ^~~~
+   { dg-end-multiline-output "" } */
+
 /* { dg-error "validation failed for the provided JSON data"  "" { target *-*-* } 0 } */
 
 int main () {}
index 20a661f557026534a2934e5c6fdda8f2d2e077f2..0e808009810ef626b9502ff6bed0c22e4aafa24a 100644 (file)
@@ -1,8 +1,16 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-muser-provided-CPU=${srcdir}/gcc.target/aarch64/aarch64-json-tunings/unsigned-3.json -fdump-tuning-model=temp.json" } */
+/* { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
 
 /* { dg-warning "JSON tuning file does not contain version information" "" { target *-*-* } 0 } */
-/* { dg-error "key .* value .* is out of range for 'uint' type"  "" { target *-*-* } 0 } */
+
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/unsigned-3.json: In JSON value '/tune_params/sve_width'" } */
+/* { dg-regexp ".*gcc.target/aarch64/aarch64-json-tunings/unsigned-3.json:3:18: error: key .* value .* is out of range for 'uint' type \\\[.*, .*\\\]" } */
+/* { dg-begin-multiline-output "" }
+    3 |     "sve_width": 5000000000
+      |                  ^~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
 /* { dg-error "validation failed for the provided JSON data"  "" { target *-*-* } 0 } */
 
 int main () {}