public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: David Brown <david@westcontrol.com>
To: gcc@gcc.gnu.org
Subject: Re: wishlist: support for shorter pointers
Date: Thu, 6 Jul 2023 14:53:43 +0200	[thread overview]
Message-ID: <u86dgn$13qa$1@ciao.gmane.io> (raw)
In-Reply-To: <2c42ea21-ad17-fe93-c228-1730a984360d@ztk-rp.eu>

On 06/07/2023 09:00, Rafał Pietrak via Gcc wrote:
> Hi,
> 
> W dniu 5.07.2023 o 19:39, David Brown pisze:
> [------------------]
>>> I'm not sure what this means? At compile time, you only have 
>>> literals, so what's missing?
>>
>> The compiler knows a lot more than just literal values at compile time 
>> - lots of things are "compile-time constants" without being literals 
>> that can be used in string literals.  That includes the value of 
>> static "const" variables, and the results of calculations or "pure" 
>> function 
> 
> const --> created by a literal.

Technically in C, the only "literals" are "string literals".  Something 
like 1234 is an integer constant, not a literal.  But I don't want to 
get too deep into such standardese - especially not for C++ !

Even in C, there are lots of things that are known at compile time 
without being literals (or explicit constants).  In many situations you 
can use "constant expressions", which includes basic arithmetic on 
constants, enumeration constants, etc.  The restrictions on what can be 
used in different circumstances is not always obvious (if you have 
"static const N = 10;", then "static const M = N + 1;" is valid but "int 
xs[N];" is not).

C++ has a very much wider concept of constant expressions at compile 
time - many more ways to make constant expressions, and many more ways 
to use them.  But even there, the compiler will know things at compile 
time that are not syntactically constant in the language.  (If you have 
code in a function "if (x < 0) return; bool b = (x >= 0);" then the 
compiler can optimise in the knowledge that "b" is a compile-time 
constant of "true".)


> 
>> calls using compile-time constant data.  You can do a great deal more of 
> 
> "compile time constant data" -> literal
> 
>> this in C++ than in C ("static const int N = 10; int arr[N];" is valid 
>> in C++, but not in C).  Calculated section names might be useful for 
>> sections that later need to be sorted.
>>
>> To be fair, you can construct string literals by the preprocessor that 
>> would cover many cases.
> 
> OK. We are talking of convenience syntax that allows for using any 
> "name" in c-sources as "const-literal" if only its rooted in literals 
> only. That's useful.
> 
> +2. :)
> 
>>
>> I can also add that generating linker symbols from compile-time 
>> constructed names could be useful, to use (abuse?) the linker to find 
>> issues across different source files.  Imagine you have a 
> 
> +1
> 
>> microcontroller with multiple timers, and several sources that all 
>> need to use timers.  A module that uses timer 1 could define a 
> [----------------------]
>>>>
>>>>      __attribute__((section("jit_buffer,\"ax\"\n@")))
>>>
>>> I assume, that adding an attribute should split a particular section 
>>> into "an old one" and "the new one with new attribute", right?
>>
>> You can't have the same section name and multiple flags.  But you 
>> sometimes want to have unusual flag combinations, such as executable 
>> ram sections for "run from ram" functions.
> 
> section flags reflect "semantic" of the section (ro v.s. rw is different 
> semantics at that level). So, how do you "merge" RAM (a section called 
> ".data"), one with "!x" flag, and the other with "x" flag?
> 
> conflicting flags of sections with the same name have to be taken into 
> consideration.
> 

It doesn't make sense to merge linker input sections with conflicting 
flags - this is (and should be) an error at link time.  So I am not 
asking for a way to make a piece of ".data" section with different flags 
from the standard ".data" section - I am asking about nicer ways to make 
different sections with different selections of flags.  (Input sections 
with different flags can be merged into one output section, as the 
semantic information is lost there.)

>>
>>>
>>> One would need to have linker logic (and linker script definitions) 
>>> altered, to follow that (other features so far wouldn't require any 
>>> changes to linkers, I think).
>>>
>>>> to add the flags manually, then a newline, then a line comment 
>>>> character (@ for ARM, but this varies according to target.)
>>>>
>>>> 6. Convenient support for non-initialised non-zeroed data sections 
>>>> in a standardised way, without having to specify sections manually 
>>>> in the source and linker setup.
>>>
>>> What gain and under which circumstances you get with this? I mean, 
>>> why enforce keeping uninitialized memory fragment, while that is just 
>>> a one shot action at load time?
>>>
>>
>> Very often you have buffers in your programs, which you want to have 
>> statically allocated in ram (so they have a fixed address, perhaps 
>> specially aligned, and so you have a full overview of your memory 
>> usage in your map files), but you don't care about the contents at 
>> startup. Clearing these to 0 is just a waste of processor time.
> 
> At startup? Really? Personally I wouldn't care if I waste those cycles.
> 

