1 //===- bolt/Utils/Utils.cpp - Common helper functions ---------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Common helper functions.
11 //===----------------------------------------------------------------------===//
13 #include "bolt/Utils/Utils.h"
14 #include "llvm/BinaryFormat/Dwarf.h"
15 #include "llvm/MC/MCDwarf.h"
16 #include "llvm/Support/LEB128.h"
17 #include "llvm/Support/raw_ostream.h"
22 void report_error(StringRef Message
, std::error_code EC
) {
24 errs() << "BOLT-ERROR: '" << Message
<< "': " << EC
.message() << ".\n";
28 void report_error(StringRef Message
, Error E
) {
30 errs() << "BOLT-ERROR: '" << Message
<< "': " << toString(std::move(E
))
35 void check_error(std::error_code EC
, StringRef Message
) {
38 report_error(Message
, EC
);
41 void check_error(Error E
, Twine Message
) {
44 handleAllErrors(std::move(E
), [&](const llvm::ErrorInfoBase
&EIB
) {
45 llvm::errs() << "BOLT-ERROR: '" << Message
<< "': " << EIB
.message()
51 std::string
getEscapedName(const StringRef
&Name
) {
52 std::string Output
= Name
.str();
53 for (size_t I
= 0; I
< Output
.size(); ++I
)
54 if (Output
[I
] == ' ' || Output
[I
] == '\\')
55 Output
.insert(I
++, 1, '\\');
60 std::string
getUnescapedName(const StringRef
&Name
) {
61 std::string Output
= Name
.str();
62 for (size_t I
= 0; I
< Output
.size(); ++I
)
63 if (Output
[I
] == '\\')
69 std::optional
<StringRef
> getCommonName(const StringRef Name
, bool KeepSuffix
,
70 ArrayRef
<StringRef
> Suffixes
) {
71 for (StringRef Suffix
: Suffixes
) {
72 size_t LTOSuffixPos
= Name
.find(Suffix
);
73 if (LTOSuffixPos
!= StringRef::npos
)
74 return Name
.substr(0, LTOSuffixPos
+ (KeepSuffix
? Suffix
.size() : 0));
79 std::optional
<StringRef
> getLTOCommonName(const StringRef Name
) {
80 return getCommonName(Name
, true,
81 {".__uniq.", ".lto_priv.", ".constprop.", ".llvm."});
84 std::optional
<uint8_t> readDWARFExpressionTargetReg(StringRef ExprBytes
) {
85 uint8_t Opcode
= ExprBytes
[0];
86 if (Opcode
== dwarf::DW_CFA_def_cfa_expression
)
88 assert((Opcode
== dwarf::DW_CFA_expression
||
89 Opcode
== dwarf::DW_CFA_val_expression
) &&
90 "invalid DWARF expression CFI");
91 assert(ExprBytes
.size() > 1 && "DWARF expression CFI is too short");
92 const uint8_t *const Start
=
93 reinterpret_cast<const uint8_t *>(ExprBytes
.drop_front(1).data());
94 const uint8_t *const End
=
95 reinterpret_cast<const uint8_t *>(Start
+ ExprBytes
.size() - 1);
96 uint8_t Reg
= decodeULEB128(Start
, nullptr, End
);
102 bool operator==(const llvm::MCCFIInstruction
&L
,
103 const llvm::MCCFIInstruction
&R
) {
104 if (L
.getOperation() != R
.getOperation())
106 switch (L
.getOperation()) {
107 case MCCFIInstruction::OpRestore
:
108 case MCCFIInstruction::OpSameValue
:
109 case MCCFIInstruction::OpUndefined
:
110 case MCCFIInstruction::OpDefCfaRegister
:
111 return L
.getRegister() == R
.getRegister();
112 case MCCFIInstruction::OpRegister
:
113 return L
.getRegister() == R
.getRegister() &&
114 L
.getRegister2() == R
.getRegister2();
115 case MCCFIInstruction::OpOffset
:
116 case MCCFIInstruction::OpRelOffset
:
117 case MCCFIInstruction::OpDefCfa
:
118 return L
.getRegister() == R
.getRegister() && L
.getOffset() == R
.getOffset();
119 case MCCFIInstruction::OpEscape
:
120 return L
.getValues() == R
.getValues();
121 case MCCFIInstruction::OpRememberState
:
122 case MCCFIInstruction::OpRestoreState
:
124 case MCCFIInstruction::OpDefCfaOffset
:
125 case MCCFIInstruction::OpAdjustCfaOffset
:
126 return L
.getOffset() == R
.getOffset();