Go Down

Topic: Compile-time checking of function arguments... (Read 365 times) previous topic - next topic

westfw

If I have a function that is often called with constants for arguments, like say:

Code: [Select]
   digitalWrite(int pin, int state);


I could consider writing a wrapper:
Code: [Select]
   static inline digitalWrite(unsigned int pin, int state) {
      if (__builtin_constant_p(pin) && pin > PIN_MAX) {
         compileTimeError("Invalid Pin number");
      }
      if (__builtin_constant_p(state) && !(state == INPUT || state == OUTPUT || state == INPUT_PULLUP)
         compileTimeError("Invalid Pin State");
      _digitalWrite_internal(pin, state);
   }

In the case where the arguments are constants, this will either generate an error at compile time when it can show meaningful error messages, or optimize down to zero code in the binary, so it has an upside but no apparent downside.
In the case where the arguments are not constants, it still optimizes down to nothing, and the function that already existed may or may not do it's own run-time error checking (but has more of a problem reporting the error.)

  • Is there some reason I shouldn't do this?  I guess it becomes dependent on gcc-specific compiler features...
  • is there a way to get the compiler to do this sort of thing automatically?  It seems like one of those things than C++ would jump on.

Coding Badly


That is precisely how Teensyduino gains a huge boost for the digital I/O functions.

Paul Stoffregen handled all four cases fordigitalWrite.  From what I could tell the gains for variable / constant and constant / variable are marginal and added a significant amount of code so I left them out of Tiny Core 2.  If you think it would be helpful I may be able to find the discussion.  As an added bonus a const array (think port addresses and bit numbers) is also optimized to simple constants when the index is a constant (Yeah GCC!).

In Tiny Core 2 I had a single array definition that was included in two places: 1. In the header file with the digital functions to be used by the inline digital functions; 2. In the CPP file with the "normal" digital functions.  The definition in the header file was always optimized to simple constants because the array index was always a constant.

That sort of construct is a great way to explore speed / size trade-offs.  For example, the digital I/O functions always reduce to less code for constant parameters (one or two machine instructions which is less than loading registers then making a call).

Quote
is there a way to get the compiler to do this sort of thing automatically?
I have a vague recollection of trying to automate the task using template but giving up.


westfw

In this case, I'm not talking about having the binaries "improved", or even changed at all.  The only thing the added "constant case" code would do is range checking that would be eliminated by optimization anyway.

Coding Badly


Ah.  Got it.

Quote
Is there some reason I shouldn't do this?
I can't come up with a reason to avoid it.  (Other than the one you mentioned.)

Quote
is there a way to get the compiler to do this sort of thing automatically?
I'm not seeing it.


Go Up