<div dir="ltr">On Thu, Aug 22, 2013 at 5:14 PM, David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<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">On Thu, Aug 22, 2013 at 5:08 PM, David Majnemer<br>
<div><div class="h5"><<a href="mailto:david.majnemer@gmail.com">david.majnemer@gmail.com</a>> wrote:<br>
> On Thu, Aug 22, 2013 at 4:02 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:<br>
>><br>
>><br>
>> On Aug 22, 2013 3:02 PM, "David Majnemer" <<a href="mailto:david.majnemer@gmail.com">david.majnemer@gmail.com</a>><br>
>> wrote:<br>
>> ><br>
>> > Hi dblaikie, echristo,<br>
>> ><br>
>> > We wouldn't emit DW_AT_location for DW_TAG_template_value_parameter if<br>
>> > the value the non-type template parameter had was casted.  This happens<br>
>> > even if there is no textual cast written.<br>
>> ><br>
>> > <a href="http://llvm-reviews.chandlerc.com/D1478" target="_blank">http://llvm-reviews.chandlerc.com/D1478</a><br>
>> ><br>
>> > Files:<br>
>> >   lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp<br>
>> >   test/DebugInfo/non-type-template-arg-cast.ll<br>
>> ><br>
>> > Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp<br>
>> > ===================================================================<br>
>> > --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp<br>
>> > +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp<br>
>> > @@ -1145,6 +1145,7 @@<br>
>> >    if (!VP.getName().empty())<br>
>> >      addString(ParamDIE, dwarf::DW_AT_name, VP.getName());<br>
>> >    if (Value *Val = VP.getValue()) {<br>
>> > +    Val = Val->stripPointerCasts();<br>
>><br>
>> Should we strip the casts in the frontend instead? Perhaps there's some<br>
>> easy way to get the right/simple thing there?<br>
><br>
> If by the "frontend" you mean CGDebugInfo::CollectTemplateParams, then we<br>
> could but I don't know if it would be better. For example, we would need to<br>
> fix this for Expression and Declaration.<br>
<br>
</div></div>Fair enough, if there are two places that would need to be fixed in<br>
the frontend (well, they could presumably be adjusted to fall through<br>
to the same stripping code?) I can live with it here. Don't have a<br>
strong feeling.<br>
<br>
Do you know why these casts are introduced & whether there are any<br>
other things we might see here? (I prefer not to add fixes blindly<br>
without understanding why the fix is necessary)<br></blockquote><div><br></div><div>The casts are introduced because of the padding.</div><div>- Y is struct Type but the ABI requires that we have padding at the end of the struct. So instead, the object Y is an anonymous LLVM struct type with the three padding bytes. The two fields are initialized with zeros and the padding is filled with undefs.</div>
<div>- However, &Y's LLVM type is %struct.Type* and not of type "pointer to anonymous struct type".</div><div><br></div><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 class="h5"><br>
>> >      if (ConstantInt *CI = dyn_cast<ConstantInt>(Val))<br>
>> >        addConstantValue(ParamDIE, CI, VP.getType().isUnsignedDIType());<br>
>> >      else if (GlobalValue *GV = dyn_cast<GlobalValue>(Val)) {<br>
>> > Index: test/DebugInfo/non-type-template-arg-cast.ll<br>
>> > ===================================================================<br>
>> > --- /dev/null<br>
>> > +++ test/DebugInfo/non-type-template-arg-cast.ll<br>
>> > @@ -0,0 +1,83 @@<br>
>> > +; REQUIRES: object-emission<br>
>> > +<br>
>> > +; RUN: llc -O0 -filetype=obj < %s > %t<br>
>> > +; RUN: llvm-dwarfdump %t | FileCheck %s<br>
>> > +<br>
>> > +; This was created from the following source:<br>
>> > +; struct Type {<br>
>> > +;   unsigned int Data1;<br>
>> > +;   unsigned short Data2, Data3;<br>
>> > +;   unsigned char Data4;<br>
>> > +; };<br>
>><br>
>> Is this the simplest class that demonstrates the problem?<br>
><br>
> No, I've simplified it a bit.<br>
>><br>
>> > +; template<const Type *G><br>
>> > +; const Type *func() {<br>
>> > +;   return G;<br>
>> > +; }<br>
>> > +<br>
>> > +; extern const Type Y;<br>
>><br>
>> Do you need the extern declaration?<br>
><br>
> If I don't declare it as extern, I get a warning about using a C++11<br>
> extension.<br>
<br>
</div></div>Which extension would that be?<br></blockquote><div><br></div><div>warning: non-type template argument referring to object 'Y' with internal linkage is a C++11 extension [-Wc++11-extensions]<br></div>
<div> </div><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 class="im"><br>
> I guess we don't care about it here though. The patch is updated<br>
> to reflect this.<br>
<br>
</div>Dropping the const might be nice too - just to keep it simple.<br>
<br>
Type Y;<br>
int main() {<br>
  func<&Y>();<br>
}<br></blockquote><div><br></div><div>Will do.</div><div> </div><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">

<br>
Also - I think we have an existing test case for non-type template<br>
parameters (test/DebugInfo/X86/templates.ll, probably?) - would this<br>
be reasonable to add there instead of adding a new test file?<br>
<div class=""><div class="h5"><br>
>><br>
>> > +; const Type Y = {};<br>
>> > +; int main() {<br>
>> > +;   func<&Y>();<br>
>> > +; }<br>
>> > +<br>
>> > +; CHECK: DW_TAG_template_value_parameter<br>
>> > +; CHECK-NEXT: DW_AT_type<br>
>> > +; CHECK-NEXT: DW_AT_name<br>
>> > +; CHECK-NEXT: DW_AT_location<br>
>> > +; CHECK: NULL<br>
>> > +<br>
>> > +%struct.Type = type { i32, i16, i16, i8 }<br>
>> > +<br>
>> > +@Y = constant { i32, i16, i16, i8, [3 x i8] } { i32 0, i16 0, i16 0, i8<br>
>> > 0, [3 x i8] undef }, align 4<br>
>> > +<br>
>> > +; Function Attrs: uwtable<br>
>> > +define i32 @main() #0 {<br>
>> > +entry:<br>
>> > +  %call = call %struct.Type* @_Z4funcIXadL_Z1YEEEPK4Typev(), !dbg !28<br>
>> > +  ret i32 0, !dbg !29<br>
>> > +}<br>
>> > +<br>
>> > +; Function Attrs: nounwind uwtable<br>
>> > +define linkonce_odr %struct.Type* @_Z4funcIXadL_Z1YEEEPK4Typev() #1 {<br>
>> > +entry:<br>
>> > +  ret %struct.Type* bitcast ({ i32, i16, i16, i8, [3 x i8] }* @Y to<br>
>> > %struct.Type*), !dbg !30<br>
>> > +}<br>
>> > +<br>
>> > +attributes #0 = { uwtable "less-precise-fpmad"="false"<br>
>> > "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true"<br>
>> > "no-infs-fp-math"="false" "no-nans-fp-math"="false"<br>
>> > "stack-protector-buffer-size"="8" "unsafe-fp-math"="false"<br>
>> > "use-soft-float"="false" }<br>
>> > +attributes #1 = { nounwind uwtable "less-precise-fpmad"="false"<br>
>> > "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true"<br>
>> > "no-infs-fp-math"="false" "no-nans-fp-math"="false"<br>
>> > "stack-protector-buffer-size"="8" "unsafe-fp-math"="false"<br>
>> > "use-soft-float"="false" }<br>
>> > +<br>
>> > +!<a href="http://llvm.dbg.cu" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
>> > +!llvm.module.flags = !{!27}<br>
>> > +<br>
>> > +!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang<br>
>> > version 3.4 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2,<br>
>> > metadata !3, metadata !25, metadata !2, metadata !""} ; [<br>
>> > DW_TAG_compile_unit ]<br>
>> > [/usr/local/google/home/majnemer/llvm/build//var/tmp/dlb.cpp]<br>
>> > [DW_LANG_C_plus_plus]<br>
>> > +!1 = metadata !{metadata !"/var/tmp/dlb.cpp", metadata<br>
>> > !"/usr/local/google/home/majnemer/llvm/build"}<br>
>> > +!2 = metadata !{i32 0}<br>
>> > +!3 = metadata !{metadata !4, metadata !9}<br>
>> > +!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"main",<br>
>> > metadata !"main", metadata !"", i32 14, metadata !6, i1 false, i1 true, i32<br>
>> > 0, i32 0, null, i32 256, i1 false, i32 ()* @main, null, null, metadata !2,<br>
>> > i32 14} ; [ DW_TAG_subprogram ] [line 14] [def] [main]<br>
>> > +!5 = metadata !{i32 786473, metadata !1}          ; [ DW_TAG_file_type<br>
>> > ] [/usr/local/google/home/majnemer/llvm/build//var/tmp/dlb.cpp]<br>
>> > +!6 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0,<br>
>> > i64 0, i64 0, i32 0, null, metadata !7, i32 0, i32 0} ; [<br>
>> > DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]<br>
>> > +!7 = metadata !{metadata !8}<br>
>> > +!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32,<br>
>> > i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32,<br>
>> > align 32, offset 0, enc DW_ATE_signed]<br>
>> > +!9 = metadata !{i32 786478, metadata !1, metadata !5, metadata<br>
>> > !"func<&Y>", metadata !"func<&Y>", metadata !"_Z4funcIXadL_Z1YEEEPK4Typev",<br>
>> > i32 8, metadata !10, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1<br>
>> > false, %struct.Type* ()* @_Z4funcIXadL_Z1YEEEPK4Typev, metadata !23, null,<br>
>> > metadata !2, i32 8} ; [ DW_TAG_subprogram ] [line 8] [def] [func<&Y>]<br>
>> > +!10 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0,<br>
>> > i64 0, i64 0, i32 0, null, metadata !11, i32 0, i32 0} ; [<br>
>> > DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]<br>
>> > +!11 = metadata !{metadata !12}<br>
>> > +!12 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64,<br>
>> > i64 64, i64 0, i32 0, metadata !13} ; [ DW_TAG_pointer_type ] [line 0, size<br>
>> > 64, align 64, offset 0] [from ]<br>
>> > +!13 = metadata !{i32 786470, null, null, metadata !"", i32 0, i64 0,<br>
>> > i64 0, i64 0, i32 0, metadata !14} ; [ DW_TAG_const_type ] [line 0, size 0,<br>
>> > align 0, offset 0] [from Type]<br>
>> > +!14 = metadata !{i32 786451, metadata !1, null, metadata !"Type", i32<br>
>> > 1, i64 96, i64 32, i32 0, i32 0, null, metadata !15, i32 0, null, null} ; [<br>
>> > DW_TAG_structure_type ] [Type] [line 1, size 96, align 32, offset 0] [def]<br>
>> > [from ]<br>
>> > +!15 = metadata !{metadata !16, metadata !18, metadata !20, metadata<br>
>> > !21}<br>
>> > +!16 = metadata !{i32 786445, metadata !1, metadata !14, metadata<br>
>> > !"Data1", i32 2, i64 32, i64 32, i64 0, i32 0, metadata !17} ; [<br>
>> > DW_TAG_member ] [Data1] [line 2, size 32, align 32, offset 0] [from unsigned<br>
>> > int]<br>
>> > +!17 = metadata !{i32 786468, null, null, metadata !"unsigned int", i32<br>
>> > 0, i64 32, i64 32, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ] [unsigned<br>
>> > int] [line 0, size 32, align 32, offset 0, enc DW_ATE_unsigned]<br>
>> > +!18 = metadata !{i32 786445, metadata !1, metadata !14, metadata<br>
>> > !"Data2", i32 3, i64 16, i64 16, i64 32, i32 0, metadata !19} ; [<br>
>> > DW_TAG_member ] [Data2] [line 3, size 16, align 16, offset 32] [from<br>
>> > unsigned short]<br>
>> > +!19 = metadata !{i32 786468, null, null, metadata !"unsigned short",<br>
>> > i32 0, i64 16, i64 16, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ] [unsigned<br>
>> > short] [line 0, size 16, align 16, offset 0, enc DW_ATE_unsigned]<br>
>> > +!20 = metadata !{i32 786445, metadata !1, metadata !14, metadata<br>
>> > !"Data3", i32 3, i64 16, i64 16, i64 48, i32 0, metadata !19} ; [<br>
>> > DW_TAG_member ] [Data3] [line 3, size 16, align 16, offset 48] [from<br>
>> > unsigned short]<br>
>> > +!21 = metadata !{i32 786445, metadata !1, metadata !14, metadata<br>
>> > !"Data4", i32 4, i64 8, i64 8, i64 64, i32 0, metadata !22} ; [<br>
>> > DW_TAG_member ] [Data4] [line 4, size 8, align 8, offset 64] [from unsigned<br>
>> > char]<br>
>> > +!22 = metadata !{i32 786468, null, null, metadata !"unsigned char", i32<br>
>> > 0, i64 8, i64 8, i64 0, i32 0, i32 8} ; [ DW_TAG_base_type ] [unsigned char]<br>
>> > [line 0, size 8, align 8, offset 0, enc DW_ATE_unsigned_char]<br>
>> > +!23 = metadata !{metadata !24}<br>
>> > +!24 = metadata !{i32 786480, null, metadata !"G", metadata !12,<br>
>> > %struct.Type* bitcast ({ i32, i16, i16, i8, [3 x i8] }* @Y to<br>
>> > %struct.Type*), null, i32 0, i32 0} ; [ DW_TAG_template_value_parameter ]<br>
>> > +!25 = metadata !{metadata !26}<br>
>> > +!26 = metadata !{i32 786484, i32 0, null, metadata !"Y", metadata !"Y",<br>
>> > metadata !"", metadata !5, i32 13, metadata !13, i32 0, i32 1, { i32, i16,<br>
>> > i16, i8, [3 x i8] }* @Y, null} ; [ DW_TAG_variable ] [Y] [line 13] [def]<br>
>> > +!27 = metadata !{i32 2, metadata !"Dwarf Version", i32 3}<br>
>> > +!28 = metadata !{i32 15, i32 0, metadata !4, null}<br>
>> > +!29 = metadata !{i32 16, i32 0, metadata !4, null}<br>
>> > +!30 = metadata !{i32 9, i32 0, metadata !9, null}<br>
><br>
><br>
</div></div></blockquote></div><br></div></div>