<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Dec 3, 2013 at 11:16 AM, David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.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 class="im">On Mon, Dec 2, 2013 at 8:00 AM, Alexey Samsonov <<a href="mailto:samsonov@google.com">samsonov@google.com</a>> wrote:<br>

> Hi David,<br>
><br>
> Let me outline some ideas I got after reading this code as a<br>
> sanity-check-request - I have too little knowledge of DBG_VALUE machine<br>
> instructions, working with machine functions, etc.<br>
><br>
> On Fri, Nov 1, 2013 at 1:46 AM, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:<br>
>><br>
>> To document some of my own state on this issue (I'm happy to take this<br>
>> into another thread or bug to discuss if people think there's a better<br>
>> context for such discussion)...<br>
>><br>
>> In DwarfDebug::beginFunction there is a bunch of code (that could probably<br>
>> be refactored into some named functions to make it more documented) but<br>
>> here's the basic idea:<br>
>><br>
>> For all MBB<br>
>>   For all MI<br>
>>     if it's a debug value<br>
>>       record the location in the 'history' for this variable<br>
>>       mark the register as in-use by a certain variable (what happens if<br>
>> we end up with two variables in the same register? I don't think this code<br>
>> can handle that)<br>
><br>
><br>
> I agree - there are real-life cases when several variables refer to the same<br>
> register - e.g. in ASan mode addresses of all local variables are defined as<br>
> offsets from $rsp via DBG_VALUE instruction.<br>
> So, instead of [Register]->[Debug variable] mapping we need to have<br>
> [Register] -> [Vector of debug variables] here.<br>
<br>
</div>Fair point. Though are we ever going to indirect through transient<br>
registers? (eg: "variable is in deref(reg+offset) where 'reg' isn't<br>
just the frame register live across the whole function)<br></blockquote><div><br></div><div>Don't know, we might. In ASan we build all code with use-after-return detection support:</div><div><br></div><div><div><div>
define i32 @_Z7my_funci(i32 %a) #0 {</div><div>entry:</div><div>  %MyAlloca = alloca [224 x i8], align 32  //<--------------------------------------- actual stack frame</div><div>  %0 = ptrtoint [224 x i8]* %MyAlloca to i64</div>
<div>  %1 = load i32* @__asan_option_detect_stack_use_after_return</div><div>  %2 = icmp ne i32 %1, 0</div><div>  br i1 %2, label %3, label %5</div><div><br></div><div>; <label>:3                                       ; preds = %entry</div>
<div>  %4 = call i64 @__asan_stack_malloc_2(i64 224, i64 %0)   <------------- "fake stack frame" returned by ASan runtime</div><div>  br label %5</div><div><br></div><div>; <label>:5                                       ; preds = %entry, %3</div>
<div>  %6 = phi i64 [ %0, %entry ], [ %4, %3 ]  <------------------------------ pointer to actual or fake stack frame, where all the local variables are located.</div><div><...></div><div>  %9 = add i64 %6, 96</div>
<div>  %10 = inttoptr i64 %9 to i32*   <--------------------------------------------- user variable, given as offset into either actual or fake stack frame</div></div></div><div><...></div><div><div>  call void @llvm.dbg.declare(metadata !{i32* %10}, metadata !18)</div>
</div><div><br></div><div>I can imaging the situation where "%6" won't be spilled on stack, and we'll have to report variable location</div><div>as "reg storing %6 + offset" (I didn't verify this happens, though).</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>
If the only indirection is for stack cases, then we don't need to<br>
worry about clobbers I think - well, not in the traditional sense the<br>
way this algorithm is written. We might need to worry about stack<br>
reuse... which could get interesting. I'm not sure how that (lifetime<br>
markers) is modeled.</blockquote><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>
> The code in this branch also inserts a range-terminator instruction between<br>
> a pair DBG_VALUE instrs for the same variable if instructions in this pair<br>
> are from different basic blocks (I assume, this is done for the same<br>
> purpose as inserting range-terminators in the second loop, and it can hurt<br>
> us as well).<br>
<br>
</div>Right - they're both parts of the same general algorithm to terminate<br>
at the end of BBs. There's no actual DBG_VALUE to terminate here, it's<br>
just implicit in this algorithm that the live ranges terminate at the<br>
BB boundary.<br>
<div><div class="h5"><br>
>>     else<br>
>>       if this instruction clobbers any register<br>
>>         if this instruction is in the same MBB as the current defining<br>
>> debug value for the variable<br>
>>           record this instruction in the history (it will act as a debug<br>
>> loc range terminator) of the variable<br>
>><br>
>> For all the variables<br>
>>   If the end of the history is debug value (not a non-debug instruction<br>
>> which would terminate the range)<br>
>>     If that debug value is in a different basic block than the final basic<br>
>> block in the function<br>
>>       add the last instruction in the debug values basic block to the<br>
>> history to terminate the range<br>
>><br>
><br>
> We terminate ranges too early - some registers may not in fact be clobbered<br>
> between two different basic blocks. However, looks like we *have* all the<br>
> information we need - DBG_VALUE instructions and<br>
> register-clobbering instructions - in DwarfDebug::beginFunction(), and<br>
> should just properly compute location ranges. It is nontrivial, though, and<br>
> I think the main purpose range-terminator instructions were added is<br>
> to deal with confusion when MBB has more than one predecessor. We need to<br>
> somehow implement "phi-nodes" for variable locations...<br>
> Suppose we have:<br>
><br>
> MBB1:<br>
>   dbg_loc("x") = %rax<br>
>   jmp MBB3<br>
> MBB2:<br>
>   dbg_loc("x") = %rdx<br>
>   jmp MBB3<br>
> MBB3:<br>
>   // where is "x" now?<br>
><br>
> currently we add dbg_loc("x") = undef at the end of MBB1 and MBB2 for<br>
> safety, but in general we should do a proper analysis.<br>
<br>
</div></div>My thinking is that we shouldn't need to perform an analysis here - we<br>
should rely on the register allocator to tell us what it already knows<br>
about liveness. Recomputing this from an MBB analysis seems like we'd<br>
be redoing work that's already been performed.<br></blockquote><div><br></div><div>I don't understand what liveness information you mean here. Looking at MBB's, we know</div><div>which instruction clobbers which (physical) registers, sets of live-ins for MBBs,</div>
<div>and we know registers each dbg_value instruction refers to. Looks like this is the granularity</div><div>we need - location ranges for each variable in general start and end at some instructions in the</div><div>middle of machine basic blocks. That is, I can't imagine what kind of data we</div>
<div>may need from register allocator that would simplify the location range building.</div><div><br></div><div>Alternatively, we may move calculation of these ranges and insertion of</div><div>location-range-terminatiors earlier, but IMO it's easier to this in AsmPrinter - after all location</div>
<div>ranges rely on labels, so we don't want to do any transformation of MachineFunction once we</div><div>calculated location ranges for variables. </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>
Thing is, things like the frame pointer are sort of "beyond" register<br>
allocation - their blessing and immutability is an underlying<br>
assumption of the whole system. So I'm wondering if the right thing to<br>
do here is to never model frame index and frame pointer reg+offsets as<br>
dbg_values and instead model them in the same way we model allocas<br>
(indeed we could generalize the alloca handling, hopefully).<br></blockquote><div><br></div><div>IIUC, you don't like the following situation happening now: </div><div><br></div><div><div><span class="" style="white-space:pre">       </span>MOV64mr %RSP, 1, %noreg, 48, %noreg, %R8<kill>; mem:ST8[FixedStack6]</div>
<div><span class="" style="white-space:pre">    </span>DBG_VALUE %RSP, 48, !"c"; line no:2</div></div><div><br></div><div>Why build a dbg_value and location range for the address "c" (deref($rsp + 48)), if this</div>
<div>address is spilled into a slot with frame index 6? Maybe it's possible to avoid this,</div><div>but this means we'll have to dive into CodeGen, find the place where it generates</div><div>mentioned dbg_value instruction, and instead of generating tell that location of "c" can</div>
<div>be found using the given stack slot. Or, we should extend dbg_value instruction and allow it to reference</div><div>stack slots, not only registers. I have no idea how to do either of this :(</div><div><br></div><div>
Also, what should we do if location of variable doesn't refer to $rsp or if it changes in the middle</div><div>of function?</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>
This won't solve our general debug info location problems at "above<br>
-O0" where non-frame registers may remain live over basic block<br>
boundaries in novel ways. And that will probably need to be solved one<br>
day - but I'm starting to think that the solution to that still won't<br>
generalize over/solve the stack slot problem we have today. Not that I<br>
know much about this stuff, but I /think/ stack slots are treated so<br>
separately that it wouldn't fall out of the<br>
register-allocator-aware-location stuff we'll need for optimized debug<br>
locations in non-frame registers.<br>
<div><div class="h5"><br>
> Now this looks like a problem, which could be solved by graph traversal :)<br>
> Basically, we may take first instruction and all the DBG_VALUE instructions<br>
> as starting points, and scan all the instructions in the order of execution<br>
> (following jumps), inserting range-terminators if we see a register<br>
> clobbering instruction or if we enter a new MBB and incoming variable<br>
> locations are different.<br>
><br>
> Does it all make sense?<br>
><br>
><br>
>> Hopefully that makes some sense. The bolded text is one of the problematic<br>
>> places - but I don't believe it's correct to simply not do that check (some<br>
>> things do actually get clobbered across basic blocks). It might be as simple<br>
>> as also checking (both at the bolded step, and in the "for all variables"<br>
>> loop) if the register in question is something that won't get clobbered<br>
>> across basic blocks.<br>
>><br>
>> Lang - this still seems rather special-cased. I assume we do some inter-BB<br>
>> register allocation above -O0, so how should we be doing this to get<br>
>> accurate live ranges for our debug variables? Just assuming all registers<br>
>> (except the base pointer?) get clobbered at the end of a basic block seems a<br>
>> bit 'rough' at best, but perhaps I'm wrong.<br>
>><br>
>> - David<br>
>><br>
>> On Tue, Oct 29, 2013 at 3:33 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:<br>
>>><br>
>>> +Alexey who's encountering this in ASan<br>
>>><br>
>>><br>
>>> On Fri, Oct 25, 2013 at 1:28 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>><br>
>>> wrote:<br>
>>>><br>
>>>> Bump because... argh. (I've also reformatted the samples to remove all<br>
>>>> the extra newlines, hopefully).<br>
>>>><br>
>>>> Lang - you want to chat about this some time? Eric & I really aren't<br>
>>>> sure who else to chat to about this.<br>
>>>><br>
>>>>> Eric - this patch seems to be related to the issue I was discussing<br>
>>>>> at/with you yesterday. Specifically the "or when the basic block ends" part<br>
>>>>> is problematic for cases I'm looking at:<br>
>>>><br>
>>>><br>
>>>>><br>
>>>>> struct foo {<br>
>>>>> foo() : i(3) {}<br>
>>>>> foo(const foo& f) : i(f.i) { }<br>
>>>>> int i;<br>
>>>>> };<br>
>>>>> int func(foo f) {<br>
>>>>> if (!f.i)<br>
>>>>> return f.i + 1;<br>
>>>>> return f.i + 2;<br>
>>>>> }<br>
>>>>> int main() {<br>
>>>>> foo l;<br>
>>>>> func(l);<br>
>>>>> }<br>
>>>>><br>
>>>>><br>
>>>>> I get the following assembly for 'func':<br>
>>>>><br>
>>>>> .globl _Z4func3foo<br>
>>>>> .align 16, 0x90<br>
>>>>> .type _Z4func3foo,@function<br>
>>>>> _Z4func3foo: # @_Z4func3foo<br>
>>>>> .cfi_startproc<br>
>>>>> .Lfunc_begin0:<br>
>>>>> .loc 1 7 0 # test.cpp:7:0<br>
>>>>> # BB#0: # %entry<br>
>>>>> pushq %rbp<br>
>>>>> .Ltmp2:<br>
>>>>> .cfi_def_cfa_offset 16<br>
>>>>> .Ltmp3:<br>
>>>>> .cfi_offset %rbp, -16<br>
>>>>> movq %rsp, %rbp<br>
>>>>> .Ltmp4:<br>
>>>>> .cfi_def_cfa_register %rbp<br>
>>>>> #DEBUG_VALUE: func:f <- RDI<br>
>>>>> .loc 1 8 0 prologue_end # test.cpp:8:0<br>
>>>>> .Ltmp5:<br>
>>>>> cmpl $0, (%rdi)<br>
>>>>> movq %rdi, -16(%rbp) # 8-byte Spill<br>
>>>>> .Ltmp6: *no<br>
>>>>> #DEBUG_VALUE: func:f <- [RBP+-16]<br>
>>>>> jne .LBB0_2<br>
>>>>> .Ltmp7:<br>
>>>>> # BB#1: # %if.then<br>
>>>>> .loc 1 9 0 # test.cpp:9:0<br>
>>>>> movq -16(%rbp), %rax # 8-byte Reload<br>
>>>>> movl (%rax), %ecx<br>
>>>>> addl $1, %ecx<br>
>>>>> movl %ecx, -4(%rbp)<br>
>>>>> jmp .LBB0_3<br>
>>>>> .Ltmp8:<br>
>>>>> .LBB0_2: # %if.end<br>
>>>>> .loc 1 10 0 # test.cpp:10:0<br>
>>>>> movq -16(%rbp), %rax # 8-byte Reload<br>
>>>>> movl (%rax), %ecx<br>
>>>>> addl $2, %ecx<br>
>>>>> movl %ecx, -4(%rbp)<br>
>>>>> .LBB0_3: # %return<br>
>>>>> .loc 1 11 0 # test.cpp:11:0<br>
>>>>> movl -4(%rbp), %eax<br>
>>>>> popq %rbp<br>
>>>>> ret<br>
>>>><br>
>>>><br>
>>>>><br>
>>>>> And the debug_loc for 'func:f' is:<br>
>>>>><br>
>>>>> .Ldebug_loc0:<br>
>>>>> .quad .Lfunc_begin0<br>
>>>>> .quad .Ltmp6<br>
>>>>> .Lset0 = .Ltmp53-.Ltmp52 # Loc expr size<br>
>>>>> .short .Lset0<br>
>>>>> .Ltmp52:<br>
>>>>> .byte 117 # DW_OP_breg5<br>
>>>>> .byte 0<br>
>>>>> .Ltmp53:<br>
>>>>> .quad .Ltmp6<br>
>>>>> .quad .Ltmp7<br>
>>>>> .Lset1 = .Ltmp55-.Ltmp54 # Loc expr size<br>
>>>>> .short .Lset1<br>
>>>>> .Ltmp54:<br>
>>>>> .byte 118 # DW_OP_breg6<br>
>>>>> .byte 112<br>
>>>>> .byte 6<br>
>>>>> .Ltmp55:<br>
>>>>><br>
>>>>><br>
>>>>> The important point being that the second range for the variable (for<br>
>>>>> -16(%rbp)) ends at the end of the first basic block. Thus for the range<br>
>>>>> tmp7-func_end we have no location information for this variable.<br>
>>>>><br>
>>>>> This bug appears to manifest on any non-trivial-pass-by-value parameter<br>
>>>>> and any trivial pass-by-value parameter than ends up lowered to LLVM "byval"<br>
>>>>> (if it's split into multiple reg parameters then we must reconstitute it<br>
>>>>> inside the function and then we track the debug info for that reconstituted<br>
>>>>> value - probably an alloca so everything is good at -O0 at least).<br>
>>>>><br>
>>>>> Should we be special casing indirect dbg_values and letting them past<br>
>>>>> the edge of basic blocks?<br>
>>>>> Or only ones relative to the base pointer?<br>
>>>>> Or do we need to have dbg_value MI intrinsics inserted at the beginning<br>
>>>>> of every subsequent basic block to properly communicate where variables are?<br>
>>>>> Or something else entirely.<br>
>>>>><br>
>>>>>> The code is now ready to deal with variables that are sometimes in a<br>
>>>>>> register<br>
>>>>>> and sometimes on the stack. We just need to teach emitDebugLoc to say<br>
>>>>>> 'stack<br>
>>>>>> slot'.<br>
>>>>><br>
>>>>><br>
>>>>> Not sure if this /\ point is relevant, irrelevant, or something that's<br>
>>>>> been addressed since this commit. My best guess is that this comment is just<br>
>>>>> about how we describe stack slots in a location list - in that we could<br>
>>>>> describe them more compactly than reg+offset (by using fbreg instead of<br>
>>>>> breg) and we aren't. That seems like an easy special case of "is the<br>
>>>>> register the frame register, then use fbreg".<br>
>>>>><br>
>>>>>><br>
>>>>>><br>
>>>>>> Modified:<br>
>>>>>>     llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h<br>
>>>>>>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br>
>>>>>>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h<br>
>>>>>>     llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll<br>
>>>>>><br>
>>>>>> Modified: llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h<br>
>>>>>> URL:<br>
>>>>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h?rev=128327&r1=128326&r2=128327&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h?rev=128327&r1=128326&r2=128327&view=diff</a><br>

