<div dir="ltr">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:<div><br></div><div><div><div>struct G;</div><div>extern const G g;</div><div>void fun(const G *g);</div>
<div>int main() {</div><div>  fun(&g);</div><div>}</div></div><div><br></div><div>However, it seems reasonable to make the declaration constant as an optimization if we happen to have the complete type.</div><div><br>
</div><div>Reid</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 6, 2013 at 8:35 AM, Robert Lytton <span dir="ltr"><<a href="mailto:robert@xmos.com" target="_blank">robert@xmos.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">




<div>
<div style="direction:ltr;font-size:10pt;font-family:Tahoma">Hi,<br>
<br>
I have narrowed the issue down to CodeGenModule::GetOrCreateLLVMGlobal()<br>
This I assume is due to the uncertainty of whether a ctor/dtor will need to run on the 'const' data.<br>
<br>
During CodeGenModule::EmitGlobalVarDefinition() the code explicitly checks the ctor/dtor situation:<br>
 // If it is safe to mark the global 'constant', do so now.<br>
  GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor &&<br>
                  isTypeConstant(D->getType(), true));<br>
<br>
However this is only done for definitions and not declarations.<br>
Should declarations be handled in a similar way?<br>
<br>
Dumping the state of the 'VarDecl *D' for the example in the previous emails gives:<br>
<br>
GetOrCreateLLVMGlobal<br>
VarDecl 0x333c230 <test.cpp:5:3, col:23> i 'const int [2]' static<br>
const int identifier[2]<br>
isTypeConstant true<br>
<br>
GetOrCreateLLVMGlobal<br>
VarDecl 0x337eed0 <test.cpp:13:3, col:25> j 'const struct S':'const struct S' static<br>
const struct S identifier<br>
isTypeConstant false<br>
<br>
EmitGlobalVarDefinition<br>
GetOrCreateLLVMGlobal<br>
VarDecl 0x337f7f0 parent 0x337ece0 prev 0x337eed0 <test.cpp:17:1, col:27> j 'const struct S':'const struct S'<br>
`-InitListExpr 0x337f920 <col:23, col:27> 'const struct S':'const struct S'<br>
  |-IntegerLiteral 0x337f890 <col:24> 'int' 1<br>
  `-IntegerLiteral 0x337f8b0 <col:26> 'int' 2<br>
const struct S identifier<br>
NeedsGlobalCtor false<br>
NeedsGlobalDtor false<br>
isTypeConstant true<br>
<br>
GetOrCreateLLVMGlobal<br>
VarDecl 0x337fb80 <test.cpp:21:3, col:25> k 'const struct S':'const struct S' static<br>
const struct S identifier<br>
isTypeConstant false<br>
<br>
<br>
<div style="font-size:16px;font-family:'Times New Roman'">
<hr>
<div style="direction:ltr"><font color="#000000" face="Tahoma"><b>From:</b> Robert Lytton<br>
<b>Sent:</b> 06 December 2013 14:41<br>
<b>To:</b> <a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a><br>
<b>Subject:</b> static const structures declared as "external global %struct.S" instead of "external constant %struct.S"<br>
</font><br>
</div><div><div class="h5">
<div></div>
<div>
<div style="direction:ltr;font-size:10pt;font-family:Tahoma">Hi,<br>
<br>
I have a problem relating to the way clang handles static const structure declarations in c++ classes.<br>
<br>
If only the declaration is visible:<br>
<font color="black" face="Tahoma"><span dir="ltr" style="font-size:10pt">    class K {static const struct S k; ...}</span></font><font color="black" face="Tahoma"><span dir="ltr" style="font-size:10pt"><br>
</span></font>the constness is not emitted in the declaration:<br>
<font color="black" face="Tahoma"><span dir="ltr" style="font-size:10pt">    @_ZN1K1kE = external global %struct.S<br>
should this not be:</span></font><br>
<font color="black" face="Tahoma"><span dir="ltr" style="font-size:10pt">    @_ZN1K1kE = external
</span></font><font color="black" face="Tahoma"><span dir="ltr" style="font-size:10pt"><font color="black" face="Tahoma"><span dir="ltr" style="font-size:10pt">constant</span></font> %struct.S</span></font><br>
<br>
If the definition is visible too:<br>
<font color="black" face="Tahoma"><span dir="ltr" style="font-size:10pt">    class J {static const struct S j;...}<br>
    const struct S J::j = {1,2};</span></font><br>
we get a global 'const' definition, viz:<br>
<font color="black" face="Tahoma"><span dir="ltr" style="font-size:10pt">    @_ZN1J1jE = constant %struct.S { i32 1, i32 2 }, align 4<br>
</span></font><br>
It should be noted that the handling of arrays always uses const - see below.<br>
<br>
Am I correct in believing this is a bug?<br>
Can anyone direct me to where the problem may reside?<br>
<br>
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.<br>
<br>
Robert<br>
<br>
<br>
<font color="black" face="Tahoma"><span dir="ltr" style="font-size:10pt">struct S{int s1; int s2;};<br>
<br>
class I {<br>
  static const int i[2];<br>
  static int ii();<br>
};<br>
int I::ii(){return i[0];}<br>
// I::i defined else where - OK<br>
<br>
class J {<br>
  static const struct S j;<br>
  static struct S jj();<br>
};<br>
struct S J::jj(){return j;}<br>
const struct S J::j = {1,2};<br>
<br>
<br>
class K {<br>
  static const struct S k;<br>
  static struct S kk();<br>
};<br>
struct S K::kk(){return k;}<br>
// K::k defined else where - const is lost<br>
<br>
<br>
%struct.S = type { i32, i32 }<br>
@_ZN1I1iE = external constant [2 x i32]<br>
@_ZN1J1jE = constant %struct.S { i32 1, i32 2 }, align 4<br>
@_ZN1K1kE = external global %struct.S<br>
<br>
define i32 @_ZN1I2iiEv() #0 align 2 {<br>
entry:<br>
  %0 = load i32* getelementptr inbounds ([2 x i32]* @_ZN1I1iE, i32 0, i32 0), align 4<br>
  ret i32 %0<br>
}<br>
<br>
define void @_ZN1J2jjEv(%struct.S* noalias sret %agg.result) #0 align 2 {<br>
entry:<br>
  %0 = bitcast %struct.S* %agg.result to i8*<br>
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* bitcast (%struct.S* @_ZN1J1jE to i8*), i32 8, i32 4, i1 false)<br>
  ret void<br>
}<br>
<br>
define void @_ZN1K2kkEv(%struct.S* noalias sret %agg.result) #0 align 2 {<br>
entry:<br>
  %0 = bitcast %struct.S* %agg.result to i8*<br>
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* bitcast (%struct.S* @_ZN1K1kE to i8*), i32 8, i32 4, i1 false)<br>
  ret void<br>
}</span></font><br>
<br>
</div>
</div>
</div></div></div>
</div>
</div>

<br>_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div></div></div>