Skip to main content

Module objsize

Module objsize 

Source
Expand description

The answer to every object_size the front end left for the IR.

Design: spec/optimizer/20-idioms-and-libcalls.md section 20.2, and spec/13-gnu-compat.md section 13.5 for the builtin itself.

The checker answers __builtin_object_size where it can see the object by looking at the expression, and leaves Opcode::ObjectSize behind where it cannot. What is left is an address read out of a variable, and inside a function that variable is usually one of a handful of addresses a branch or a loop chose between, as in r = l == 1 ? &a.buf1[5] : &a.buf2[4]. The IR as the front end writes it has every one of those in front of it: the variable is a block parameter and each branch to its block passes one address, which is an alloca or a global with constant offsets on top. This walks that and writes the answer in as a constant.

§When it runs

Before every other pass and at every level, because nothing after the front end is allowed to see the instruction. The _chk folds in crate::libcall run next and read the answer as the constant they compare a count against, which is the order gcc’s own object size pass and its _chk folds run in. At -O0 nothing is walked and every question gets the answer that says nothing, which is what gcc 16.2.0 gives at that level for an address in a variable.

§What the walk believes

A fixed alloca is its size and a dynamic one of a constant count is that count. A global is its size where extents::vouched says the definition in the module is the one that will run. A ptr_add of a constant count takes it off what is left, down to nothing past the end, and one going backwards is not followed. A block parameter is every argument every branch to its block passes and a select is both of its arms. Anything else is not known.

The kinds asking for the largest answer take the largest of a choice and the kinds asking for the smallest take the smallest, and not knowing any part of a choice is not knowing the whole of it. A loop is the one place that needs thought. A parameter reached again while its own answer is being worked out is the pointer carried round the loop unchanged or moved forward, which can only leave less, so for the largest it adds nothing to the choice. Moved backwards it could leave more, and that is why a backwards ptr_add is never followed. For the smallest the same holds where the pointer comes round unchanged, and one moved forward each time round may leave as little as anything, so there the smallest is not known.

The closest member, which is the low bit of the kind, is not something the IR remembers. The whole object is an answer no smaller than the member for the largest, so the first kind’s answer stands for the second. For the smallest it could be too big, so the fourth kind is not known here and only the checker ever answers it.

Functions§

answer
Answers every object_size in the module and says how many there were.