llvm.org GIT mirror llvm / c86178e
Add llvm.codeview.annotation to implement MSVC __annotation Summary: This intrinsic represents a label with a list of associated metadata strings. It is modelled as reading and writing inaccessible memory so that it won't be removed as dead code. I think the intention is that the annotation strings should appear at most once in the debug info, so I marked it noduplicate. We are allowed to inline code with annotations as long as we strip the annotation, but that can be done later. Reviewers: majnemer Subscribers: eraman, llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D36904 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312569 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 3 years ago
18 changed file(s) with 226 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
1362513625 optimizations that want to look for these annotations. These have no
1362613626 other defined use; they are ignored by code generation and optimization.
1362713627
13628 '``llvm.codeview.annotation``' Intrinsic
13629 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13630
13631 Syntax:
13632 """""""
13633
13634 This annotation emits a label at its program point and an associated
13635 ``S_ANNOTATION`` codeview record with some additional string metadata. This is
13636 used to implement MSVC's ``__annotation`` intrinsic. It is marked
13637 ``noduplicate``, so calls to this intrinsic prevent inlining and should be
13638 considered expensive.
13639
13640 ::
13641
13642 declare void @llvm.codeview.annotation(metadata)
13643
13644 Arguments:
13645 """"""""""
13646
13647 The argument should be an MDTuple containing any number of MDStrings.
13648
1362813649 '``llvm.trap``' Intrinsic
1362913650 ^^^^^^^^^^^^^^^^^^^^^^^^^
1363013651
636636 /// locations needed for debug and exception handling tables. These nodes
637637 /// take a chain as input and return a chain.
638638 EH_LABEL,
639
640 /// ANNOTATION_LABEL - Represents a mid basic block label used by
641 /// annotations. This should remain within the basic block and be ordered
642 /// with respect to other call instructions, but loads and stores may float
643 /// past it.
644 ANNOTATION_LABEL,
639645
640646 /// CATCHPAD - Represents a catchpad instruction.
641647 CATCHPAD,
313313 /// Map of invoke call site index values to associated begin EH_LABEL.
314314 DenseMap CallSiteMap;
315315
316 /// CodeView label annotations.
317 std::vector> CodeViewAnnotations;
318
316319 bool CallsEHReturn = false;
317320 bool CallsUnwindInit = false;
318321 bool HasEHFunclets = false;
831834 return CallSiteMap.count(BeginLabel);
832835 }
833836
837 /// Record annotations associated with a particular label.
838 void addCodeViewAnnotation(MCSymbol *Label, MDNode *MD) {
839 CodeViewAnnotations.push_back({Label, MD});
840 }
841
842 ArrayRef> getCodeViewAnnotations() const {
843 return CodeViewAnnotations;
844 }
845
834846 /// Return a reference to the C++ typeinfo for the current function.
835847 const std::vector &getTypeInfos() const {
836848 return TypeInfos;
634634 SDValue getRegister(unsigned Reg, EVT VT);
635635 SDValue getRegisterMask(const uint32_t *RegMask);
636636 SDValue getEHLabel(const SDLoc &dl, SDValue Root, MCSymbol *Label);
637 SDValue getLabelNode(unsigned Opcode, const SDLoc &dl, SDValue Root,
638 MCSymbol *Label);
637639 SDValue getBlockAddress(const BlockAddress *BA, EVT VT,
638640 int64_t Offset = 0, bool isTarget = false,
639641 unsigned char TargetFlags = 0);
18471847 }
18481848 };
18491849
1850 class EHLabelSDNode : public SDNode {
1850 class LabelSDNode : public SDNode {
18511851 friend class SelectionDAG;
18521852
18531853 MCSymbol *Label;
18541854
1855 EHLabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L)
1855 LabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L)
18561856 : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {}
18571857
18581858 public:
18591859 MCSymbol *getLabel() const { return Label; }
18601860
18611861 static bool classof(const SDNode *N) {
1862 return N->getOpcode() == ISD::EH_LABEL;
1862 return N->getOpcode() == ISD::EH_LABEL ||
1863 N->getOpcode() == ISD::ANNOTATION_LABEL;
18631864 }
18641865 };
18651866
941941 uint32_t RecordOffset;
942942 };
943943
944 // S_ANNOTATION
945
944946 using CVSymbol = CVRecord;
945947 using CVSymbolArray = VarStreamArray;
946948
639639 [LLVMMatchType<0>, llvm_ptr_ty,
640640 llvm_ptr_ty, llvm_i32_ty],
641641 [], "llvm.annotation">;
642
643 // Annotates the current program point with metadata strings which are emitted
644 // as CodeView debug info records. This is expensive, as it disables inlining
645 // and is modelled as having side effects.
646 def int_codeview_annotation : Intrinsic<[], [llvm_metadata_ty],
647 [IntrInaccessibleMemOnly, IntrNoDuplicate],
648 "llvm.codeview.annotation">;
642649
643650 //===------------------------ Trampoline Intrinsics -----------------------===//
644651 //
839839 let hasCtrlDep = 1;
840840 let isNotDuplicable = 1;
841841 }
842 def ANNOTATION_LABEL : Instruction {
843 let OutOperandList = (outs);
844 let InOperandList = (ins i32imm:$id);
845 let AsmString = "";
846 let hasCtrlDep = 1;
847 let isNotDuplicable = 1;
848 }
842849 def KILL : Instruction {
843850 let OutOperandList = (outs);
844851 let InOperandList = (ins variable_ops);
3131 HANDLE_TARGET_OPCODE(CFI_INSTRUCTION)
3232 HANDLE_TARGET_OPCODE(EH_LABEL)
3333 HANDLE_TARGET_OPCODE(GC_LABEL)
34 HANDLE_TARGET_OPCODE(ANNOTATION_LABEL)
3435
3536 /// KILL - This instruction is a noop that is used only to adjust the
3637 /// liveness of registers. This can be useful when dealing with
859859 emitInlinedCallSite(FI, InlinedAt, I->second);
860860 }
861861
862 for (auto Annot : FI.Annotations) {
863 MCSymbol *Label = Annot.first;
864 MDTuple *Strs = cast(Annot.second);
865 MCSymbol *AnnotBegin = MMI->getContext().createTempSymbol(),
866 *AnnotEnd = MMI->getContext().createTempSymbol();
867 OS.AddComment("Record length");
868 OS.emitAbsoluteSymbolDiff(AnnotEnd, AnnotBegin, 2);
869 OS.EmitLabel(AnnotBegin);
870 OS.AddComment("Record kind: S_ANNOTATION");
871 OS.EmitIntValue(SymbolKind::S_ANNOTATION, 2);
872 OS.EmitCOFFSecRel32(Label, /*Offset=*/0);
873 // FIXME: Make sure we don't overflow the max record size.
874 OS.EmitCOFFSectionIndex(Label);
875 OS.EmitIntValue(Strs->getNumOperands(), 2);
876 for (Metadata *MD : Strs->operands()) {
877 // MDStrings are null terminated, so we can do EmitBytes and get the
878 // nice .asciz directive.
879 StringRef Str = cast(MD)->getString();
880 assert(Str.data()[Str.size()] == '\0' && "non-nullterminated MDString");
881 OS.EmitBytes(StringRef(Str.data(), Str.size() + 1));
882 }
883 OS.EmitLabel(AnnotEnd);
884 }
885
862886 if (SP != nullptr)
863887 emitDebugInfoForUDTs(LocalUDTs);
864888
21942218 return;
21952219 }
21962220
2221 CurFn->Annotations = MF->getCodeViewAnnotations();
2222
21972223 CurFn->End = Asm->getFunctionEnd();
21982224
21992225 CurFn = nullptr;
118118
119119 SmallVector Locals;
120120
121 std::vector> Annotations;
122
121123 const MCSymbol *Begin = nullptr;
122124 const MCSymbol *End = nullptr;
123125 unsigned FuncId = 0;
165165 InstructionRecycler.clear(Allocator);
166166 OperandRecycler.clear(Allocator);
167167 BasicBlockRecycler.clear(Allocator);
168 CodeViewAnnotations.clear();
168169 VariableDbgInfos.clear();
169170 if (RegInfo) {
170171 RegInfo->~MachineRegisterInfo();
934934 EmitCopyFromReg(Node, 0, IsClone, IsCloned, SrcReg, VRBaseMap);
935935 break;
936936 }
937 case ISD::EH_LABEL: {
938 MCSymbol *S = cast(Node)->getLabel();
937 case ISD::EH_LABEL:
938 case ISD::ANNOTATION_LABEL: {
939 unsigned Opc = (Node->getOpcode() == ISD::EH_LABEL)
940 ? TargetOpcode::EH_LABEL
941 : TargetOpcode::ANNOTATION_LABEL;
942 MCSymbol *S = cast(Node)->getLabel();
939943 BuildMI(*MBB, InsertPos, Node->getDebugLoc(),
940 TII->get(TargetOpcode::EH_LABEL)).addSym(S);
944 TII->get(Opc)).addSym(S);
941945 break;
942946 }
943947
16791679
16801680 SDValue SelectionDAG::getEHLabel(const SDLoc &dl, SDValue Root,
16811681 MCSymbol *Label) {
1682 return getLabelNode(ISD::EH_LABEL, dl, Root, Label);
1683 }
1684
1685 SDValue SelectionDAG::getLabelNode(unsigned Opcode, const SDLoc &dl,
1686 SDValue Root, MCSymbol *Label) {
16821687 FoldingSetNodeID ID;
16831688 SDValue Ops[] = { Root };
1684 AddNodeIDNode(ID, ISD::EH_LABEL, getVTList(MVT::Other), Ops);
1689 AddNodeIDNode(ID, Opcode, getVTList(MVT::Other), Ops);
16851690 ID.AddPointer(Label);
16861691 void *IP = nullptr;
16871692 if (SDNode *E = FindNodeOrInsertPos(ID, IP))
16881693 return SDValue(E, 0);
16891694
1690 auto *N = newSDNode<EHLabelSDNode>(dl.getIROrder(), dl.getDebugLoc(), Label);
1695 auto *N = newSDNode<LabelSDNode>(dl.getIROrder(), dl.getDebugLoc(), Label);
16911696 createOperands(N, Ops);
16921697
16931698 CSEMap.InsertNode(N, IP);
56495649 case Intrinsic::var_annotation:
56505650 // Discard annotate attributes and assumptions
56515651 return nullptr;
5652
5653 case Intrinsic::codeview_annotation: {
5654 // Emit a label associated with this metadata.
5655 MachineFunction &MF = DAG.getMachineFunction();
5656 MCSymbol *Label =
5657 MF.getMMI().getContext().createTempSymbol("annotation", true);
5658 Metadata *MD = cast(I.getArgOperand(0))->getMetadata();
5659 MF.addCodeViewAnnotation(Label, cast(MD));
5660 Res = DAG.getLabelNode(ISD::ANNOTATION_LABEL, sdl, getRoot(), Label);
5661 DAG.setRoot(Res);
5662 return nullptr;
5663 }
56525664
56535665 case Intrinsic::init_trampoline: {
56545666 const Function *F = cast(I.getArgOperand(1)->stripPointerCasts());
29102910 case ISD::CopyFromReg:
29112911 case ISD::CopyToReg:
29122912 case ISD::EH_LABEL:
2913 case ISD::ANNOTATION_LABEL:
29132914 case ISD::LIFETIME_START:
29142915 case ISD::LIFETIME_END:
29152916 NodeToMatch->setNodeId(-1); // Mark selected.
0 ; RUN: llc < %s | FileCheck %s
1 ; FIXME: fastisel screws up the order here.
2 ; RUNX: llc -O0 < %s | FileCheck %s
3
4 ; Source to regenerate:
5 ; $ clang --target=x86_64-windows-msvc -S annotation.c -g -gcodeview -o t.ll \
6 ; -emit-llvm -O1 -Xclang -disable-llvm-passes -fms-extensions
7 ; void g(void);
8 ; void f(void) {
9 ; g();
10 ; __annotation(L"a1", L"a2");
11 ; g();
12 ; }
13
14 ; ModuleID = 'annotation.c'
15 source_filename = "annotation.c"
16 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
17 target triple = "x86_64-pc-windows-msvc19.0.24215"
18
19 ; Function Attrs: nounwind uwtable
20 define void @f() #0 !dbg !8 {
21 entry:
22 call void @g(), !dbg !11
23 call void @llvm.codeview.annotation(metadata !12), !dbg !13
24 call void @g(), !dbg !14
25 ret void, !dbg !15
26 }
27
28 ; CHECK-LABEL: f: # @f
29 ; CHECK: callq g
30 ; CHECK: .Lannotation0:
31 ; CHECK: callq g
32 ; CHECK: retq
33
34 ; CHECK-LABEL: .short 4423 # Record kind: S_GPROC32_ID
35 ; CHECK: .short 4121 # Record kind: S_ANNOTATION
36 ; CHECK-NEXT: .secrel32 .Lannotation0
37 ; CHECK-NEXT: .secidx .Lannotation0
38 ; CHECK-NEXT: .short 2
39 ; CHECK-NEXT: .asciz "a1"
40 ; CHECK-NEXT: .asciz "a2"
41
42 ; CHECK-LABEL: .short 4431 # Record kind: S_PROC_ID_END
43
44 declare void @g() #1
45
46 ; Function Attrs: nounwind
47 declare void @llvm.codeview.annotation(metadata) #2
48
49 attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
50 attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
51 attributes #2 = { nounwind }
52
53 !llvm.dbg.cu = !{!0}
54 !llvm.module.flags = !{!3, !4, !5, !6}
55 !llvm.ident = !{!7}
56
57 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
58 !1 = !DIFile(filename: "annotation.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "51164221112d8a5baa55a995027e4ba5")
59 !2 = !{}
60 !3 = !{i32 2, !"CodeView", i32 1}
61 !4 = !{i32 2, !"Debug Info Version", i32 3}
62 !5 = !{i32 1, !"wchar_size", i32 2}
63 !6 = !{i32 7, !"PIC Level", i32 2}
64 !7 = !{!"clang version 6.0.0 "}
65 !8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
66 !9 = !DISubroutineType(types: !10)
67 !10 = !{null}
68 !11 = !DILocation(line: 3, column: 3, scope: !8)
69 !12 = !{!"a1", !"a2"}
70 !13 = !DILocation(line: 4, column: 3, scope: !8)
71 !14 = !DILocation(line: 5, column: 3, scope: !8)
72 !15 = !DILocation(line: 6, column: 1, scope: !8)
0 ; Inlining should not clone label annotations.
1 ; Currently we block all duplication for simplicity.
2
3 ; RUN: opt < %s -S -inline | FileCheck %s
4
5 @the_global = global i32 0
6
7 declare void @llvm.codeview.annotation(metadata)
8
9 define void @inlinee() {
10 entry:
11 store i32 42, i32* @the_global
12 call void @llvm.codeview.annotation(metadata !0)
13 ret void
14 }
15
16 define void @caller() {
17 entry:
18 call void @inlinee()
19 ret void
20 }
21
22 !0 = !{!"annotation"}
23
24 ; CHECK-LABEL: define void @inlinee()
25 ; CHECK: store i32 42, i32* @the_global
26 ; CHECK: call void @llvm.codeview.annotation(metadata !0)
27 ; CHECK: ret void
28
29 ; CHECK-LABEL: define void @caller()
30 ; MSVC can inline this. If we ever do, check for the store but make sure
31 ; there is no annotation.
32 ; CHECK: call void @inlinee()
33 ; CHECK-NOT: call void @llvm.codeview.annotation
34 ; CHECK: ret void