>>>>>><br>
>>>>>> ==============================================================================<br>
>>>>>> --- llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h (original)<br>
>>>>>> +++ llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h Fri Mar 25<br>
>>>>>> 21:19:36 2011<br>
>>>>>> @@ -309,6 +309,10 @@<br>
>>>>>>    /// instruction in the basic block, or end()<br>
>>>>>>    iterator getLastNonDebugInstr();<br>
>>>>>><br>
>>>>>> +  const_iterator getLastNonDebugInstr() const {<br>
>>>>>> +    return<br>
>>>>>> const_cast<MachineBasicBlock*>(this)->getLastNonDebugInstr();<br>
>>>>>> +  }<br>
>>>>>> +<br>
>>>>>>    /// SplitCriticalEdge - Split the critical edge from this block to<br>
>>>>>> the<br>
>>>>>>    /// given successor block, and return the newly created block, or<br>
>>>>>> null<br>
>>>>>>    /// if splitting is not possible.<br>
>>>>>><br>
>>>>>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br>
>>>>>> URL:<br>
>>>>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=128327&r1=128326&r2=128327&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=128327&r1=128326&r2=128327&view=diff</a><br>

>>>>>><br>
>>>>>> ==============================================================================<br>
>>>>>> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)<br>
>>>>>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Fri Mar 25<br>
>>>>>> 21:19:36 2011<br>
>>>>>> @@ -2408,38 +2408,21 @@<br>
>>>>>>    /// collection info from MMI table.<br>
>>>>>>    collectVariableInfoFromMMITable(MF, Processed);<br>
>>>>>><br>
>>>>>> -  SmallVector<const MachineInstr *, 8> DbgValues;<br>
>>>>>> -  // Collect variable information from DBG_VALUE machine<br>
>>>>>> instructions;<br>
>>>>>> -  for (MachineFunction::const_iterator I = Asm->MF->begin(), E =<br>
>>>>>> Asm->MF->end();<br>
>>>>>> -       I != E; ++I)<br>
>>>>>> -    for (MachineBasicBlock::const_iterator II = I->begin(), IE =<br>
>>>>>> I->end();<br>
>>>>>> -         II != IE; ++II) {<br>
>>>>>> -      const MachineInstr *MInsn = II;<br>
>>>>>> -      if (!MInsn->isDebugValue())<br>
>>>>>> -        continue;<br>
>>>>>> -      DbgValues.push_back(MInsn);<br>
>>>>>> -    }<br>
>>>>>> -<br>
>>>>>> -  // This is a collection of DBG_VALUE instructions describing same<br>
>>>>>> variable.<br>
>>>>>> -  SmallVector<const MachineInstr *, 4> MultipleValues;<br>
>>>>>> -  for(SmallVector<const MachineInstr *, 8>::iterator I =<br>
>>>>>> DbgValues.begin(),<br>
>>>>>> -        E = DbgValues.end(); I != E; ++I) {<br>
>>>>>> -    const MachineInstr *MInsn = *I;<br>
>>>>>> -    MultipleValues.clear();<br>
>>>>>> -    if (isDbgValueInDefinedReg(MInsn))<br>
>>>>>> -      MultipleValues.push_back(MInsn);<br>
>>>>>> -    DIVariable DV(MInsn->getOperand(MInsn->getNumOperands() -<br>
>>>>>> 1).getMetadata());<br>
>>>>>> -    if (Processed.count(DV) != 0)<br>
>>>>>> +  for (SmallVectorImpl<const MDNode*>::const_iterator<br>
>>>>>> +         UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI<br>
>>>>>> != UVE;<br>
>>>>>> +         ++UVI) {<br>
>>>>>> +    const MDNode *Var = *UVI;<br>
>>>>>> +    if (Processed.count(Var))<br>
>>>>>>        continue;<br>
>>>>>><br>
>>>>>> -    for (SmallVector<const MachineInstr *, 8>::iterator MI = I+1,<br>
>>>>>> -           ME = DbgValues.end(); MI != ME; ++MI) {<br>
>>>>>> -      const MDNode *Var =<br>
>>>>>> -        (*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata();<br>
>>>>>> -      if (Var == DV)<br>
>>>>>> -        MultipleValues.push_back(*MI);<br>
>>>>>> -    }<br>
>>>>>> +    // History contains relevant DBG_VALUE instructions for Var and<br>
>>>>>> instructions<br>
>>>>>> +    // clobbering it.<br>
>>>>>> +    SmallVectorImpl<const MachineInstr*> &History = DbgValues[Var];<br>
>>>>>> +    if (History.empty())<br>
>>>>>> +      continue;<br>
>>>>>> +    const MachineInstr *MInsn = History.front();<br>
>>>>>><br>
>>>>>> +    DIVariable DV(Var);<br>
>>>>>>      DbgScope *Scope = NULL;<br>
>>>>>>      if (DV.getTag() == dwarf::DW_TAG_arg_variable &&<br>
>>>>>>          DISubprogram(DV.getContext()).describes(MF->getFunction()))<br>
>>>>>> @@ -2451,6 +2434,7 @@<br>
>>>>>>        continue;<br>
>>>>>><br>
>>>>>>      Processed.insert(DV);<br>
>>>>>> +    assert(MInsn->isDebugValue() && "History must begin with debug<br>
>>>>>> value");<br>
>>>>>>      DbgVariable *RegVar = new DbgVariable(DV);<br>
>>>>>>      if (!addCurrentFnArgument(MF, RegVar, Scope))<br>
>>>>>>        Scope->addVariable(RegVar);<br>
>>>>>> @@ -2458,21 +2442,21 @@<br>
>>>>>>        DbgVariableToDbgInstMap[AbsVar] = MInsn;<br>
>>>>>>        VarToAbstractVarMap[RegVar] = AbsVar;<br>
>>>>>>      }<br>
>>>>>> -    if (MultipleValues.size() <= 1 && !RegClobberInsn.count(MInsn)) {<br>
>>>>>> +<br>
>>>>>> +    // Simple ranges that are fully coalesced.<br>
>>>>>> +    if (History.size() <= 1 || (History.size() == 2 &&<br>
>>>>>> +<br>
>>>>>> MInsn->isIdenticalTo(History.back()))) {<br>
>>>>>>        DbgVariableToDbgInstMap[RegVar] = MInsn;<br>
>>>>>>        continue;<br>
>>>>>>      }<br>
>>>>>><br>
>>>>>>      // handle multiple DBG_VALUE instructions describing one<br>
>>>>>> variable.<br>
>>>>>> -    if (DotDebugLocEntries.empty())<br>
>>>>>> -      RegVar->setDotDebugLocOffset(0);<br>
>>>>>> -    else<br>
>>>>>> -      RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());<br>
</div></div><div><div class="h5">>>>>>> +    RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());<br>
>>>>>><br>
>>>>>> -    for (SmallVector<const MachineInstr *, 4>::iterator<br>
>>>>>> -           MVI = MultipleValues.begin(), MVE = MultipleValues.end();<br>
>>>>>> -         MVI != MVE; ++MVI) {<br>
>>>>>> -      const MachineInstr *Begin = *MVI;<br>
>>>>>> +    for (SmallVectorImpl<const MachineInstr*>::const_iterator<br>
>>>>>> +           HI = History.begin(), HE = History.end(); HI != HE; ++HI)<br>
>>>>>> {<br>
>>>>>> +      const MachineInstr *Begin = *HI;<br>
>>>>>> +      assert(Begin->isDebugValue() && "Invalid History entry");<br>
>>>>>>        MachineLocation MLoc;<br>
>>>>>>        if (Begin->getNumOperands() == 3) {<br>
>>>>>>          if (Begin->getOperand(0).isReg() &&<br>
>>>>>> Begin->getOperand(1).isImm())<br>
>>>>>> @@ -2480,6 +2464,7 @@<br>
>>>>>>        } else<br>
>>>>>>          MLoc = Asm->getDebugValueLocation(Begin);<br>
>>>>>><br>
>>>>>> +      // FIXME: emitDebugLoc only understands registers.<br>
>>>>>>        if (!MLoc.getReg())<br>
>>>>>>          continue;<br>
>>>>>><br>
>>>>>> @@ -2487,17 +2472,23 @@<br>
>>>>>>        const MCSymbol *FLabel = getLabelBeforeInsn(Begin);<br>
>>>>>>        const MCSymbol *SLabel = 0;<br>
>>>>>><br>
>>>>>> -      if (const MachineInstr *ClobberMI =<br>
>>>>>> RegClobberInsn.lookup(Begin))<br>
>>>>>> -        // The register range starting at Begin may be clobbered.<br>
>>>>>> -        SLabel = getLabelAfterInsn(ClobberMI);<br>
>>>>>> -      else if (MVI + 1 == MVE)<br>
>>>>>> -        // If Begin is the last instruction then its value is valid<br>
>>>>>> +      if (HI + 1 == HE)<br>
>>>>>> +        // If Begin is the last instruction in History then its value<br>
>>>>>> is valid<br>
>>>>>>          // until the end of the funtion.<br>
>>>>>>          SLabel = FunctionEndSym;<br>
>>>>>> -      else<br>
>>>>>> -        // The value is valid until the next DBG_VALUE.<br>
>>>>>> -        SLabel = getLabelBeforeInsn(MVI[1]);<br>
>>>>>> +      else {<br>
>>>>>> +        const MachineInstr *End = HI[1];<br>
>>>>>> +        if (End->isDebugValue())<br>
>>>>>> +          SLabel = getLabelBeforeInsn(End);<br>
>>>>>> +        else {<br>
>>>>>> +          // End is a normal instruction clobbering the range.<br>
>>>>>> +          SLabel = getLabelAfterInsn(End);<br>
>>>>>> +          assert(SLabel && "Forgot label after clobber instruction");<br>
>>>>>> +          ++HI;<br>
>>>>>> +        }<br>
>>>>>> +      }<br>
>>>>>><br>
>>>>>> +      // The value is valid until the next DBG_VALUE or clobber.<br>
>>>>>>        DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel,<br>
>>>>>> MLoc));<br>
>>>>>>      }<br>
>>>>>>      DotDebugLocEntries.push_back(DotDebugLocEntry());<br>
>>>>>> @@ -2519,21 +2510,14 @@<br>
>>>>>><br>
>>>>>>  /// getLabelBeforeInsn - Return Label preceding the instruction.<br>
>>>>>>  const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr<br>
>>>>>> *MI) {<br>
>>>>>> -  DenseMap<const MachineInstr *, MCSymbol *>::iterator I =<br>
>>>>>> -    LabelsBeforeInsn.find(MI);<br>
>>>>>> -  if (I == LabelsBeforeInsn.end())<br>
>>>>>> -    // FunctionBeginSym always preceeds all the instruction in<br>
>>>>>> current function.<br>
>>>>>> -    return FunctionBeginSym;<br>
>>>>>> -  return I->second;<br>
>>>>>> +  MCSymbol *Label = LabelsBeforeInsn.lookup(MI);<br>
>>>>>> +  assert(Label && "Didn't insert label before instruction");<br>
>>>>>> +  return Label;<br>
>>>>>>  }<br>
>>>>>><br>
>>>>>>  /// getLabelAfterInsn - Return Label immediately following the<br>
>>>>>> instruction.<br>
>>>>>>  const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI)<br>
>>>>>> {<br>
>>>>>> -  DenseMap<const MachineInstr *, MCSymbol *>::iterator I =<br>
>>>>>> -    LabelsAfterInsn.find(MI);<br>
>>>>>> -  if (I == LabelsAfterInsn.end())<br>
>>>>>> -    return NULL;<br>
>>>>>> -  return I->second;<br>
>>>>>> +  return LabelsAfterInsn.lookup(MI);<br>
>>>>>>  }<br>
>>>>>><br>
>>>>>>  /// beginInstruction - Process beginning of an instruction.<br>
>>>>>> @@ -2552,14 +2536,22 @@<br>
>>>>>>    }<br>
>>>>>><br>
>>>>>>    // Insert labels where requested.<br>
>>>>>> -  if (!InsnNeedsLabel.count(MI))<br>
>>>>>> +  DenseMap<const MachineInstr*, MCSymbol*>::iterator I =<br>
>>>>>> +    LabelsBeforeInsn.find(MI);<br>
>>>>>> +<br>
>>>>>> +  // No label needed.<br>
>>>>>> +  if (I == LabelsBeforeInsn.end())<br>
</div></div><div class="im">>>>>>> +    return;<br>
>>>>>> +<br>
>>>>>> +  // Label already assigned.<br>
>>>>>> +  if (I->second)<br>
>>>>>>      return;<br>
>>>>>><br>
>>>>>>    if (!PrevLabel) {<br>
>>>>>>      PrevLabel = MMI->getContext().CreateTempSymbol();<br>
>>>>>>      Asm->OutStreamer.EmitLabel(PrevLabel);<br>
>>>>>>    }<br>
>>>>>> -  LabelsBeforeInsn[MI] = PrevLabel;<br>
>>>>>> +  I->second = PrevLabel;<br>
>>>>>>  }<br>
>>>>>><br>
>>>>>>  /// endInstruction - Process end of an instruction.<br>
>>>>>> @@ -2569,7 +2561,15 @@<br>
>>>>>>    if (!MI->isDebugValue())<br>
>>>>>>      PrevLabel = 0;<br>
>>>>>><br>
>>>>>> -  if (!InsnsNeedsLabelAfter.count(MI))<br>
</div><div class="im">>>>>>> +  DenseMap<const MachineInstr*, MCSymbol*>::iterator I =<br>
</div>>>>>>> +    LabelsAfterInsn.find(MI);<br>
<div class="im">>>>>>> +<br>
>>>>>> +  // No label needed.<br>
</div><div><div class="h5">>>>>>> +  if (I == LabelsAfterInsn.end())<br>
>>>>>> +    return;<br>
>>>>>> +<br>
>>>>>> +  // Label already assigned.<br>
>>>>>> +  if (I->second)<br>
>>>>>>      return;<br>
>>>>>><br>
>>>>>>    // We need a label after this instruction.<br>
>>>>>> @@ -2577,7 +2577,7 @@<br>
>>>>>>      PrevLabel = MMI->getContext().CreateTempSymbol();<br>
>>>>>>      Asm->OutStreamer.EmitLabel(PrevLabel);<br>
>>>>>>    }<br>
>>>>>> -  LabelsAfterInsn[MI] = PrevLabel;<br>
>>>>>> +  I->second = PrevLabel;<br>
>>>>>>  }<br>
>>>>>><br>
>>>>>>  /// getOrCreateDbgScope - Create DbgScope for the scope.<br>
>>>>>> @@ -2837,8 +2837,8 @@<br>
>>>>>>             RE = Ranges.end(); RI != RE; ++RI) {<br>
>>>>>>        assert(RI->first && "DbgRange does not have first<br>
>>>>>> instruction!");<br>
>>>>>>        assert(RI->second && "DbgRange does not have second<br>
>>>>>> instruction!");<br>
>>>>>> -      InsnNeedsLabel.insert(RI->first);<br>
>>>>>> -      InsnsNeedsLabelAfter.insert(RI->second);<br>
>>>>>> +      requestLabelBeforeInsn(RI->first);<br>
>>>>>> +      requestLabelAfterInsn(RI->second);<br>
>>>>>>      }<br>
>>>>>>    }<br>
>>>>>>  }<br>
>>>>>> @@ -2916,46 +2916,78 @@<br>
>>>>>><br>
>>>>>>    recordSourceLine(Line, Col, TheScope);<br>
>>>>>><br>
>>>>>> +  assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't<br>
>>>>>> cleaned");<br>
>>>>>> +<br>
>>>>>>    /// ProcessedArgs - Collection of arguments already processed.<br>
>>>>>>    SmallPtrSet<const MDNode *, 8> ProcessedArgs;<br>
>>>>>><br>
>>>>>> -  /// LastDbgValue - Refer back to the last DBG_VALUE instruction to<br>
>>>>>> mention MD.<br>
>>>>>> -  DenseMap<const MDNode*, const MachineInstr*> LastDbgValue;<br>
>>>>>> -<br>
>>>>>>    const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();<br>
>>>>>><br>
>>>>>>    /// LiveUserVar - Map physreg numbers to the MDNode they contain.<br>
>>>>>>    std::vector<const MDNode*> LiveUserVar(TRI->getNumRegs());<br>
>>>>>><br>
</div></div>>>>>>>    for (MachineFunction::const_iterator I = MF->begin(), E =<br>
<div class="im">>>>>>> MF->end();<br>
>>>>>> -       I != E; ++I)<br>
</div><div class="im">>>>>>> +       I != E; ++I) {<br>
>>>>>> +    bool AtBlockEntry = true;<br>
</div><div class="im">>>>>>>      for (MachineBasicBlock::const_iterator II = I->begin(), IE =<br>
>>>>>> I->end();<br>
</div><div class="im">>>>>>>           II != IE; ++II) {<br>
>>>>>>        const MachineInstr *MI = II;<br>
>>>>>> -      DebugLoc DL = MI->getDebugLoc();<br>
>>>>>> +<br>
>>>>>>        if (MI->isDebugValue()) {<br>
>>>>>>          assert (MI->getNumOperands() > 1 && "Invalid machine<br>
>>>>>> instruction!");<br>
>>>>>><br>
>>>>>> -        // Keep track of variables in registers.<br>
>>>>>> +        // Keep track of user variables.<br>
>>>>>>          const MDNode *Var =<br>
>>>>>>            MI->getOperand(MI->getNumOperands() - 1).getMetadata();<br>
>>>>>> -        LastDbgValue[Var] = MI;<br>
>>>>>> +<br>
</div><div class="im">>>>>>> +        // Variable is in a register, we need to check for clobbers.<br>
>>>>>>          if (isDbgValueInDefinedReg(MI))<br>
>>>>>>            LiveUserVar[MI->getOperand(0).getReg()] = Var;<br>
>>>>>><br>
>>>>>> -        DIVariable DV(Var);<br>
>>>>>> -        if (!DV.Verify()) continue;<br>
>>>>>> -        // If DBG_VALUE is for a local variable then it needs a<br>
>>>>>> label.<br>
>>>>>> -        if (DV.getTag() != dwarf::DW_TAG_arg_variable)<br>
>>>>>> -          InsnNeedsLabel.insert(MI);<br>
>>>>>> -        // DBG_VALUE for inlined functions argument needs a label.<br>
>>>>>> -        else if (!DISubprogram(getDISubprogram(DV.getContext())).<br>
>>>>>> -                 describes(MF->getFunction()))<br>
>>>>>> -          InsnNeedsLabel.insert(MI);<br>
</div>>>>>>> -        // DBG_VALUE indicating argument location change needs a<br>
>>>>>> label.<br>
>>>>>> -        else if (!ProcessedArgs.insert(DV))<br>
>>>>>> -          InsnNeedsLabel.insert(MI);<br>
>>>>>> +        // Check the history of this variable.<br>
<div class="im">>>>>>> +        SmallVectorImpl<const MachineInstr*> &History =<br>
>>>>>> DbgValues[Var];<br>
>>>>>> +        if (History.empty()) {<br>
</div>>>>>>> +          UserVariables.push_back(Var);<br>
>>>>>> +          // The first mention of a function argument gets the<br>
>>>>>> FunctionBeginSym<br>
>>>>>> +          // label, so arguments are visible when breaking at<br>
>>>>>> function entry.<br>
>>>>>> +          DIVariable DV(Var);<br>
>>>>>> +          if (DV.Verify() && DV.getTag() ==<br>
>>>>>> dwarf::DW_TAG_arg_variable &&<br>
>>>>>> +              DISubprogram(getDISubprogram(DV.getContext()))<br>
>>>>>> +                .describes(MF->getFunction()))<br>
>>>>>> +            LabelsBeforeInsn[MI] = FunctionBeginSym;<br>
>>>>>> +        } else {<br>
>>>>>> +          // We have seen this variable before. Try to coalesce<br>
>>>>>> DBG_VALUEs.<br>
>>>>>> +          const MachineInstr *Prev = History.back();<br>
>>>>>> +          if (Prev->isDebugValue()) {<br>
>>>>>> +            // Coalesce identical entries at the end of History.<br>
>>>>>> +            if (History.size() >= 2 &&<br>
>>>>>> +                Prev->isIdenticalTo(History[History.size() - 2]))<br>
>>>>>> +              History.pop_back();<br>
>>>>>> +<br>
>>>>>> +            // Terminate old register assignments that don't reach<br>
>>>>>> MI;<br>
>>>>>> +            MachineFunction::const_iterator PrevMBB =<br>
>>>>>> Prev->getParent();<br>
>>>>>> +            if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB)<br>
>>>>>> != I) &&<br>
>>>>>> +                isDbgValueInDefinedReg(Prev)) {<br>
>>>>>> +              // Previous register assignment needs to terminate at<br>
>>>>>> the end of<br>
>>>>>> +              // its basic block.<br>
>>>>>> +              MachineBasicBlock::const_iterator LastMI =<br>
>>>>>> +                PrevMBB->getLastNonDebugInstr();<br>
>>>>>> +              if (LastMI == PrevMBB->end())<br>
>>>>>> +                // Drop DBG_VALUE for empty range.<br>
>>>>>> +                History.pop_back();<br>
>>>>>> +              else {<br>
>>>>>> +                // Terminate after LastMI.<br>
>>>>>> +                History.push_back(LastMI);<br>
>>>>>> +              }<br>
>>>>>> +            }<br>
>>>>>> +          }<br>
>>>>>> +        }<br>
>>>>>> +        History.push_back(MI);<br>
>>>>>>        } else {<br>
>>>>>> +        // Not a DBG_VALUE instruction.<br>
>>>>>> +        if (!MI->isLabel())<br>
>>>>>> +          AtBlockEntry = false;<br>
>>>>>> +<br>
>>>>>>          // Check if the instruction clobbers any registers with debug<br>
>>>>>> vars.<br>
>>>>>>          for (MachineInstr::const_mop_iterator MOI =<br>
>>>>>> MI->operands_begin(),<br>
>>>>>>                 MOE = MI->operands_end(); MOI != MOE; ++MOI) {<br>
>>>>>> @@ -2970,19 +3002,57 @@<br>
>>>>>>              LiveUserVar[Reg] = 0;<br>
>>>>>><br>
>>>>>>              // Was MD last defined by a DBG_VALUE referring to Reg?<br>
>>>>>> -            const MachineInstr *Last = LastDbgValue.lookup(Var);<br>
>>>>>> -            if (!Last || Last->getParent() != MI->getParent())<br>
>>>>>> +            DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);<br>
>>>>>> +            if (HistI == DbgValues.end())<br>
>>>>>>                continue;<br>
>>>>>> -            if (!isDbgValueInDefinedReg(Last) ||<br>
>>>>>> -                Last->getOperand(0).getReg() != Reg)<br>
<div class="im">>>>>>> +            SmallVectorImpl<const MachineInstr*> &History =<br>
</div>>>>>>> HistI->second;<br>
>>>>>> +            if (History.empty())<br>
>>>>>>                continue;<br>
>>>>>> -            // MD is clobbered. Make sure the next instruction gets a<br>
>>>>>> label.<br>
>>>>>> -            InsnsNeedsLabelAfter.insert(MI);<br>
>>>>>> -            RegClobberInsn[Last] = MI;<br>
>>>>>> +            const MachineInstr *Prev = History.back();<br>
>>>>>> +            // Sanity-check: Register assignments are terminated at<br>
>>>>>> the end of<br>
>>>>>> +            // their block.<br>
>>>>>> +            if (!Prev->isDebugValue() || Prev->getParent() !=<br>
>>>>>> MI->getParent())<br>
>>>>>> +              continue;<br>
>>>>>> +            // Is the variable still in Reg?<br>
>>>>>> +            if (!isDbgValueInDefinedReg(Prev) ||<br>
>>>>>> +                Prev->getOperand(0).getReg() != Reg)<br>
>>>>>> +              continue;<br>
>>>>>> +            // Var is clobbered. Make sure the next instruction gets<br>
>>>>>> a label.<br>
>>>>>> +            History.push_back(MI);<br>
>>>>>>            }<br>
>>>>>>          }<br>
>>>>>>        }<br>
>>>>>>      }<br>
>>>>>> +  }<br>
>>>>>> +<br>
>>>>>> +  for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E =<br>
>>>>>> DbgValues.end();<br>
<div class="im">>>>>>> +       I != E; ++I) {<br>
</div>>>>>>> +    SmallVectorImpl<const MachineInstr*> &History = I->second;<br>
<div class="im">>>>>>> +    if (History.empty())<br>
>>>>>> +      continue;<br>
>>>>>> +<br>
</div>>>>>>> +    // Make sure the final register assignments are terminated.<br>
>>>>>> +    const MachineInstr *Prev = History.back();<br>
>>>>>> +    if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {<br>
>>>>>> +      const MachineBasicBlock *PrevMBB = Prev->getParent();<br>
>>>>>> +      MachineBasicBlock::const_iterator LastMI =<br>
>>>>>> PrevMBB->getLastNonDebugInstr();<br>
>>>>>> +      if (LastMI == PrevMBB->end())<br>
>>>>>> +        // Drop DBG_VALUE for empty range.<br>
>>>>>> +        History.pop_back();<br>
>>>>>> +      else {<br>
>>>>>> +        // Terminate after LastMI.<br>
>>>>>> +        History.push_back(LastMI);<br>
>>>>>> +      }<br>
>>>>>> +    }<br>
>>>>>> +    // Request labels for the full history.<br>
>>>>>> +    for (unsigned i = 0, e = History.size(); i != e; ++i) {<br>
>>>>>> +      const MachineInstr *MI = History[i];<br>
>>>>>> +      if (MI->isDebugValue())<br>
>>>>>> +        requestLabelBeforeInsn(MI);<br>
>>>>>> +      else<br>
>>>>>> +        requestLabelAfterInsn(MI);<br>
>>>>>> +    }<br>
>>>>>> +  }<br>
>>>>>><br>
>>>>>>    PrevInstLoc = DebugLoc();<br>
>>>>>>    PrevLabel = FunctionBeginSym;<br>
>>>>>> @@ -3043,13 +3113,12 @@<br>
>>>>>>    // Clear debug info<br>
>>>>>>    CurrentFnDbgScope = NULL;<br>
>>>>>>    CurrentFnArguments.clear();<br>
>>>>>> -  InsnNeedsLabel.clear();<br>
>>>>>>    DbgVariableToFrameIndexMap.clear();<br>
>>>>>>    VarToAbstractVarMap.clear();<br>
>>>>>>    DbgVariableToDbgInstMap.clear();<br>
>>>>>>    DeleteContainerSeconds(DbgScopeMap);<br>
>>>>>> -  InsnsNeedsLabelAfter.clear();<br>
>>>>>> -  RegClobberInsn.clear();<br>
>>>>>> +  UserVariables.clear();<br>
>>>>>> +  DbgValues.clear();<br>
>>>>>>    ConcreteScopes.clear();<br>
>>>>>>    DeleteContainerSeconds(AbstractScopes);<br>
>>>>>>    AbstractScopesList.clear();<br>
>>>>>><br>
>>>>>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h<br>
>>>>>> URL:<br>
>>>>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=128327&r1=128326&r2=128327&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=128327&r1=128326&r2=128327&view=diff</a><br>

