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 OS.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(10, 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(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(String)->data();
71}
72
73extern "C" uint32_t LLVMRemarkStringGetLen(LLVMRemarkStringRef String) {
74  return unwrap(String)->size();
75}
76
77extern "C" LLVMRemarkStringRef
78LLVMRemarkDebugLocGetSourceFilePath(LLVMRemarkDebugLocRef DL) {
79  return wrap(&unwrap(DL)->SourceFilePath);
80}
81
82extern "C" uint32_t LLVMRemarkDebugLocGetSourceLine(LLVMRemarkDebugLocRef DL) {
83  return unwrap(DL)->SourceLine;
84}
85
86extern "C" uint32_t
87LLVMRemarkDebugLocGetSourceColumn(LLVMRemarkDebugLocRef DL) {
88  return unwrap(DL)->SourceColumn;
89}
90
91extern "C" LLVMRemarkStringRef LLVMRemarkArgGetKey(LLVMRemarkArgRef Arg) {
92  return wrap(&unwrap(Arg)->Key);
93}
94
95extern "C" LLVMRemarkStringRef LLVMRemarkArgGetValue(LLVMRemarkArgRef Arg) {
96  return wrap(&unwrap(Arg)->Val);
97}
98
99extern "C" LLVMRemarkDebugLocRef
100LLVMRemarkArgGetDebugLoc(LLVMRemarkArgRef Arg) {
101  if (const std::optional<RemarkLocation> &Loc = unwrap(Arg)->Loc)
102    return wrap(&*Loc);
103  return nullptr;
104}
105
106extern "C" void LLVMRemarkEntryDispose(LLVMRemarkEntryRef Remark) {
107  delete unwrap(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(Remark)->RemarkType);
113}
114
115extern "C" LLVMRemarkStringRef
116LLVMRemarkEntryGetPassName(LLVMRemarkEntryRef Remark) {
117  return wrap(&unwrap(Remark)->PassName);
118}
119
120extern "C" LLVMRemarkStringRef
121LLVMRemarkEntryGetRemarkName(LLVMRemarkEntryRef Remark) {
122  return wrap(&unwrap(Remark)->RemarkName);
123}
124
125extern "C" LLVMRemarkStringRef
126LLVMRemarkEntryGetFunctionName(LLVMRemarkEntryRef Remark) {
127  return wrap(&unwrap(Remark)->FunctionName);
128}
129
130extern "C" LLVMRemarkDebugLocRef
131LLVMRemarkEntryGetDebugLoc(LLVMRemarkEntryRef Remark) {
132  if (const std::optional<RemarkLocation> &Loc = unwrap(Remark)->Loc)
133    return wrap(&*Loc);
134  return nullptr;
135}
136
137extern "C" uint64_t LLVMRemarkEntryGetHotness(LLVMRemarkEntryRef Remark) {
138  if (const std::optional<uint64_t> &Hotness = unwrap(Remark)->Hotness)
139    return *Hotness;
140  return 0;
141}
142
143extern "C" uint32_t LLVMRemarkEntryGetNumArgs(LLVMRemarkEntryRef Remark) {
144  return unwrap(Remark)->Args.size();
145}
146
147extern "C" LLVMRemarkArgRef
148LLVMRemarkEntryGetFirstArg(LLVMRemarkEntryRef Remark) {
149  ArrayRef<Argument> Args = unwrap(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(It);
165  if (Next == unwrap(Remark)->Args.end())
166    return nullptr;
167
168  return reinterpret_cast<LLVMRemarkArgRef>(const_cast<Argument *>(Next));
169}
170