Usually it is not an issue, but it can be for some systems.  I've seen 
systems where a hardware watchdog has timed out while the startup code 
is clearing large buffers unnecessarily.  There are also some low-power 
systems that are halted until some external event triggers their reset - 
you want to get to the code that checks the reset source (reset pin or 
power on) as fast as possible, and you want much of your data to remain 
preserved over soft resets.

And maybe your buffers are allocated in external dynamic ram which is 
not accessible until you have configured the ram controller - and 
thereafter it is accessible as normal ram.  For one project I have at 
the moment, the chip's on-chip ram blocks can be allocated individually 
to data tightly coupled memory, instruction tightly coupled memory, or 
general-purpose ram - all at different addresses in the memory map.  You 
do not want anything cleared until the blocks have been re-mapped from 
their default settings to their final settings.


> And having that explicitly "vocalized" in sources, I think it'll just 
> make them harder to read by a maintainer.
> 

It is even harder to read if it is not explicit in the C sources, but 
only in the linker files!


> Otherwise, from my personal experience, it may or may not be desirable.
> 
>>
>>
>>>> 7. Convenient support for sections (or variables) placed at specific 
>>>> addresses, in a standardised way.
>>>
>>> Hmm... Frankly, I'm quite comfortable with current features of linker 
>>> script, and I do it like this:
>>> SECTIONS
>>> {
>>>      sfr_devices 0x40000000 (NOLOAD): {
>>>          . = ALIGN(1K);    PROVIDE(TIM2 =    .);
>>>          . = 0x00400;    PROVIDE(TIM3 =    .);
>>>          . = 0x00800;    PROVIDE(TIM4 =    .);
>>>      }
>>> }
>>>
>>> The only problem is that so far I'm not aware of command line options 
>>> to "supplement" default linker script with such fragment. Option "-T" 
>>> replaces it, which is a nuisance.
>>
>> These are ugly and hard to maintain in practice - the most common way 
>> to give fixed addresses is to use macros that cast the fixed address 
>> to pointers to volatile objects and structs.
> 
> Yes, I know that macros are traditionally used here, but personally I 
> think using them is just hideous. I'm using the above section 
> definitions for years and they keep my c-sources nice and clean. And (in 
> particular with stm32) if I change the target device, I just change the 
> linker script and don't usually have to change the sources. That's 
> really nice. It's like efortless porting.
> 
> Having said that. I'm opened to suggestion how to get this better - like 
> having a compiler "talk to linker" about those locations.
> 

There are always more than one way to do these things.  But I believe 
most programmers prefer to stick to the C (and/or C++) source files, and 
avoid anything involving linker files or assembly files.  We are looking 
for ideas that could suit a wide range of people, not just you or I 
personally :-)

>>
>> But sometimes it is nice to have sections at specific addresses, and 
>> it would be a significant gain for most people if these could be 
>> defined entirely in C (or C++), without editing linker files.  Many 
>> embedded toolchains support such features - "int reg @ 0x1234;", or 
>> similar syntax.  gcc has an "address" attribute for the AVR, but not 
>> as a common attribute.  (It is always annoying when one target has an 
>> attribute that would be useful on other ports, but only exists on the 
>> one target.)
> 
> Yes, I know that. Then again (personally) I do prefer to be able to tell 
> the compiler "-mcpu=atmega128" ... and so have it select appropriate 
> linker script, while NOT changing my sources, then do it the other way 
> around.
> 
> [----------------]
>>>
>>> Extrapolating your words: Do you think of sections that you would 
>>> have full control on it's content at compilation, and it isn't 
>>> sufficient to do it like this:
>>> char private[] __attribute__((section("something"))) = {
>>>   0xFF, 0x01, 0x02, ....
>>> };
>>>
>>
>> You also need control of the allocation (or lack thereof).  This can 
>> be done using sections with flags and/or linker file setup, but again 
>> it would be good to have a standardised GCC extension for it.  It is 
>> far easier for people to use a GCC attribute than to learn about the 
>> messy details of section flags and linker files.
> 
> OK. But IMHO, should you move the functionality from linker to GCC, then 
> all the "mess" just get transferred upstairs. And to know the linker is 
> a must if you do a bare-metal programming anyway.
> 

I like having my messes in one place, rather than scattered around :-)

> Still, standardization is good, good, good. But how to you standardize 
> something "private" by definition?

You have to pick the right level of standardisation.  I don't believe 
any of this should be at the level of the C standards, for example.  But 
I think it should be possible to get a generalisation within GCC, so 
that it is "standard" across all targets rather than having 
target-specific attributes or extensions like named address spaces. 
It's fine for GCC to say that this feature is only guaranteed to work 
for binutils gas and ld, or compatible assemblers and linkers, with elf 
outputs.  That gives you a "standard" for most use-cases.

