DIP62: Volatile type qualifier for unoptimizable variables in embedded programming
Walter Bright via Digitalmars-d
digitalmars-d at puremagic.com
Tue Jul 15 23:38:21 PDT 2014
On 7/15/2014 10:15 PM, Johannes Pfau wrote:
> Yes, I actually tried tested that simple implementation with gdc. With
> aggressive optimizations the code inlines just fine and it'll generate
> the same asm as an access to a volatile variable in C. But it's not
> space-effecient: Even if it inlines, the function is still in the
> object file as a distinct function. There's TypeInfo and there's the
> assert(this), there's an initializer symbol and I guess there could be
> copy constructors as well. I expect many bug reports/fixes till we get
> a Volatile!T wrapper to be really space-efficient.
D is intended to have a robust enough feature set in order to implement types as
library types rather than builtin, and have them operate as good as a builtin
type would. These are more general issues, and are not specific to volatile.
>>>> 3. if you really hate peek/poke calls appearing in the code, you
>>>> can use UFCS to make them look like variables
>>> But you cant do REGISTER.peek() |= 0b1;
>> As you mentioned in the DIP, read-modify-write operations should be
>> split up, as their semantics are murky.
> But not necessarily in user code. REGISTER |= is quite common in C and
> it's perfectly safe.
The point is it is not perfectly safe. There is no definition, and certainly no
portable definition, as to how many read/write cycles such an operation entails.
That's what I meant, and DIP62 says pretty much said the same thing. Please
allow me to quote:
"CISC machines may allow other operations to memory than simple load/store
operations. The question is then if a read-modify-write operation like 'x++'
should translate to 'r = load x; r++; x = store r' or to a single add
instruction 'add x;'. This DIP does not dictate any specific behaviour, but this
is recommended: If it is known that instructions operating on memory do not work
for memory mapped IO as expected, compilers should default to generating a
load/modify/store sequence. Otherwise compilers should generate the same code
sequence as for regular variables. It is recommended to provide a compiler
switch on CISC architectures to allow the user to choose between these two
different behaviours."
> If people will have to split this up into peek |=
> poke that's a step backwards from C.
Support for op= is fairly simple for VolatilePointerToUint to implement, and it
can implement them in terms of peek/poke for precise and portable semantics.
>>> A few months
>>> ago you suggested namespaces for D - in addition to modules - which
>>> would have lead to a complexity disaster.
>> C++ namespaces are now implemented in D, and will they lead to
>> complexity disaster? Certainly not in the implementation. For users?
>> I don't think so, but we'll see.
> You were initially in favor of an option which would have allowed to
> use namespaces in D code as well (namespace A {}). The current
> implementation is mostly limited to C++ so that's better, but my point
> was that nobody cared about complexity back then.
I objected to several proposals for namespace support that I regarded as
significantly more complex.
>>> This just shows the priorities of the project leads:
>>> Desktop apps matter, we add @nogc, c++ namespaces, shared,
>>> immutable, const, -cov, ...
>>> but for embedded systems we won't even add one qualifier.
>>
>> I don't think this is the right argument. It isn't about embedded
>> systems should be acknowledged with a qualifier. I see it as about
>> how often does MMIO logic appear in an actual embedded program? In
>> the embedded systems I've written, it only appears in a handful of
>> places. It is not pervasive.
>
> But it's not only about frequency, it's also about convenience and
> safety. How often is opDispatch actually used? The synchronized
> statement? Nevertheless they are there, because someone thought these
> use cases are important enough.
The synchronized statement was something I thought would be widely used. It
turns out to be largely a failure. opDispatch is actually pretty simple, and I
believe it is an "enabling" feature that hasn't, but will, come into its own.
Nevertheless, we should not follow the trap of "we made a mistake on A, so that
justifies making another mistake B". Nor should we say "feature X has reasons
A,B,C,D, therefore reason D is justification enough for other things." Changes
to D must stand/fall on their own merits.
> The perceived importance of a special qualifier for MMIO code is highly
> subjective,
Of course. There is no doubt that both yours and my opinions here are subjective.
> but I think that most embedded programmers would say it's
> necessary.
I do believe that a wrapper type around peek/poke satisfies essentially all your
necessary requirements, except for transitivity.
> In Andrei's Leverage talk he said (5:57): "Consider this:
> Convenience, modeling power, efficiency: [...] You gonna have to have a
> large language. This is a fact of life. [...]". We have
> weak pure/ strong pure & immutable for functional programming, A
> complete set of OO primitives, builtin unit tests, code coverage, ... I
> think it's a correct argument to say that you think embedded system
> programming is not important enough for the additional complexity
> introduced by a new qualifier.
That is not what I'm saying at all. Please do not conflate disagreement about
the best way to achieve a goal with disagreement about the goal.
I understand that you and others put a lot of work into DIP62. As I said before,
it's a very nice example of a well-done DIP.
More information about the Digitalmars-d
mailing list