Skip to content

Commit c203496

Browse files
Merge branch 'main' into lwg-4140
2 parents b2db095 + 416c7b3 commit c203496

File tree

71 files changed

+834
-1632
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+834
-1632
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,17 @@ class BinaryContext {
537537
BinaryFunction *createInjectedBinaryFunction(const std::string &Name,
538538
bool IsSimple = true);
539539

540+
/// Patch the original binary contents at address \p Address with a sequence
541+
/// of instructions from the \p Instructions list. The callee is responsible
542+
/// for checking that the sequence doesn't cross any function or section
543+
/// boundaries.
544+
///
545+
/// Optional \p Name can be assigned to the patch. The name will be emitted to
546+
/// the symbol table at \p Address.
547+
BinaryFunction *createInstructionPatch(uint64_t Address,
548+
InstructionListType &Instructions,
549+
const Twine &Name = "");
550+
540551
std::vector<BinaryFunction *> &getInjectedBinaryFunctions() {
541552
return InjectedBinaryFunctions;
542553
}

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -637,10 +637,6 @@ class MCPlusBuilder {
637637
return false;
638638
}
639639

640-
virtual void getADRReg(const MCInst &Inst, MCPhysReg &RegName) const {
641-
llvm_unreachable("not implemented");
642-
}
643-
644640
virtual bool isMoveMem2Reg(const MCInst &Inst) const { return false; }
645641

646642
virtual bool mayLoad(const MCInst &Inst) const {
@@ -1538,6 +1534,13 @@ class MCPlusBuilder {
15381534
llvm_unreachable("not implemented");
15391535
}
15401536

1537+
/// Undo the linker's ADRP+ADD to ADR relaxation. Take \p ADRInst and return
1538+
/// ADRP+ADD instruction sequence.
1539+
virtual InstructionListType undoAdrpAddRelaxation(const MCInst &ADRInst,
1540+
MCContext *Ctx) const {
1541+
llvm_unreachable("not implemented");
1542+
}
1543+
15411544
/// Return not 0 if the instruction CurInst, in combination with the recent
15421545
/// history of disassembled instructions supplied by [Begin, End), is a linker
15431546
/// generated veneer/stub that needs patching. This happens in AArch64 when

bolt/include/bolt/Passes/PatchEntries.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ class PatchEntries : public BinaryFunctionPass {
2626
struct Patch {
2727
const MCSymbol *Symbol;
2828
uint64_t Address;
29-
uint64_t FileOffset;
30-
BinarySection *Section;
3129
};
3230

3331
public:

bolt/lib/Core/BinaryContext.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,6 +2400,32 @@ BinaryContext::createInjectedBinaryFunction(const std::string &Name,
24002400
return BF;
24012401
}
24022402

2403+
BinaryFunction *BinaryContext::createInstructionPatch(
2404+
uint64_t Address, InstructionListType &Instructions, const Twine &Name) {
2405+
ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
2406+
assert(Section && "cannot get section for patching");
2407+
assert(Section->hasSectionRef() && Section->isText() &&
2408+
"can only patch input file code sections");
2409+
2410+
const uint64_t FileOffset =
2411+
Section->getInputFileOffset() + Address - Section->getAddress();
2412+
2413+
std::string PatchName = Name.str();
2414+
if (PatchName.empty()) {
2415+
// Assign unique name to the patch.
2416+
static uint64_t N = 0;
2417+
PatchName = "__BP_" + std::to_string(N++);
2418+
}
2419+
2420+
BinaryFunction *PBF = createInjectedBinaryFunction(PatchName);
2421+
PBF->setOutputAddress(Address);
2422+
PBF->setFileOffset(FileOffset);
2423+
PBF->setOriginSection(&Section.get());
2424+
PBF->addBasicBlock()->addInstructions(Instructions);
2425+
2426+
return PBF;
2427+
}
2428+
24032429
std::pair<size_t, size_t>
24042430
BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) {
24052431
// Adjust branch instruction to match the current layout.

bolt/lib/Passes/ADRRelaxationPass.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,10 @@ void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) {
7171
continue;
7272
}
7373

74-
MCPhysReg Reg;
75-
BC.MIB->getADRReg(Inst, Reg);
76-
int64_t Addend = BC.MIB->getTargetAddend(Inst);
77-
InstructionListType Addr;
78-
74+
InstructionListType AdrpAdd;
7975
{
8076
auto L = BC.scopeLock();
81-
Addr = BC.MIB->materializeAddress(Symbol, BC.Ctx.get(), Reg, Addend);
77+
AdrpAdd = BC.MIB->undoAdrpAddRelaxation(Inst, BC.Ctx.get());
8278
}
8379

8480
if (It != BB.begin() && BC.MIB->isNoop(*std::prev(It))) {
@@ -99,7 +95,7 @@ void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) {
9995
PassFailed = true;
10096
return;
10197
}
102-
It = BB.replaceInstruction(It, Addr);
98+
It = BB.replaceInstruction(It, AdrpAdd);
10399
}
104100
}
105101
}

bolt/lib/Passes/PatchEntries.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,8 @@ Error PatchEntries::runOnFunctions(BinaryContext &BC) {
8383
return false;
8484
}
8585