> 
> [------------]
>>>> 11. Convenient support for building up tables where the contents are 
>>>> scattered across different source files, without having to manually 
>>>> edit the linker files.
>>>
>>> do you have an example where that is useful?
>>
>> You might like to have a code organisation where source files could 
>> define structures for, say, threads.  Each of these would need an 
>> entry in a thread table holding priorities, run function pointer, 
>> etc.  If this table were built up as a single section where each 
>> thread declaration contributed their part of it, then the global 
>> thread table would be built at link time rather than traditional run 
>> time setup.  The advantages include a clear static measure of the 
>> number of the number of threads (see point 9), clear memory usage, and 
>> smaller initialisation code.  (Obviously we are talking about 
>> statically defined threads here, not dynamically defined threads.)
> 
> I still don' get it. (pt.9 - sizes/locations of sections available to 
> compiler? relevant to this?)
> 
> Then again. I wouldn't aspire to understand everything. If that's 
> useful, let it be.
> 
> But I'd object to call this constructs "a table". A programmer should 
> have control of how compiler interprets his/her words. "table" has a 
> very well defined semantics and to have it the way you propose ... it'd 
> be better to have a different name/syntax for those other objects.
> 

I don't think "table" /does/ have well defined semantics.  But I do 
think this would be a table!

When you use C++, you already get a table like this for global 
constructors and other initialisation code.  Sometimes the 
initialisation for a variable - especially class objects where there is 
a non-trivial constructor - requires some code to be run.  When 
compiling a C++ file, every time the compiler needs to run some 
initialisation code, it generates a little function, and then makes a 
".ctors.xxx" section containing a pointer to that function.  In the 
linker, there is a section like this:

             . = ALIGN(4);
             KEEP (*crtbegin.o(.ctors))
             KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
             KEEP (*(SORT(.ctors.*)))
             KEEP (*crtend.o(.ctors))

The ".ctors" section in crtbegin.o defines a "start of constructors 
table" symbol, and the matching section in ctrend.o has the end symbol. 
Linking collects all these constructor pointers into a table, and the 
C++ start up code can run through the table calling all the functions in 
order.

I want to be able to do something similar, with a convenient syntax, but 
with my own choice of tables and contents.





  reply	other threads:[~2023-07-06 12:53 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-27 12:26 Rafał Pietrak
2023-06-28  1:54 ` waffl3x
2023-06-28  7:13   ` Rafał Pietrak
2023-06-28  7:31     ` Jonathan Wakely
2023-06-28  8:35       ` Rafał Pietrak
2023-06-28  9:56         ` waffl3x
2023-06-28 10:43           ` Rafał Pietrak
2023-06-28 12:12             ` waffl3x
2023-06-28 12:23               ` Rafał Pietrak
2023-07-03 14:52         ` David Brown
2023-07-03 16:29           ` Rafał Pietrak
2023-07-04 14:20             ` Rafał Pietrak
2023-07-04 15:13               ` David Brown
2023-07-04 16:15                 ` Rafał Pietrak
2023-06-28  7:34     ` waffl3x
2023-06-28  8:41       ` Rafał Pietrak
2023-06-28 13:00 ` Martin Uecker
2023-06-28 14:51   ` Rafał Pietrak
2023-06-28 15:44     ` Richard Earnshaw (lists)
2023-06-28 16:07       ` Martin Uecker
2023-06-28 16:49         ` Richard Earnshaw (lists)
2023-06-28 17:00           ` Martin Uecker
2023-06-28 16:48       ` Rafał Pietrak
2023-06-29  6:19       ` Rafał Pietrak
2023-07-03 15:07         ` Ian Lance Taylor
2023-07-03 16:42           ` Rafał Pietrak
2023-07-03 16:57             ` Richard Earnshaw (lists)
2023-07-03 17:34               ` Rafał Pietrak
2023-07-04 12:38             ` David Brown
2023-07-04 12:57               ` Oleg Endo
2023-07-04 14:46               ` Rafał Pietrak
2023-07-04 15:55                 ` David Brown
2023-07-04 16:20                   ` Rafał Pietrak
2023-07-04 22:57                 ` Martin Uecker
2023-07-05  5:26                   ` Rafał Pietrak
2023-07-05  7:29                     ` Martin Uecker
2023-07-05  8:05                       ` Rafał Pietrak
2023-07-05  9:11                         ` David Brown
2023-07-05  9:25                           ` Martin Uecker
2023-07-05 11:34                             ` David Brown
2023-07-05 12:01                               ` Martin Uecker
2023-07-05  9:42                           ` Rafał Pietrak
2023-07-05 11:55                             ` David Brown
2023-07-05 12:25                               ` Rafał Pietrak
2023-07-05 12:57                                 ` David Brown
2023-07-05 13:29                                   ` Rafał Pietrak
2023-07-05 14:45                                     ` David Brown
2023-07-05 16:13                                       ` Rafał Pietrak
2023-07-05 17:39                                         ` David Brown
2023-07-06  7:00                                           ` Rafał Pietrak
2023-07-06 12:53                                             ` David Brown [this message]
2023-07-05  9:29                         ` Martin Uecker
2023-07-05 10:17                           ` Rafał Pietrak
2023-07-05 10:48                             ` Martin Uecker

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='u86dgn$13qa$1@ciao.gmane.io' \
    --to=david@westcontrol.com \
    --cc=gcc@gcc.gnu.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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).