1//===- Remark.cpp ---------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Implementation of the Remark type and the C API.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Remarks/Remark.h"
14#include "llvm/ADT/APInt.h"
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/STLExtras.h"
17#include <optional>
18
19using namespace llvm;
20using namespace llvm::remarks;
21
22std::string Remark::getArgsAsMsg() const {
23 std::string Str;
24 raw_string_ostream OS(Str);
25 for (const Argument &Arg : Args)
26 OS << Arg.Val;
27 return Str;
28}
29
30Argument *Remark::getArgByKey(StringRef Key) {
31 auto *It = find_if(Range&: Args, P: [&](auto &Arg) { return Arg.Key == Key; });
32 if (It == Args.end())
33 return nullptr;
34 return &*It;
35}
36
37void RemarkLocation::print(raw_ostream &OS) const {
38 OS << "{ "
39 << "File: " << SourceFilePath << ", Line: " << SourceLine
40 << " Column:" << SourceColumn << " }\n";
41}
42
43void Argument::print(raw_ostream &OS) const {
44 OS << Key << ": " << Val << "\n";
45}
46
47void Remark::print(raw_ostream &OS) const {
48 OS << "Name: ";
49 OS << RemarkName << "\n";
50 OS << "Type: " << typeToStr(Ty: RemarkType) << "\n";
51 OS << "FunctionName: " << FunctionName << "\n";
52 OS << "PassName: " << PassName << "\n";
53 if (Loc)
54 OS << "Loc: " << Loc.value();
55 if (Hotness)
56 OS << "Hotness: " << Hotness;
57 if (!Args.empty()) {
58 OS << "Args:\n";
59 for (auto Arg : Args)
60 OS << "\t" << Arg;
61 }
62}
63
64// Create wrappers for C Binding types (see CBindingWrapping.h).
65DEFINE_SIMPLE_CONVERSION_FUNCTIONS(StringRef, LLVMRemarkStringRef)
66
67extern "C" const char *LLVMRemarkStringGetData(LLVMRemarkStringRef String) {
68 return unwrap(P: String)->data();
69}
70
71extern "C" uint32_t LLVMRemarkStringGetLen(LLVMRemarkStringRef String) {
72 return unwrap(P: String)->size();
73}
74
75extern "C" LLVMRemarkStringRef
76LLVMRemarkDebugLocGetSourceFilePath(LLVMRemarkDebugLocRef DL) {
77 return wrap(P: &unwrap(P: DL)->SourceFilePath);
78}
79
80extern "C" uint32_t LLVMRemarkDebugLocGetSourceLine(LLVMRemarkDebugLocRef DL) {
81 return unwrap(P: DL)->SourceLine;
82}
83
84extern "C" uint32_t
85LLVMRemarkDebugLocGetSourceColumn(LLVMRemarkDebugLocRef DL) {
86 return unwrap(P: DL)->SourceColumn;
87}
88
89extern "C" LLVMRemarkStringRef LLVMRemarkArgGetKey(LLVMRemarkArgRef Arg) {
90 return wrap(P: &unwrap(P: Arg)->Key);
91}
92
93extern "C" LLVMRemarkStringRef LLVMRemarkArgGetValue(LLVMRemarkArgRef Arg) {
94 return wrap(P: &unwrap(P: Arg)->Val);
95}
96
97extern "C" LLVMRemarkDebugLocRef
98LLVMRemarkArgGetDebugLoc(LLVMRemarkArgRef Arg) {
99 if (const std::optional<RemarkLocation> &Loc = unwrap(P: Arg)->Loc)
100 return wrap(P: &*Loc);
101 return nullptr;
102}
103
104extern "C" void LLVMRemarkEntryDispose(LLVMRemarkEntryRef Remark) {
105 delete unwrap(P: Remark);
106}
107
108extern "C" LLVMRemarkType LLVMRemarkEntryGetType(LLVMRemarkEntryRef Remark) {
109 // Assume here that the enums can be converted both ways.
110 return static_cast<LLVMRemarkType>(unwrap(P: Remark)->RemarkType);
111}
112
113extern "C" LLVMRemarkStringRef
114LLVMRemarkEntryGetPassName(LLVMRemarkEntryRef Remark) {
115 return wrap(P: &unwrap(P: Remark)->PassName);
116}
117
118extern "C" LLVMRemarkStringRef
119LLVMRemarkEntryGetRemarkName(LLVMRemarkEntryRef Remark) {
120 return wrap(P: &unwrap(P: Remark)->RemarkName);
121}
122
123extern "C" LLVMRemarkStringRef
124LLVMRemarkEntryGetFunctionName(LLVMRemarkEntryRef Remark) {
125 return wrap(P: &unwrap(P: Remark)->FunctionName);
126}
127
128extern "C" LLVMRemarkDebugLocRef
129LLVMRemarkEntryGetDebugLoc(LLVMRemarkEntryRef Remark) {
130 if (const std::optional<RemarkLocation> &Loc = unwrap(P: Remark)->Loc)
131 return wrap(P: &*Loc);
132 return nullptr;
133}
134
135extern "C" uint64_t LLVMRemarkEntryGetHotness(LLVMRemarkEntryRef Remark) {
136 if (const std::optional<uint64_t> &Hotness = unwrap(P: Remark)->Hotness)
137 return *Hotness;
138 return 0;
139}
140
141extern "C" uint32_t LLVMRemarkEntryGetNumArgs(LLVMRemarkEntryRef Remark) {
142 return unwrap(P: Remark)->Args.size();
143}
144
145extern "C" LLVMRemarkArgRef
146LLVMRemarkEntryGetFirstArg(LLVMRemarkEntryRef Remark) {
147 ArrayRef<Argument> Args = unwrap(P: Remark)->Args;
148 // No arguments to iterate on.
149 if (Args.empty())
150 return nullptr;
151 return reinterpret_cast<LLVMRemarkArgRef>(
152 const_cast<Argument *>(Args.begin()));
153}
154
155extern "C" LLVMRemarkArgRef
156LLVMRemarkEntryGetNextArg(LLVMRemarkArgRef ArgIt, LLVMRemarkEntryRef Remark) {
157 // No more arguments to iterate on.
158 if (ArgIt == nullptr)
159 return nullptr;
160
161 auto It = (ArrayRef<Argument>::const_iterator)ArgIt;
162 auto Next = std::next(x: It);
163 if (Next == unwrap(P: Remark)->Args.end())
164 return nullptr;
165
166 return reinterpret_cast<LLVMRemarkArgRef>(const_cast<Argument *>(Next));
167}
168