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