[LLVMdev] Evaluation of offsetof() macro

350 views
Skip to first unread message

Vadim Chugunov

unread,
Jan 2, 2015, 5:01:02 AM1/2/15
to LLVM Developers Mailing List
Hi!
LLVM has a class, ConstantExpr, that is very handy for compile-time evaluation of const expressions.   Unfortunately I cannot find any methods in it that would be helpful in evaluation of expressions similar to this: (uintptr_t)(&(*(TYPE*)0).FIELD), which is basically the implementation of the offsetof(TYPE, FIELD) macro.  Specifically, there seem to be no provisions for dereferencing a pointer.

Does LLVM have any facilities (that I missed), that would help language front-ends in dealing with this sort of expressions?
Obviously, clang does it somehow, but so far I was not able to locate the relevant bit of code.  Any pointers would be appreciated!

Vadim

David Majnemer

unread,
Jan 2, 2015, 5:23:55 AM1/2/15
to Vadim Chugunov, LLVM Developers Mailing List
On Fri, Jan 2, 2015 at 1:58 AM, Vadim Chugunov <vad...@gmail.com> wrote:
Hi!
LLVM has a class, ConstantExpr, that is very handy for compile-time evaluation of const expressions.   Unfortunately I cannot find any methods in it that would be helpful in evaluation of expressions similar to this: (uintptr_t)(&(*(TYPE*)0).FIELD), which is basically the implementation of the offsetof(TYPE, FIELD) macro.

I think the closest entity for this sort of thing is LLVM's ConstantExpr::getOffsetOf.
 
Specifically, there seem to be no provisions for dereferencing a pointer.

Does LLVM have any facilities (that I missed), that would help language front-ends in dealing with this sort of expressions?
Obviously, clang does it somehow, but so far I was not able to locate the relevant bit of code.  Any pointers would be appreciated!

Clang handles record types in a very abstract way, it doesn't rely on LLVM IR at any level. An ASTRecordLayout is built for a record type and the ASTRecordLayout::getFieldIndex method is used to determine the offset for a particular field.
 


Vadim

_______________________________________________
LLVM Developers mailing list
LLV...@cs.uiuc.edu         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev


Vadim Chugunov

unread,
Jan 2, 2015, 5:56:32 AM1/2/15
to David Majnemer, LLVM Developers Mailing List
On Fri, Jan 2, 2015 at 2:20 AM, David Majnemer <david.m...@gmail.com> wrote:


On Fri, Jan 2, 2015 at 1:58 AM, Vadim Chugunov <vad...@gmail.com> wrote:
Hi!
LLVM has a class, ConstantExpr, that is very handy for compile-time evaluation of const expressions.   Unfortunately I cannot find any methods in it that would be helpful in evaluation of expressions similar to this: (uintptr_t)(&(*(TYPE*)0).FIELD), which is basically the implementation of the offsetof(TYPE, FIELD) macro.

I think the closest entity for this sort of thing is LLVM's ConstantExpr::getOffsetOf.

Certainly, but I think this requires either making `offsetof` a first-class operation in the source language, or handling the folding of <pointer deref>-<field select>-<get-address-of> combo in the front-end.
 
Specifically, there seem to be no provisions for dereferencing a pointer.

Does LLVM have any facilities (that I missed), that would help language front-ends in dealing with this sort of expressions?
Obviously, clang does it somehow, but so far I was not able to locate the relevant bit of code.  Any pointers would be appreciated!

Clang handles record types in a very abstract way, it doesn't rely on LLVM IR at any level. An ASTRecordLayout is built for a record type and the ASTRecordLayout::getFieldIndex method is used to determine the offset for a particular field.

 So it handles all const expression evaluation in the front-end? 

David Majnemer

unread,
Jan 2, 2015, 6:59:14 PM1/2/15
to Vadim Chugunov, LLVM Developers Mailing List
Yes, clang has it's own constant expression evaluator which understands the rules of C++.

Let's take an example.
The expression (long)&x/(long)&y divides two globals by each other.  This expression is lowered to the following LLVM IR Constant:
i64 sdiv (i64 ptrtoint (i32* @x to i64), i64 ptrtoint (i32* @y to i64))

This Constant is a ConstantExpr but certainly not indicative of something that would be 'constexpr' in C++.

Vadim Chugunov

unread,
Jan 2, 2015, 8:29:33 PM1/2/15
to David Majnemer, LLVM Developers Mailing List

 So it handles all const expression evaluation in the front-end? 


Yes, clang has it's own constant expression evaluator which understands the rules of C++.

Let's take an example.
The expression (long)&x/(long)&y divides two globals by each other.  This expression is lowered to the following LLVM IR Constant:
i64 sdiv (i64 ptrtoint (i32* @x to i64), i64 ptrtoint (i32* @y to i64))

This Constant is a ConstantExpr but certainly not indicative of something that would be 'constexpr' in C++.

My goal is to be able to use the result in constexpr contexts (like declaring an array, whose size expression involves offsetof()).   Please correct me if this is wrong, but I think this means that the expression must be evaluated before any IR is emitted.

Joerg Sonnenberger

unread,
Jan 3, 2015, 4:27:08 PM1/3/15
to llv...@cs.uiuc.edu
On Fri, Jan 02, 2015 at 05:26:42PM -0800, Vadim Chugunov wrote:
> My goal is to be able to use the result in constexpr contexts (like
> declaring an array, whose size expression involves offsetof()). Please
> correct me if this is wrong, but I think this means that the expression
> must be evaluated before any IR is emitted.

Do you start from offsetof() or the expanded form? For various reasons,
it is normally defined to use __builtin_offsetof, since the problems you
have run into also stop the "legacy" C version from being appropoiate
for C++ as it doesn't create an ICE.

Joerg

Vadim Chugunov

unread,
Jan 3, 2015, 9:04:23 PM1/3/15
to LLVM Developers Mailing List
Do you start from offsetof() or the expanded form? For various reasons,
it is normally defined to use __builtin_offsetof, since the problems you
have run into also stop the "legacy" C version from being appropoiate
for C++ as it doesn't create an ICE.

I start with a macro, but I was considering expanding it to pointer arithmetic, to avoid creating special operators such as __builtin_offsetof.   Would that be considered a bad idea?

Joerg Sonnenberger

unread,
Jan 4, 2015, 2:53:16 AM1/4/15
to llv...@cs.uiuc.edu
You found the problems with dealing with pointer arithmetic already.
Dealing with the (existing) builtin is much easier. It also helps to
give some diagnostics for illegal use, e.g. non-POD arguments in C++
mode.
Reply all
Reply to author
Forward
0 new messages