Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

evaluating/accessing a structure

Consider the two slightly different versions of the same code:

struct s
{
  int dummy[1];
};

volatile struct s s;

int main(void)
{
  s;
  return 0;
}

and

struct s
{
  int dummy[16];
};

volatile struct s s;

int main(void)
{
  s;
  return 0;
}

Here's what I'm getting with gcc 4.6.2 for them:

_main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        call    ___main
        movl    _s, %eax
        xorl    %eax, %eax
        leave
        ret

        .comm   _s, 4, 2

and

_main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        call    ___main
        xorl    %eax, %eax
        leave
        ret

        .comm   _s, 64, 5

Please note the absence of access to s in the second case.

Is it a compiler bug or am I just dealing with the following statement of the C standard and the gcc developers simply chose such a weird implementation-definedness and are still playing by the rules?:

What constitutes an access to an object that has volatile-qualified type is implementation-defined.

What would be the reason for this difference? I'd naturally expect the whole structre being accessed (or not accessed, I'm not sure), irrespective of its size and of what's inside it.

P.S. What does your compiler (non-gcc or newer gcc) do in this case? (please answer this last question in a comment if that's the only part you're going to address, as this isn't the main question being asked, but more of a curiosity question).

like image 305
Alexey Frunze Avatar asked Dec 03 '13 04:12

Alexey Frunze


People also ask

How do you evaluate the structure?

Most common steps for structural evaluation are as follows: a) Reviewing available information on the building. b) Conducting a condition survey of the building. c) Determining the cause and rate of progression of existing distress. d) Determining the degree of repair required.

How do you analyze an organisational structure?

Use organizational charts, meet with department managers, executives and board members and conduct a survey to determine where changes in organizational structure may be necessary.

What are the 4 characteristics of a good structure?

Important characteristics of an organization's structure include span of control, departmentalization, centralization, and decentralization.

What are the factors that can be used in assessing the structure of an organization?

Although many things can affect the choice of an appropriate structure for an organization, the following five factors are the most common: size, life cycle, strategy, environment, and technology. The larger an organization becomes, the more complicated its structure.


1 Answers

There is a difference between C and C++ for this question which explains what's going on.

clang-3.4

When compiling either of these snippets as C++, the emitted assembly didn't reference s in either case. In fact a warning was issued for both:

volatile.c:8:2: warning: expression result unused; assign into a variable to force a volatile load [-Wunused-volatile-lvalue] s;

These warnings were not issued when compiling in C99 mode. As mentioned in this blog post and this GCC wiki entry from the question comments, using s in this context causes an lvalue-to-rvalue conversion in C, but not in C++. This is confirmed by examining the Clang AST for C, as there is an ImplicitCastExpr from LvalueToRValue, which does not exist in the AST generated from C++. (The AST is not affected by the size of the struct).

A quick grep of the Clang source reveals this in the emission of aggregate expressions:

case CK_LValueToRValue:
// If we're loading from a volatile type, force the destination
// into existence.
if (E->getSubExpr()->getType().isVolatileQualified()) {
  EnsureDest(E->getType());
  return Visit(E->getSubExpr());
}

EnsureDest forces the emission of a stack slot, sized and typed for the expression. As the optimizers are not allowed to remove volatile accesses, they remain as a scalar load/store and a memcpy respectively in both the IR and output asm. This is the behavior I would expect, given the above.

gcc-4.8.2

Here, I observe the same behavior as in the question. However when I change the expression from s; to s.dummy;, the access does not appear in either version. I'm not familiar with the internals of gcc as I am with LLVM so I can't speculate why this would happen. But based on the above observations, I would say this is a compiler bug due to inconsistency.

like image 103
jared_schmitz Avatar answered Oct 12 '22 13:10

jared_schmitz