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