>>>>>><br>
>>>>>> ==============================================================================<br>
>>>>>> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)<br>
>>>>>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Fri Mar 25 21:19:36<br>
>>>>>> 2011<br>
>>>>>> @@ -218,19 +218,16 @@<br>
>>>>>>    /// instruction.<br>
>>>>>>    DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn;<br>
>>>>>><br>
>>>>>> -  /// insnNeedsLabel - Collection of instructions that need a label<br>
>>>>>> to mark<br>
>>>>>> -  /// a debuggging information entity.<br>
>>>>>> -  SmallPtrSet<const MachineInstr *, 8> InsnNeedsLabel;<br>
>>>>>> -<br>
>>>>>> -  /// InsnsNeedsLabelAfter - Collection of instructions that need a<br>
>>>>>> label after<br>
>>>>>> -  /// the instruction because they end a scope of clobber a register.<br>
>>>>>> -  SmallPtrSet<const MachineInstr *, 8> InsnsNeedsLabelAfter;<br>
>>>>>> -<br>
>>>>>> -  /// RegClobberInsn - For each DBG_VALUE instruction referring to a<br>
>>>>>> register<br>
>>>>>> -  /// that is clobbered before the variable gets a new DBG_VALUE, map<br>
>>>>>> the<br>
>>>>>> -  /// instruction that clobbered the register. This instruction will<br>
>>>>>> also be in<br>
>>>>>> -  /// InsnsNeedsLabelAfter.<br>
>>>>>> -  DenseMap<const MachineInstr *, const MachineInstr *><br>
>>>>>> RegClobberInsn;<br>
>>>>>> +  /// UserVariables - Every user variable mentioned by a DBG_VALUE<br>
>>>>>> instruction<br>
>>>>>> +  /// in order of appearance.<br>
>>>>>> +  SmallVector<const MDNode*, 8> UserVariables;<br>
>>>>>> +<br>
>>>>>> +  /// DbgValues - For each user variable, keep a list of DBG_VALUE<br>
>>>>>> +  /// instructions in order. The list can also contain normal<br>
>>>>>> instructions that<br>
>>>>>> +  /// clobber the previous DBG_VALUE.<br>
>>>>>> +  typedef DenseMap<const MDNode*, SmallVector<const MachineInstr*, 4><br>
>>>>>> ><br>
>>>>>> +    DbgValueHistoryMap;<br>
>>>>>> +  DbgValueHistoryMap DbgValues;<br>
>>>>>><br>
>>>>>>    SmallVector<const MCSymbol *, 8> DebugRangeSymbols;<br>
>>>>>><br>
>>>>>> @@ -570,6 +567,23 @@<br>
>>>>>>    /// side table maintained by MMI.<br>
>>>>>>    void collectVariableInfoFromMMITable(const MachineFunction * MF,<br>
>>>>>>                                         SmallPtrSet<const MDNode *,<br>
>>>>>> 16> &P);<br>
>>>>>> +<br>
>>>>>> +  /// requestLabelBeforeInsn - Ensure that a label will be emitted<br>
>>>>>> before MI.<br>
>>>>>> +  void requestLabelBeforeInsn(const MachineInstr *MI) {<br>
>>>>>> +    LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol*)0));<br>
>>>>>> +  }<br>
>>>>>> +<br>
>>>>>> +  /// getLabelBeforeInsn - Return Label preceding the instruction.<br>
>>>>>> +  const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);<br>
>>>>>> +<br>
>>>>>> +  /// requestLabelAfterInsn - Ensure that a label will be emitted<br>
>>>>>> after MI.<br>
>>>>>> +  void requestLabelAfterInsn(const MachineInstr *MI) {<br>
>>>>>> +    LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol*)0));<br>
>>>>>> +  }<br>
>>>>>> +<br>
>>>>>> +  /// getLabelAfterInsn - Return Label immediately following the<br>
>>>>>> instruction.<br>
>>>>>> +  const MCSymbol *getLabelAfterInsn(const MachineInstr *MI);<br>
>>>>>> +<br>
>>>>>>  public:<br>
>>>>>><br>
>>>>>> //===--------------------------------------------------------------------===//<br>
>>>>>>    // Main entry points.<br>
>>>>>> @@ -593,12 +607,6 @@<br>
>>>>>>    ///<br>
>>>>>>    void endFunction(const MachineFunction *MF);<br>
>>>>>><br>
>>>>>> -  /// getLabelBeforeInsn - Return Label preceding the instruction.<br>
>>>>>> -  const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);<br>
>>>>>> -<br>
>>>>>> -  /// getLabelAfterInsn - Return Label immediately following the<br>
>>>>>> instruction.<br>
>>>>>> -  const MCSymbol *getLabelAfterInsn(const MachineInstr *MI);<br>
<div class="im">>>>>>> -<br>
>>>>>>    /// beginInstruction - Process beginning of an instruction.<br>
</div>>>>>>>    void beginInstruction(const MachineInstr *MI);<br>
>>>>>><br>
>>>>>><br>
>>>>>> Modified: llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll<br>
>>>>>> URL:<br>
>>>>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll?rev=128327&r1=128326&r2=128327&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll?rev=128327&r1=128326&r2=128327&view=diff</a><br>

