From: Herve Codina <herve.codina@bootlin.com>
To: Simon Glass <sjg@chromium.org>
Cc: Devicetree Compiler <devicetree-compiler@vger.kernel.org>,
David Gibson <david@gibson.dropbear.id.au>
Subject: Re: [PATCH 12/13] dtc: Merge the fragments of a dts file after parsing
Date: Tue, 3 Nov 2026 18:07:53 +0100 [thread overview]
Message-ID: <20261103180753.37c83a4c@bootlin.com> (raw)
In-Reply-To: <20261101163721.2458982-13-sjg@chromium.org>
On Sun, 1 Nov 2026 09:37:06 -0700
Simon Glass <sjg@chromium.org> wrote:
> We would like to deal with each top-level fragment of a dts file before
> it is merged into the tree, but that requires the fragments to be kept
> apart until the whole file is parsed. At present the parser merges each
> one as soon as it is parsed. The grammar actions also need to know
> whether the file is a plugin, which they find using $<flags>-1
>
> Have the grammar build a list of the fragments instead, in source order,
> and merge them with a new merge_fragments() once the whole file is
> parsed. This calls merge_fragment() for each one, so the output does not
> change, and frees each fragment once it is merged.
>
> The $<flags>-1 term is no longer needed. Within a devicetree action it
> reaches back up the parser stack to the value of headers, i.e. the flags
> from /dts-v1/ and /plugin/. The sourcefile action passes the same value
> to build_dt_info(), which stores it in dti->dtsflags, so
> merge_fragments() can use that instead.
>
> There are two differences in the errors. A syntax error later in the
> file now stops dtc before any earlier reference errors are reported, and
> reference errors now come after any other errors which the parser
> reports, such as a division by zero, rather than in source order.
>
> dtc gives the same output and messages as before for all 4162 .dts and
> .dtso files in Linux v7.3-12284-g3799eeb906c9, and for the dts files in
> tests/
>
> Suggested-by: David Gibson <david@gibson.dropbear.id.au>
> Link: https://lore.kernel.org/devicetree-compiler/auK0ERvxGCJGSc3p@gractus.seuss/
> Assisted-by: Claude:claude-opus-5-5
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> dtc-parser.y | 43 +++++++++++++------------------------------
> dtc.h | 2 +-
> livetree.c | 36 ++++++++++++++++++++++++++++++++++--
> 3 files changed, 48 insertions(+), 33 deletions(-)
>
> diff --git a/dtc-parser.y b/dtc-parser.y
> index 1ed9731..c1aa4ad 100644
> --- a/dtc-parser.y
> +++ b/dtc-parser.y
> @@ -24,22 +24,6 @@ extern void yyerror(char const *s);
> extern struct dt_info *parser_output;
> extern bool treesource_error;
>
> -/*
> - * Merge a fragment into the tree as soon as it is parsed. The flags come
> - * from the actions using $<flags>-1, which relies on the rule being always:
> - * headers memreserves devicetree
> - * so $-1 is the value of headers
> - */
> -static struct node *merge_parsed_fragment(struct node *dt, struct fragment *f,
> - unsigned int flags)
> -{
> - if (merge_fragment(&dt, f, flags & DTSF_PLUGIN))
> - treesource_error = true;
> - free_fragment(f);
> -
> - return dt;
> -}
> -
> %}
>
> %union {
> @@ -94,7 +78,7 @@ static struct node *merge_parsed_fragment(struct node *dt, struct fragment *f,
> %type <labelref> dt_ref
> %type <fragment> fragment_ref
>
> -%type <node> devicetree
> +%type <fragment> devicetree
> %type <node> nodedef
> %type <node> subnode
> %type <nodelist> subnodes
> @@ -119,8 +103,10 @@ static struct node *merge_parsed_fragment(struct node *dt, struct fragment *f,
> sourcefile:
> headers memreserves devicetree
> {
> - parser_output = build_dt_info($1, $2, $3,
> - guess_boot_cpuid($3));
> + parser_output = build_dt_info($1, $2, NULL, 0);
> + parser_output->fragments = $3;
> + if (merge_fragments(parser_output))
> + treesource_error = true;
Why not just pass the fragment list to build_dt_info() instead of using the
parser_output->fragments and later in merge_fragments() setting this same field
to NULL once the merge is done?
IHMO, the struct dt_info doesn't need the fragments fiels (already mentionned
in patch 2).
If build_dt_info() has too much parameters, a struct dt_info_def could be
created to group all those parameters in one structure.
> }
> ;
>
> @@ -184,42 +170,39 @@ fragment_ref:
> devicetree:
> '/' nodedef
> {
> - struct fragment *f = build_fragment(FRAGMENT_ROOT, $2);
> -
> - $$ = merge_parsed_fragment(NULL, f, $<flags>-1);
> + $$ = build_fragment(FRAGMENT_ROOT, $2);
> }
> | devicetree '/' nodedef
> {
> - struct fragment *f = build_fragment(FRAGMENT_ROOT, $3);
> -
> - $$ = merge_parsed_fragment($1, f, $<flags>-1);
> + $$ = append_fragment($1, build_fragment(FRAGMENT_ROOT,
> + $3));
> }
> | fragment_ref nodedef
> {
> $1->node = $2;
> - $$ = merge_parsed_fragment(NULL, $1, $<flags>-1);
> + $$ = $1;
> }
> | devicetree DT_LABEL fragment_ref nodedef
> {
> $3->label = $2;
> $3->label_srcpos = srcpos_copy(&@2);
> $3->node = $4;
> - $$ = merge_parsed_fragment($1, $3, $<flags>-1);
> + $$ = append_fragment($1, $3);
> }
> | devicetree fragment_ref nodedef
> {
> $2->node = $3;
> - $$ = merge_parsed_fragment($1, $2, $<flags>-1);
> + $$ = append_fragment($1, $2);
> }
> | devicetree DT_DEL_NODE fragment_ref ';'
> {
> $3->type = FRAGMENT_DELETE_NODE;
> - $$ = merge_parsed_fragment($1, $3, $<flags>-1);
> + $$ = append_fragment($1, $3);
> }
> | devicetree DT_OMIT_NO_REF fragment_ref ';'
> {
> $3->type = FRAGMENT_OMIT_IF_NO_REF;
> - $$ = merge_parsed_fragment($1, $3, $<flags>-1);
> + $$ = append_fragment($1, $3);
> }
> ;
>
> diff --git a/dtc.h b/dtc.h
> index 41013f5..fdd0d75 100644
> --- a/dtc.h
> +++ b/dtc.h
> @@ -368,7 +368,6 @@ struct fragment *build_fragment_ref(char *ref, bool path_ref,
> struct srcpos *srcpos);
> struct fragment *append_fragment(struct fragment *list, struct fragment *new);
> void free_fragment(struct fragment *f);
> -bool merge_fragment(struct node **dtp, struct fragment *f, bool plugin);
>
> struct dt_info {
> unsigned int dtsflags;
> @@ -386,6 +385,7 @@ struct dt_info {
> struct dt_info *build_dt_info(unsigned int dtsflags,
> struct reserve_info *reservelist,
> struct node *tree, uint32_t boot_cpuid_phys);
> +bool merge_fragments(struct dt_info *dti);
> void sort_tree(struct dt_info *dti);
> void generate_labels_from_tree(struct dt_info *dti, const char *name);
> void generate_label_tree(struct dt_info *dti, const char *name, bool allocph);
> diff --git a/livetree.c b/livetree.c
> index 1e012d4..68ad3c3 100644
> --- a/livetree.c
> +++ b/livetree.c
> @@ -537,7 +537,8 @@ struct dt_info *build_dt_info(unsigned int dtsflags,
> dti->fragments = NULL;
> dti->boot_cpuid_phys = boot_cpuid_phys;
>
> - fill_fullpaths(dti->dt, "");
> + if (tree)
> + fill_fullpaths(dti->dt, "");
>
> return dti;
> }
> @@ -718,7 +719,8 @@ static bool merge_omit_if_no_ref(struct node *dt, struct fragment *f)
> *
> * Returns true if there is an error, which has been reported.
> */
> -bool merge_fragment(struct node **dtp, struct fragment *f, bool plugin)
> +static bool merge_fragment(struct node **dtp, struct fragment *f,
> + bool plugin)
> {
> struct node *dt = *dtp;
>
> @@ -750,6 +752,36 @@ bool merge_fragment(struct node **dtp, struct fragment *f, bool plugin)
> return false;
> }
>
> +/*
> + * Merge the fragments of a dts file into a single tree, in source order.
> + *
> + * Returns true if there are errors, which have been reported.
> + */
> +bool merge_fragments(struct dt_info *dti)
> +{
> + bool plugin = dti->dtsflags & DTSF_PLUGIN;
> + struct fragment *f, *next;
> + struct node *dt = NULL;
> + bool error = false;
> +
> + if (!dti->fragments)
> + return false;
> +
> + for (f = dti->fragments; f; f = next) {
> + next = f->next;
> + if (merge_fragment(&dt, f, plugin))
> + error = true;
> + free_fragment(f);
> + }
> +
> + dti->dt = dt;
> + dti->fragments = NULL;
This field is really a temporary field. Should be removed from the
struct dt_info.
> + dti->boot_cpuid_phys = guess_boot_cpuid(dt);
> + fill_fullpaths(dti->dt, "");
fill_fullpaths() should be called only once in build_dt_info() as well as
setting dti->boot_cpuid_phys.
They have nothing to do with fragments.
> +
> + return error;
> +}
> +
> /*
> * Tree accessor functions
> */
Best regards,
Hervé
next prev parent reply other threads:[~2026-11-03 17:07 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-01 16:36 [PATCH 00/13] dtc: Merge the fragments of a dts file after parsing Simon Glass
2026-11-01 16:36 ` [PATCH 01/13] tests: Check each error when merging a dts file Simon Glass
2026-11-02 6:32 ` David Gibson
2026-11-04 15:15 ` Simon Glass
2026-11-01 16:36 ` [PATCH 02/13] dtc: Add a list for the top-level fragments of " Simon Glass
2026-11-02 9:49 ` David Gibson
2026-11-03 17:56 ` Herve Codina
2026-11-04 6:32 ` David Gibson
2026-11-04 8:29 ` Herve Codina
2026-11-04 9:34 ` David Gibson
2026-11-04 15:18 ` Simon Glass
2026-11-03 17:07 ` Herve Codina
2026-11-04 6:28 ` David Gibson
2026-11-01 16:36 ` [PATCH 03/13] dtc: Move the /delete-node/ handling out of the grammar Simon Glass
2026-11-02 9:55 ` David Gibson
2026-11-04 15:15 ` Simon Glass
2026-11-01 16:36 ` [PATCH 04/13] dtc: Move the /omit-if-no-ref/ " Simon Glass
2026-11-02 10:03 ` David Gibson
2026-11-01 16:36 ` [PATCH 05/13] dtc: Move is_ref_relative() to livetree.c Simon Glass
2026-11-02 10:04 ` David Gibson
2026-11-01 16:37 ` [PATCH 06/13] dtc: Move label-reference handling out of the grammar Simon Glass
2026-11-03 7:25 ` David Gibson
2026-11-01 16:37 ` [PATCH 07/13] dtc: Move path-reference " Simon Glass
2026-11-03 7:27 ` David Gibson
2026-11-04 15:16 ` Simon Glass
2026-11-01 16:37 ` [PATCH 08/13] dtc: Move labelled-reference " Simon Glass
2026-11-03 7:29 ` David Gibson
2026-11-04 15:16 ` Simon Glass
2026-11-01 16:37 ` [PATCH 09/13] dtc: Move first-reference " Simon Glass
2026-11-01 16:37 ` [PATCH 10/13] dtc: Add merge_fragment() to merge any fragment Simon Glass
2026-11-01 16:37 ` [PATCH 11/13] dtc: Add helpers for the errors when merging a fragment Simon Glass
2026-11-03 17:23 ` Herve Codina
2026-11-04 6:49 ` David Gibson
2026-11-04 8:55 ` Herve Codina
2026-11-01 16:37 ` [PATCH 12/13] dtc: Merge the fragments of a dts file after parsing Simon Glass
2026-11-03 17:07 ` Herve Codina [this message]
2026-11-04 6:50 ` David Gibson
2026-11-04 15:18 ` Simon Glass
2026-11-01 16:37 ` [PATCH 13/13] dtc: Merge the fragments of a dts file in main() Simon Glass
2026-11-03 17:08 ` Herve Codina
2026-11-04 6:51 ` David Gibson
2026-11-04 8:40 ` Herve Codina
2026-11-04 9:47 ` David Gibson
2026-11-04 13:23 ` Herve Codina
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261103180753.37c83a4c@bootlin.com \
--to=herve.codina@bootlin.com \
--cc=david@gibson.dropbear.id.au \
--cc=devicetree-compiler@vger.kernel.org \
--cc=sjg@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox