<div dir="ltr">No, there's no way to disable this conversion. What's happening here is that the base class has four bytes of tail padding, and the derived class is storing it's data in it.<div><br></div><div>Consider this two-class hierarchy:</div><div>struct A { virtual void f(); int a; };</div><div>struct B : A { int b; };</div><div><br></div><div>The layout for A, in the form offset : field, is:</div><div>0 : void* vtable</div><div>8 : int a</div><div>12 : 4 bytes of padding</div><div>16 : total size</div><div><br></div><div>The layout for B is:</div><div>0 : A</div><div>12 : int b</div><div><br></div><div>LLVM IR struct types having tail padding, so we cannot use the exact same type that we would normally use for B. In the past, we've talked about rearranging things like this:</div><div><br></div><div>%struct.A = type <{ i32 (...)**, i32 }></div><div>%struct.A.complete = type { %struct.A, [4 x i8] }</div><div>%struct.B = type { %struct.A, i32 }</div><div>; no struct.B.complete since sizeof(B) % alignof(B) == 0</div><div><br></div><div>The standard LLVM struct type (%struct.A) would be the layout for the type if it is used as a non-virtual base. The complete struct type (%struct.A.complete) is the type as it would be stored in memory (with tail padding) and including any virtual bases. We can always use the nvbase LLVM IR struct type inside derived class types because it never has tail padding.</div><div><br></div><div>This would be a disruptive change, but I'd be happy to review patches for it.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 19, 2015 at 9:30 AM, Panning, Benjamin J <span dir="ltr"><<a href="mailto:benjamin.j.panning@intel.com" target="_blank">benjamin.j.panning@intel.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div lang="EN-US" link="blue" vlink="purple">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Hi David,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Thank you for your response. The –target I’m using is “x86_64-pc-win”, and in order to see the output, my test uses the following code below the class definitions:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:#1f497d"> TestClass3 g_test3;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:#1f497d"> TestClass1 *g_test1Ptr = &g_test3;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Without this code, the types end up being eliminated.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Unfortunately we have an optimization pass that crawls this type information and requires that base class types be present in derived class types. The pass
breaks down when the base class types are replaced with byte array types.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Would you happen to know if there is any way to disable the conversion of the base class type to byte array type?<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Thanks,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Ben<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif""> David Majnemer [mailto:<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>]
<br>
<b>Sent:</b> Sunday, May 17, 2015 7:31 PM<br>
<b>To:</b> Panning, Benjamin J<br>
<b>Cc:</b> <a href="mailto:llvmdev@cs.uiuc.edu" target="_blank">llvmdev@cs.uiuc.edu</a><br>
<b>Subject:</b> Re: [LLVMdev] Clang question on x86-64 class type definitions<u></u><u></u></span></p><div><div class="h5">
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<p class="MsoNormal">On Fri, May 15, 2015 at 4:48 PM, Panning, Benjamin J <<a href="mailto:benjamin.j.panning@intel.com" target="_blank">benjamin.j.panning@intel.com</a>> wrote:<u></u><u></u></p>
<div>
<div>
<p class="MsoNormal">Hi All,<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">I have a question on the type definitions that Clang generates when compiling for x86-64. Here is the C++ code that I compile:<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> class TestClass1 {<u></u><u></u></p>
<p class="MsoNormal"> int X;<u></u><u></u></p>
<p class="MsoNormal"> public:<u></u><u></u></p>
<p class="MsoNormal"> virtual int Foo() { return 1; }<u></u><u></u></p>
<p class="MsoNormal"> };<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> class TestClass2 : public TestClass1 {<u></u><u></u></p>
<p class="MsoNormal"> int X;<u></u><u></u></p>
<p class="MsoNormal"> public:<u></u><u></u></p>
<p class="MsoNormal"> virtual int Foo() { return 1; }<u></u><u></u></p>
<p class="MsoNormal"> };<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> class TestClass3 : public TestClass2 {<u></u><u></u></p>
<p class="MsoNormal"> int X;<u></u><u></u></p>
<p class="MsoNormal"> public:<u></u><u></u></p>
<p class="MsoNormal"> virtual int Foo() { return 1; }<u></u><u></u></p>
<p class="MsoNormal"> };<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">Here is the command lines that I am using, for 32-bit and 64-bit mode respectively:<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> clang.exe -S -emit-llvm -O0 test.cpp -o test.ll<u></u><u></u></p>
<p class="MsoNormal"> clang.exe -S -emit-llvm -O0 test.cpp -o test.ll -march=x86-64<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">The 32-bit compile produces this, which I understand:<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> %class.TestClass3 = type { %class.TestClass2, i32 }<u></u><u></u></p>
<p class="MsoNormal"> %class.TestClass2 = type { %class.TestClass1, i32 }<u></u><u></u></p>
<p class="MsoNormal"> %class.TestClass1 = type { i32 (...)**, i32 }<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">The 64-bit compile produces this:<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> %class.TestClass3 = type { %class.TestClass2, i32, [4 x i8] }<u></u><u></u></p>
<p class="MsoNormal"> %class.TestClass2 = type { [12 x i8], i32 }<u></u><u></u></p>
<p class="MsoNormal"> %class.TestClass1 = type { i32 (...)**, i32 }<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">A few basic questions: (1) Why does TestClass2 have a [12 x i8] array instead of a reference to TestClass1?
<u></u><u></u></p>
</div>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">What triple are you using? I cannot reproduce your %class.TestClass2 type.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<p class="MsoNormal">(2) What is the [4 x i8] array at the end of TestClass3?<u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">The record is eight byte aligned because of the vptr at offset 0. Those 32-bytes are for padding to align the record's size to a multiple of the alignment (8 bytes in this example).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<p class="MsoNormal">(3) Is it safe to use a bitcast instead of a getelementptr constant expression for casting a TestClass3* to a TestClass1* in this case (I see no other way of doing it…)?<u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Yes, it is perfectly safe to use bitcast instead of gep here.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">I’m not very knowledgeable about Clang, and I greatly appreciate your help.<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">Thanks,<br>
Ben<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
</div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu" target="_blank">LLVMdev@cs.uiuc.edu</a> <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><u></u><u></u></p>
</blockquote>
</div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
</div>
</div></div></div>
</div>
<br>_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a> <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
<br></blockquote></div><br></div>