[cfe-dev] How to create a new builtin in clang?

Andy Gibbs andyg1001 at hotmail.co.uk
Sat May 19 07:54:57 PDT 2012


On Friday, May 18, 2012 9:13 PM, Richard Smith wrote:

> OK. The first thing you need to be aware of is that 'folded
> to a constant' is not the same as 'evaluated as a constant
> expression'. The former case just means "take an expression,
> and use any tricks we know to reduce it to a compile-time
> constant". The latter means following the relevant language
> standards, which is a nebulous affair [...]

Firstly, thank you for such a detailed reply.  I have read it through now several times to be sure I understand everything!

>From what you say, just to be sure I do understand, the range of expressions that can be "folded" is a super-set of those "evaluated to a constant expression" in C++11 terms, which is in turn a super-set of those which are "integer constant expressions" of C++98 / C.

So, what I am looking for is the first thing, i.e. to use "any tricks we know" to reduce an expression to a compile-time constant, which should mean, as an example, any calls to functions should be eliminated.  If they cannot be, then by extension the expression cannot be folded, and the compiler should at this point stop with an error message to that effect.

As I mentioned in my post to Jonathan Sauer (http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-May/021554.html), one such use case for this is to limit the possibility of using what may be necessarily-inefficient compile-time algorithms accidentally in a run-time environment.

> Additionally, the set of things we can fold is slightly
> different in the different languages. Anyway, the point is,
> outside of C++11, we don't really have an implemented,
> checkable notion of 'constant expression' other than
> 'integer constant expression'.

Doesn't Expr::EvaluateAsRValue(...) fill this criteria?

> For what it's worth, if you want something which folds
> expressions, I think you can already build that [...]

Unfortunately, I couldn't get your suggestion to work in my tests.  Here's some sample code:

struct assert_foldable_t { int arr[1]; };
#define fold(X) (__builtin_constant_p(1)?(X):(X))
#define ignore(X) ((int)!(X))
#define assert_foldable(X) ((void)(struct assert_foldable_t){.arr[ignore(fold(X))]=1})
#define builtin_fold(X) (assert_foldable(X),fold(X))

constexpr double X() {
    return 5.0;
}

int main() {
    double i = builtin_fold(12.0 / X());
    printf("%f\n", i);
    return 0;
}

It does at least stop compilation if the expression is not foldable, but it doesn't produce code as though I had written "double i = 2.4" which is what my aim is (I checked the output using -S -emit-llvm).

I also liked your solution using lambdas (I'd actually considered a similar solution before), although as you say, it won't work outside a C++11 environment.  Also, you can't use it to assign to a constexpr variable so it can't be used as a generic solution, although this is in this case a minor thing.

> If you want to add a new builtin for this, you should
> search through the codebase to find the places where
> builtins are currently handled, and add the relevant
> support for your builtin there. [...]

Thank you for the pointers; I will have a nose around and see what I can do!  The way I have been approaching it so far is to use Parser::ParseAssignmentExpression then Expr::EvaluateAsRValue which returns an APValue which is the constant I'm looking for.  If any of these steps fail, I can generate some diagnostics and stop.  Next, my understanding and maybe you can confirm whether I'm right, is that I need to then turn my APValue into an Expr object.  There doesn't seem to be a direct function available for doing this, but I could use IntegerLiteral or FloatingLiteral for these types, and extract Expr directly from APValue if it is an LValue type.  Other APValue types may be more difficult, but its a starting point.  Is this the best route to take, do you think?

> However, I think a better feature (and one which I would
> definitely support pushing into trunk clang) would be an
> attribute which can be applied to declarations (maybe
> [[clang::const_init]]) [...]

I agree that I can certainly see an advantage to this feature.  I'll have a look into this too.

Thanks again,

Andy

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120519/0699f2b0/attachment.html>


More information about the cfe-dev mailing list