Summary:
When we're building with XRay instrumentation, we use a trick that
preserves references from the function to a function sled index. This
index table lives in a separate section, and without this trick the
linker is free to garbage-collect this section and all the segments it
refers to. Until we're able to tell the linkers to preserve these
sections, we use this reference trick to keep around both the index and
the entries in the instrumentation map.
Before this change we emitted both a synthetic reference to the label in
the instrumentation map, and to the entry in the function map index.
This change removes the first synthetic reference and only emits one
synthetic reference to the index -- the index entry has the references
to the labels in the instrumentation map, so the linker will still
preserve those if the function itself is preserved.
This reduces the amount of synthetic references we emit from 16 bytes to
just 8 bytes in x86_64, and similarly to other platforms.
Reviewers: dblaikie
Subscribers: javed.absar, kpw, pelikan, llvm-commits
Differential Revision: https://reviews.llvm.org/D34340
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305880
91177308-0d34-0410-b5e6-
96231b3b80d8
}
// Before we switch over, we force a reference to a label inside the
- // xray_instr_map and xray_fn_idx sections. Since this function is always
- // called just before the function's end, we assume that this is happening
- // after the last return instruction. We also use the synthetic label in the
- // xray_inster_map as a delimeter for the range of sleds for this function in
- // the index.
+ // xray_fn_idx sections. This makes sure that the xray_fn_idx section is kept
+ // live by the linker if the function is not garbage-collected. Since this
+ // function is always called just before the function's end, we assume that
+ // this is happening after the last return instruction.
auto WordSizeBytes = MAI->getCodePointerSize();
- MCSymbol *SledsStart = OutContext.createTempSymbol("xray_synthetic_", true);
MCSymbol *IdxRef = OutContext.createTempSymbol("xray_fn_idx_synth_", true);
OutStreamer->EmitCodeAlignment(16);
- OutStreamer->EmitSymbolValue(SledsStart, WordSizeBytes, false);
OutStreamer->EmitSymbolValue(IdxRef, WordSizeBytes, false);
// Now we switch to the instrumentation map section. Because this is done
// per-function, we are able to create an index entry that will represent the
// range of sleds associated with a function.
+ MCSymbol *SledsStart = OutContext.createTempSymbol("xray_sleds_start", true);
OutStreamer->SwitchSection(InstMap);
OutStreamer->EmitLabel(SledsStart);
for (const auto &Sled : Sleds)
Sled.emit(WordSizeBytes, OutStreamer.get(), CurrentFnSym);
- MCSymbol *SledsEnd = OutContext.createTempSymbol("xray_synthetic_end", true);
+ MCSymbol *SledsEnd = OutContext.createTempSymbol("xray_sleds_end", true);
OutStreamer->EmitLabel(SledsEnd);
// We then emit a single entry in the index per function. We use the symbols
; CHECK-NEXT: ret
}
; CHECK: .p2align 4
-; CHECK-NEXT: .xword .Lxray_synthetic_0
; CHECK-NEXT: .xword .Lxray_fn_idx_synth_0
; CHECK-NEXT: .section xray_instr_map,{{.*}}
-; CHECK-LABEL: Lxray_synthetic_0:
+; CHECK-LABEL: Lxray_sleds_start0
; CHECK: .xword .Lxray_sled_0
; CHECK: .xword .Lxray_sled_1
+; CHECK-LABEL: Lxray_sleds_end0
; CHECK-NEXT: ret\r
}\r
; CHECK: .p2align 4\r
-; CHECK-NEXT: .xword .Lxray_synthetic_0\r
; CHECK-NEXT: .xword .Lxray_fn_idx_synth_0\r
; CHECK-NEXT: .section xray_instr_map,{{.*}}\r
-; CHECK-LABEL: Lxray_synthetic_0:\r
+; CHECK-LABEL: Lxray_sleds_start0:\r
; CHECK: .xword .Lxray_sled_0\r
; CHECK: .xword .Lxray_sled_1\r
-; CHECK-LABEL: Lxray_synthetic_end0:\r
+; CHECK-LABEL: Lxray_sleds_end0:\r
; CHECK: .section xray_fn_idx,{{.*}}\r
; CHECK-LABEL: Lxray_fn_idx_synth_0:\r
-; CHECK: .xword .Lxray_synthetic_0\r
-; CHECK-NEXT: .xword .Lxray_synthetic_end0\r
+; CHECK: .xword .Lxray_sleds_start0\r
+; CHECK-NEXT: .xword .Lxray_sleds_end0\r
\r
define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-always" {\r
; CHECK: .p2align 2\r
-; CHECK-LABEL: .Lxray_sled_2:\r
+; CHECK-LABEL: Lxray_sled_2:\r
; CHECK-NEXT: b #32\r
; CHECK-NEXT: nop\r
; CHECK-NEXT: nop\r
; CHECK-NEXT: nop\r
; CHECK-LABEL: .Ltmp2:\r
; CHECK: .p2align 2\r
-; CHECK-LABEL: .Lxray_sled_3:\r
+; CHECK-LABEL: Lxray_sled_3:\r
; CHECK-NEXT: b #32\r
; CHECK-NEXT: nop\r
; CHECK-NEXT: nop\r
ret i32 %retval\r
}\r
; CHECK: .p2align 4\r
-; CHECK-NEXT: .xword .Lxray_synthetic_1\r
; CHECK-NEXT: .xword .Lxray_fn_idx_synth_1\r
; CHECK-NEXT: .section xray_instr_map,{{.*}}\r
-; CHECK-LABEL: Lxray_synthetic_1:\r
+; CHECK-LABEL: Lxray_sleds_start1:\r
; CHECK: .xword .Lxray_sled_2\r
; CHECK: .xword .Lxray_sled_3\r
-; CHECK-LABEL: Lxray_synthetic_end1:\r
+; CHECK-LABEL: Lxray_sleds_end1:\r
; CHECK: .section xray_fn_idx,{{.*}}\r
; CHECK-LABEL: Lxray_fn_idx_synth_1:\r
-; CHECK: .xword .Lxray_synthetic_1\r
-; CHECK-NEXT: .xword .Lxray_synthetic_end1\r
+; CHECK: .xword .Lxray_sleds_start1\r
+; CHECK-NEXT: .xword .Lxray_sleds_end1\r
; CHECK-NEXT: bx lr
}
; CHECK: .p2align 4
-; CHECK-NEXT: .long {{.*}}Lxray_synthetic_0
; CHECK-NEXT: .long {{.*}}Lxray_fn_idx_synth_0
; CHECK-NEXT: .section {{.*}}xray_instr_map{{.*}}
-; CHECK-LABEL: Lxray_synthetic_0:
+; CHECK-LABEL: Lxray_sleds_start0:
; CHECK: .long {{.*}}Lxray_sled_0
; CHECK: .long {{.*}}Lxray_sled_1
-; CHECK-LABEL: Lxray_synthetic_end0:
+; CHECK-LABEL: Lxray_sleds_end0:
; CHECK: .section {{.*}}xray_fn_idx{{.*}}
; CHECK-LABEL: Lxray_fn_idx_synth_0:
-; CHECK: .long {{.*}}Lxray_synthetic_0
-; CHECK-NEXT: .long {{.*}}Lxray_synthetic_end0
+; CHECK: .long {{.*}}Lxray_sleds_start0
+; CHECK-NEXT: .long {{.*}}Lxray_sleds_end0
; CHECK-NEXT: bx lr
}
; CHECK: .p2align 4
-; CHECK-NEXT: .long {{.*}}Lxray_synthetic_0
; CHECK-NEXT: .long {{.*}}Lxray_fn_idx_synth_0
; CHECK-NEXT: .section {{.*}}xray_instr_map{{.*}}
-; CHECK-LABEL: Lxray_synthetic_0:
+; CHECK-LABEL: Lxray_sleds_start0:
; CHECK: .long {{.*}}Lxray_sled_0
; CHECK: .long {{.*}}Lxray_sled_1
-; CHECK-LABEL: Lxray_synthetic_end0:
+; CHECK-LABEL: Lxray_sleds_end0:
; CHECK: .section {{.*}}xray_fn_idx{{.*}}
; CHECK-LABEL: Lxray_fn_idx_synth_0:
-; CHECK: .long {{.*}}xray_synthetic_0
-; CHECK-NEXT: .long {{.*}}xray_synthetic_end0
+; CHECK: .long {{.*}}xray_sleds_start0
+; CHECK-NEXT: .long {{.*}}xray_sleds_end0
; CHECK-NEXT: nopw %cs:512(%rax,%rax)
}
; CHECK: .p2align 4, 0x90
-; CHECK-NEXT: .quad {{.*}}xray_synthetic_0
; CHECK-NEXT: .quad {{.*}}xray_fn_idx_synth_0
; CHECK-NEXT: .section {{.*}}xray_instr_map
-; CHECK-LABEL: Lxray_synthetic_0:
+; CHECK-LABEL: Lxray_sleds_start0:
; CHECK: .quad {{.*}}xray_sled_0
; CHECK: .quad {{.*}}xray_sled_1
-; CHECK-LABEL: Lxray_synthetic_end0:
+; CHECK-LABEL: Lxray_sleds_end0:
; CHECK: .section {{.*}}xray_fn_idx
; CHECK-LABEL: Lxray_fn_idx_synth_0:
-; CHECK: .quad {{.*}}xray_synthetic_0
-; CHECK-NEXT: .quad {{.*}}xray_synthetic_end0
+; CHECK: .quad {{.*}}xray_sleds_start0
+; CHECK-NEXT: .quad {{.*}}xray_sleds_end0
; We test multiple returns in a single function to make sure we're getting all
; CHECK-NEXT: nopw %cs:512(%rax,%rax)
}
; CHECK: .p2align 4, 0x90
-; CHECK-NEXT: .quad {{.*}}xray_synthetic_1
; CHECK-NEXT: .quad {{.*}}xray_fn_idx_synth_1
; CHECK-NEXT: .section {{.*}}xray_instr_map
-; CHECK-LABEL: Lxray_synthetic_1:
+; CHECK-LABEL: Lxray_sleds_start1:
; CHECK: .quad {{.*}}xray_sled_2
; CHECK: .quad {{.*}}xray_sled_3
; CHECK: .quad {{.*}}xray_sled_4
-; CHECK-LABEL: Lxray_synthetic_end1:
+; CHECK-LABEL: Lxray_sleds_end1:
; CHECK: .section {{.*}}xray_fn_idx
; CHECK-LABEL: Lxray_fn_idx_synth_1:
-; CHECK: .quad {{.*}}xray_synthetic_1
-; CHECK-NEXT: .quad {{.*}}xray_synthetic_end1
+; CHECK: .quad {{.*}}xray_sleds_start1
+; CHECK-NEXT: .quad {{.*}}xray_sleds_end1
ret i32 0
}
; CHECK: .section {{.*}}xray_instr_map
-; CHECK-LABEL: Lxray_synthetic_0:
+; CHECK-LABEL: Lxray_sleds_start0:
; CHECK: .quad {{.*}}xray_event_sled_0
declare void @llvm.xray.customevent(i8*, i32)
define i32 @callee(i32 %arg) nounwind noinline uwtable "function-instrument"="xray-always" "xray-log-args"="1" {
ret i32 %arg
}
-; CHECK-LABEL: Lxray_synthetic_0:
+; CHECK-LABEL: Lxray_sleds_start0:
; CHECK: .quad {{\.?}}Lxray_sled_0
; CHECK: .quad {{_?}}callee
; CHECK: .byte 3
%retval = tail call i32 @callee(i32 %arg)
ret i32 %retval
}
-; CHECK-LABEL: Lxray_synthetic_1:
+; CHECK-LABEL: Lxray_sleds_start1:
; CHECK: .quad {{\.?}}Lxray_sled_2
; CHECK: .quad {{_?}}caller
; CHECK: .byte 3
; CHECK-NEXT: nopw %cs:512(%rax,%rax)
}
; CHECK: .p2align 4, 0x90
-; CHECK-NEXT: .quad {{.*}}xray_synthetic_0{{.*}}
; CHECK-NEXT: .quad {{.*}}xray_fn_idx_synth_0{{.*}}
; CHECK-NEXT: .section {{.*}}xray_instr_map
-; CHECK-LABEL: Lxray_synthetic_0:
+; CHECK-LABEL: Lxray_sleds_start0:
; CHECK: .quad {{.*}}xray_sled_0
; CHECK: .quad {{.*}}xray_sled_1
-; CHECK-LABEL: Lxray_synthetic_end0:
+; CHECK-LABEL: Lxray_sleds_end0:
; CHECK-NEXT: .section {{.*}}xray_fn_idx
; CHECK-LABEL: Lxray_fn_idx_synth_0:
-; CHECK: .quad {{.*}}xray_synthetic_0
-; CHECK-NEXT: .quad {{.*}}xray_synthetic_end0
+; CHECK: .quad {{.*}}xray_sleds_start0
+; CHECK-NEXT: .quad {{.*}}xray_sleds_end0
define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-always" {
; CHECK: .p2align 1, 0x90
ret i32 %retval
}
; CHECK: .p2align 4, 0x90
-; CHECK-NEXT: .quad {{.*}}xray_synthetic_1{{.*}}
; CHECK-NEXT: .quad {{.*}}xray_fn_idx_synth_1{{.*}}
-; CHECK-LABEL: Lxray_synthetic_1:
+; CHECK-LABEL: Lxray_sleds_start1:
; CHECK: .quad {{.*}}xray_sled_2
; CHECK: .quad {{.*}}xray_sled_3
-; CHECK-LABEL: Lxray_synthetic_end1:
+; CHECK-LABEL: Lxray_sleds_end1:
; CHECK: .section {{.*}}xray_fn_idx
; CHECK-LABEL: Lxray_fn_idx_synth_1:
-; CHECK: .quad {{.*}}xray_synthetic_1
-; CHECK: .quad {{.*}}xray_synthetic_end1
+; CHECK: .quad {{.*}}xray_sleds_start1
+; CHECK: .quad {{.*}}xray_sleds_end1