86-
PendingPatches.emplace_back(Patch{Symbol, Function.getAddress() + Offset,
87-
Function.getFileOffset() + Offset,
88-
Function.getOriginSection()});
86+
PendingPatches.emplace_back(
87+
Patch{Symbol, Function.getAddress() + Offset});
8988
NextValidByte = Offset + PatchSize;
9089
if (NextValidByte > Function.getMaxSize()) {
9190
if (opts::Verbosity >= 1)
@@ -118,16 +117,12 @@ Error PatchEntries::runOnFunctions(BinaryContext &BC) {
118117
}
119118

120119
for (Patch &Patch : PendingPatches) {
121-
BinaryFunction *PatchFunction = BC.createInjectedBinaryFunction(
120+
// Add instruction patch to the binary.
121+
InstructionListType Instructions;
122+
BC.MIB->createLongTailCall(Instructions, Patch.Symbol, BC.Ctx.get());
123+
BinaryFunction *PatchFunction = BC.createInstructionPatch(
124+
Patch.Address, Instructions,
122125
NameResolver::append(Patch.Symbol->getName(), ".org.0"));
123-
// Force the function to be emitted at the given address.
124-
PatchFunction->setOutputAddress(Patch.Address);
125-
PatchFunction->setFileOffset(Patch.FileOffset);
126-
PatchFunction->setOriginSection(Patch.Section);
127-
128-
InstructionListType Seq;
129-
BC.MIB->createLongTailCall(Seq, Patch.Symbol, BC.Ctx.get());
130-
PatchFunction->addBasicBlock()->addInstructions(Seq);
131126

132127
// Verify the size requirements.
133128
uint64_t HotSize, ColdSize;

bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,23 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
278278
return Inst.getOpcode() == AArch64::ADDXri;
279279
}
280280

281-
void getADRReg(const MCInst &Inst, MCPhysReg &RegName) const override {
281+
MCPhysReg getADRReg(const MCInst &Inst) const {
282282
assert((isADR(Inst) || isADRP(Inst)) && "Not an ADR instruction");
283283
assert(MCPlus::getNumPrimeOperands(Inst) != 0 &&
284284
"No operands for ADR instruction");
285285
assert(Inst.getOperand(0).isReg() &&
286286
"Unexpected operand in ADR instruction");
287-
RegName = Inst.getOperand(0).getReg();
287+
return Inst.getOperand(0).getReg();
288+
}
289+
290+
InstructionListType undoAdrpAddRelaxation(const MCInst &ADRInst,
291+
MCContext *Ctx) const override {
292+
assert(isADR(ADRInst) && "ADR instruction expected");
293+
294+
const MCPhysReg Reg = getADRReg(ADRInst);
295+
const MCSymbol *Target = getTargetSymbol(ADRInst);
296+
const uint64_t Addend = getTargetAddend(ADRInst);
297+
return materializeAddress(Target, Ctx, Reg, Addend);
288298
}
289299

290300
bool isTB(const MCInst &Inst) const {

bolt/test/X86/Inputs/define_bar.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Mocks a vtable object weak def in the C++ stdlib.
2-
.data.rel.ro
2+
.section .data.rel.ro,"aw"
33
.weak bar
44
.type bar, %object
55
bar:

clang/bindings/python/clang/cindex.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2713,6 +2713,21 @@ def visitor(base, children):
27132713
conf.lib.clang_visitCXXBaseClasses(self, fields_visit_callback(visitor), bases)
27142714
return iter(bases)
27152715

2716+
def get_methods(self):
2717+
"""Return an iterator for accessing the methods of this type."""
2718+
2719+
def visitor(method, children):
2720+
assert method != conf.lib.clang_getNullCursor()
2721+
2722+
# Create reference to TU so it isn't GC'd before Cursor.
2723+
method._tu = self._tu
2724+
methods.append(method)
2725+
return 1 # continue
2726+
2727+
methods: list[Cursor] = []
2728+
conf.lib.clang_visitCXXMethods(self, fields_visit_callback(visitor), methods)
2729+
return iter(methods)
2730+
27162731
def get_exception_specification_kind(self):
27172732
"""
27182733
Return the kind of the exception specification; a value from
@@ -4020,6 +4035,7 @@ def set_property(self, property, value):
40204035
),
40214036
("clang_visitChildren", [Cursor, cursor_visit_callback, py_object], c_uint),
40224037
("clang_visitCXXBaseClasses", [Type, fields_visit_callback, py_object], c_uint),
4038+
("clang_visitCXXMethods", [Type, fields_visit_callback, py_object], c_uint),
40234039
("clang_Cursor_getNumArguments", [Cursor], c_int),
40244040
("clang_Cursor_getArgument", [Cursor, c_uint], Cursor),
40254041
("clang_Cursor_getNumTemplateArguments", [Cursor], c_int),

clang/bindings/python/tests/cindex/test_type.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,3 +559,21 @@ class Template : public A, public B, virtual C {
559559
self.assertEqual(bases[1].get_base_offsetof(cursor_type_decl), 96)
560560
self.assertTrue(bases[2].is_virtual_base())
561561
self.assertEqual(bases[2].get_base_offsetof(cursor_type_decl), 128)
562+
563+
def test_class_methods(self):
564+
source = """
565+
template <typename T>
566+
class Template { void Foo(); };
567+
typedef Template<int> instance;
568+
instance bar;
569+
"""
570+
tu = get_tu(source, lang="cpp", flags=["--target=x86_64-linux-gnu"])
571+
cursor = get_cursor(tu, "instance")
572+
cursor_type = cursor.underlying_typedef_type
573+
self.assertEqual(cursor.kind, CursorKind.TYPEDEF_DECL)
574+
methods = list(cursor_type.get_methods())
575+
self.assertEqual(len(methods), 4)
576+
self.assertEqual(methods[0].kind, CursorKind.CXX_METHOD)
577+
self.assertEqual(methods[1].kind, CursorKind.CONSTRUCTOR)
578+
self.assertEqual(methods[2].kind, CursorKind.CONSTRUCTOR)
579+
self.assertEqual(methods[3].kind, CursorKind.CONSTRUCTOR)

0 commit comments

Comments
 (0)