[cfe-dev] static const structures declared as "external global %struct.S" instead of "external constant %struct.S"

Reid Kleckner rnk at google.com
Fri Dec 6 10:29:58 PST 2013


The type of the global doesn't have to be complete, so clang can't really
know if it will be constant.  This is valid:

struct G;
extern const G g;
void fun(const G *g);
int main() {
  fun(&g);
}

However, it seems reasonable to make the declaration constant as an
optimization if we happen to have the complete type.

Reid

On Fri, Dec 6, 2013 at 8:35 AM, Robert Lytton <robert at xmos.com> wrote:

>  Hi,
>
> I have narrowed the issue down to CodeGenModule::GetOrCreateLLVMGlobal()
> This I assume is due to the uncertainty of whether a ctor/dtor will need
> to run on the 'const' data.
>
> During CodeGenModule::EmitGlobalVarDefinition() the code explicitly checks
> the ctor/dtor situation:
>  // If it is safe to mark the global 'constant', do so now.
>   GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor &&
>                   isTypeConstant(D->getType(), true));
>
> However this is only done for definitions and not declarations.
> Should declarations be handled in a similar way?
>
> Dumping the state of the 'VarDecl *D' for the example in the previous
> emails gives:
>
> GetOrCreateLLVMGlobal
> VarDecl 0x333c230 <test.cpp:5:3, col:23> i 'const int [2]' static
> const int identifier[2]
> isTypeConstant true
>
> GetOrCreateLLVMGlobal
> VarDecl 0x337eed0 <test.cpp:13:3, col:25> j 'const struct S':'const struct
> S' static
> const struct S identifier
> isTypeConstant false
>
> EmitGlobalVarDefinition
> GetOrCreateLLVMGlobal
> VarDecl 0x337f7f0 parent 0x337ece0 prev 0x337eed0 <test.cpp:17:1, col:27>
> j 'const struct S':'const struct S'
> `-InitListExpr 0x337f920 <col:23, col:27> 'const struct S':'const struct S'
>   |-IntegerLiteral 0x337f890 <col:24> 'int' 1
>   `-IntegerLiteral 0x337f8b0 <col:26> 'int' 2
> const struct S identifier
> NeedsGlobalCtor false
> NeedsGlobalDtor false
> isTypeConstant true
>
> GetOrCreateLLVMGlobal
> VarDecl 0x337fb80 <test.cpp:21:3, col:25> k 'const struct S':'const struct
> S' static
> const struct S identifier
> isTypeConstant false
>
>
>  ------------------------------
> *From:* Robert Lytton
> *Sent:* 06 December 2013 14:41
> *To:* cfe-dev at cs.uiuc.edu
> *Subject:* static const structures declared as "external global
> %struct.S" instead of "external constant %struct.S"
>
>   Hi,
>
> I have a problem relating to the way clang handles static const structure
> declarations in c++ classes.
>
> If only the declaration is visible:
>     class K {static const struct S k; ...}
> the constness is not emitted in the declaration:
>     @_ZN1K1kE = external global %struct.S
> should this not be:
>     @_ZN1K1kE = external constant %struct.S
>
> If the definition is visible too:
>     class J {static const struct S j;...}
>     const struct S J::j = {1,2};
> we get a global 'const' definition, viz:
>     @_ZN1J1jE = constant %struct.S { i32 1, i32 2 }, align 4
>
> It should be noted that the handling of arrays always uses const - see
> below.
>
> Am I correct in believing this is a bug?
> Can anyone direct me to where the problem may reside?
>
> This is a problem on the XCore target as we handle constant and
> non-constant data in separate areas and hence will emit different assembler
> instructions.
>
> Robert
>
>
> struct S{int s1; int s2;};
>
> class I {
>   static const int i[2];
>   static int ii();
> };
> int I::ii(){return i[0];}
> // I::i defined else where - OK
>
> class J {
>   static const struct S j;
>   static struct S jj();
> };
> struct S J::jj(){return j;}
> const struct S J::j = {1,2};
>
>
> class K {
>   static const struct S k;
>   static struct S kk();
> };
> struct S K::kk(){return k;}
> // K::k defined else where - const is lost
>
>
> %struct.S = type { i32, i32 }
> @_ZN1I1iE = external constant [2 x i32]
> @_ZN1J1jE = constant %struct.S { i32 1, i32 2 }, align 4
> @_ZN1K1kE = external global %struct.S
>
> define i32 @_ZN1I2iiEv() #0 align 2 {
> entry:
>   %0 = load i32* getelementptr inbounds ([2 x i32]* @_ZN1I1iE, i32 0, i32
> 0), align 4
>   ret i32 %0
> }
>
> define void @_ZN1J2jjEv(%struct.S* noalias sret %agg.result) #0 align 2 {
> entry:
>   %0 = bitcast %struct.S* %agg.result to i8*
>   call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* bitcast (%struct.S*
> @_ZN1J1jE to i8*), i32 8, i32 4, i1 false)
>   ret void
> }
>
> define void @_ZN1K2kkEv(%struct.S* noalias sret %agg.result) #0 align 2 {
> entry:
>   %0 = bitcast %struct.S* %agg.result to i8*
>   call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* bitcast (%struct.S*
> @_ZN1K1kE to i8*), i32 8, i32 4, i1 false)
>   ret void
> }
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131206/ef9a1dd9/attachment.html>


More information about the cfe-dev mailing list