[cfe-dev] How to create a new builtin in clang?
    Andy Gibbs 
    andyg1001 at hotmail.co.uk
       
    Sat May 19 03:18:10 PDT 2012
    
    
  
Hi Jonathan,
On Friday, May 18, 2012 9:32 PM, Jonathan Sauer wrote:
> Hello Andy,
>
>>> Maybe I'm missing something, but constexpr does exactly that
>>
>> It does and it doesn't.  If you declare a variable 'constexpr'
>> then you can expect that a compile-time-evaluated constant is
>> assigned to it.  However, a 'constexpr'-declared variable is
>> forever immutable [...]
>
> So far, so good. Although I don't see why the immutability should
> be a problem; after all, you can simply say:
>
> constexpr int firstValue = ...;
> int i = firstValue;
> ...
> constexpr int secondValue = ...;
> i = secondValue;
>
> [...] When using constexpr on a variable, this means that the
> variable's value must be a compile-time constant [...]
Yes, you are right: this is a work-around and certainly works.  However, I 
wouldn't call it a clean solution, I'm afraid.  In effect, it requires that 
every time we want to ensure something is compile-time folded (I'm trying to 
use the terms as Richard Smith in his post [1] defines them), we have to 
remember to explicitly declare a constexpr variable to hold the value and 
then assign the "working" variable to this value.
Let's extend the field of the problem a bit.  Let's say, for arguments sake, 
we have a constexpr function which takes a string and calculates an 
arbitrary CRC value from it.  Such a function may have a signature similar 
to:
    template <long Polynomial>
    constexpr auto calc_CRC(const char* string)
        -> poly_to_width<Polynomial>::type;
The function here takes the CRC polynomial as a template parameter, 
calculates the appropriate CRC from the provided string and returns the 
value in a suitably-sized integer (calculated by a helper struct named 
poly_to_width).
Since the polynomial can change, then a pre-calculated lookup table approach 
is not practical: instead the algorithm must use a bit-based approach.  This 
is much, much less efficient than the lookup table method and wouldn't want 
to be used at runtime.  However, there is nothing in the C++11 standard, 
that I know of, that stops someone using this algorithm in a non-constexpr 
way.  As the library writer, I can say to my users, you must use this 
function this way:
constexpr int temp_value = calc_CRC<32>("string");
int value = temp_value;
but I can't stop them from simply doing:
char* string = ...
int value = calc_CRC<32>(string);
This is what I meant in my previous post regarding 'constexpr' being little 
more than a hint to the compiler like 'inline'.  With constexpr you get the 
additional benefit of being able to use that function at compile-time (as 
long as you can rework your algorithm in a way that complies with the 
restrictions of a constexpr function) but you don't have a way of limiting 
its use solely to compile-time.  Note that even the following is a runtime 
evaluation when compiled with clang without optimisations switched on:
int value = calc_CRC<32>("string");
Now at this point, we can start doing some tricks.  We can hide the 
implementation behind a macro:
template <typename T, T V> struct Constant { static constexpr T value = 
V; };
#define calc_CRC(N,S) Constant<poly_to_width<N>::type, 
calc_CRC_impl<N>(S)>::value
Now the following use:
char* string = ...
int value = calc_CRC(32, string);
will result in a compiler error since string is not a constant expression.
In this case, our work-around works.  However, it works because calc_CRC 
returns an integer type.  If we had a constexpr function which returned a 
floating point value, or one wrapped in a struct, this work-around would 
fail.  What I wish to create is the generic solution which works for all 
return types, such that the macro becomes:
#define my_func(...) __builtin_fold(my_func_impl(...))
In Richard Smith's post [1] is a really intriguing macro solution involving 
folding via __builtin_constant_p and ?: which I believe is a gcc 
extension(?), but I need to think this through thoroughly and test it.
Regards,
Andy
[1] http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-May/021549.html
 
    
    
More information about the cfe-dev
mailing list