>>>>>><br>
>>>>>> ==============================================================================<br>
>>>>>> --- llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll (original)<br>
>>>>>> +++ llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll Fri Mar 25<br>
>>>>>> 21:19:36 2011<br>
>>>>>> @@ -4,7 +4,7 @@<br>
>>>>>><br>
>>>>>>  ;CHECK: Ldebug_loc0:<br>
>>>>>>  ;CHECK-NEXT:   .quad   Lfunc_begin0<br>
>>>>>> -;CHECK-NEXT:   .quad   Lfunc_end0<br>
>>>>>> +;CHECK-NEXT:   .quad   L<br>
>>>>>>  ;CHECK-NEXT:   .short  1                       ## Loc expr size<br>
>>>>>>  ;CHECK-NEXT:   .byte   85                      ## DW_OP_reg5<br>
>>>>>>  ;CHECK-NEXT:   .quad   0<br>
>>>>>><br>
>>>>>><br>
>>>>>> _______________________________________________<br>
>>>>>> llvm-commits mailing list<br>
>>>>>> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
>>>>>> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
>>>>><br>
>>>>><br>
>>>><br>
>>><br>
>><br>
><br>
><br>
<span class=""><font color="#888888">><br>
> --<br>
> Alexey Samsonov, MSK<br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div>
</div></div>