Skip to content

Commit 0b026f3

Browse files
committed
[CGData] LLD for MachO
1 parent b5d7f5f commit 0b026f3

File tree

5 files changed

+126
-0
lines changed

5 files changed

+126
-0
lines changed

lld/MachO/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ struct Configuration {
207207
std::vector<SectionAlign> sectionAlignments;
208208
std::vector<SegmentProtection> segmentProtections;
209209
bool ltoDebugPassManager = false;
210+
llvm::StringRef codegenDataGeneratePath;
210211
bool csProfileGenerate = false;
211212
llvm::StringRef csProfilePath;
212213
bool pgoWarnMismatch;

lld/MachO/Driver.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "llvm/ADT/StringRef.h"
3737
#include "llvm/BinaryFormat/MachO.h"
3838
#include "llvm/BinaryFormat/Magic.h"
39+
#include "llvm/CodeGenData/CodeGenDataWriter.h"
3940
#include "llvm/Config/llvm-config.h"
4041
#include "llvm/LTO/LTO.h"
4142
#include "llvm/Object/Archive.h"
@@ -1250,6 +1251,38 @@ static void gatherInputSections() {
12501251
}
12511252
}
12521253

1254+
static void codegenDataGenerate() {
1255+
TimeTraceScope timeScope("Generating codegen data");
1256+
1257+
OutlinedHashTreeRecord globalOutlineRecord;
1258+
for (ConcatInputSection *isec : inputSections) {
1259+
if (isec->getSegName() == segment_names::data &&
1260+
isec->getName() == section_names::outlinedHashTree) {
1261+
// Read outlined hash tree from each section
1262+
OutlinedHashTreeRecord localOutlineRecord;
1263+
auto *data = isec->data.data();
1264+
localOutlineRecord.deserialize(data);
1265+
1266+
// Merge it to the global hash tree.
1267+
globalOutlineRecord.merge(localOutlineRecord);
1268+
}
1269+
}
1270+
1271+
CodeGenDataWriter Writer;
1272+
if (!globalOutlineRecord.empty())
1273+
Writer.addRecord(globalOutlineRecord);
1274+
1275+
std::error_code EC;
1276+
auto fileName = config->codegenDataGeneratePath;
1277+
assert(!fileName.empty());
1278+
raw_fd_ostream Output(fileName, EC, sys::fs::OF_None);
1279+
if (EC)
1280+
error("fail to create raw_fd_ostream");
1281+
1282+
if (auto E = Writer.write(Output))
1283+
error("fail to write CGData");
1284+
}
1285+
12531286
static void foldIdenticalLiterals() {
12541287
TimeTraceScope timeScope("Fold identical literals");
12551288
// We always create a cStringSection, regardless of whether dedupLiterals is
@@ -1665,6 +1698,8 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
16651698
config->ignoreAutoLinkOptions.insert(arg->getValue());
16661699
config->strictAutoLink = args.hasArg(OPT_strict_auto_link);
16671700
config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
1701+
config->codegenDataGeneratePath =
1702+
args.getLastArgValue(OPT_codegen_data_generate_path);
16681703
config->csProfileGenerate = args.hasArg(OPT_cs_profile_generate);
16691704
config->csProfilePath = args.getLastArgValue(OPT_cs_profile_path);
16701705
config->pgoWarnMismatch =
@@ -1959,6 +1994,10 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
19591994
}
19601995

19611996
gatherInputSections();
1997+
1998+
if (!config->codegenDataGeneratePath.empty())
1999+
codegenDataGenerate();
2000+
19622001
if (config->callGraphProfileSort)
19632002
priorityBuilder.extractCallGraphProfile();
19642003

lld/MachO/InputSection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ constexpr const char objcMethname[] = "__objc_methname";
353353
constexpr const char objcNonLazyCatList[] = "__objc_nlcatlist";
354354
constexpr const char objcNonLazyClassList[] = "__objc_nlclslist";
355355
constexpr const char objcProtoList[] = "__objc_protolist";
356+
constexpr const char outlinedHashTree[] = "__llvm_outline";
356357
constexpr const char pageZero[] = "__pagezero";
357358
constexpr const char pointers[] = "__pointers";
358359
constexpr const char rebase[] = "__rebase";

lld/MachO/Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ def no_objc_category_merging : Flag<["-"], "no_objc_category_merging">,
137137
Group<grp_lld>;
138138
def lto_debug_pass_manager: Flag<["--"], "lto-debug-pass-manager">,
139139
HelpText<"Debug new pass manager">, Group<grp_lld>;
140+
def codegen_data_generate_path : Joined<["--"], "codegen-data-generate-path=">,
141+
HelpText<"Codegen data file path">, Group<grp_lld>;
140142
def cs_profile_generate: Flag<["--"], "cs-profile-generate">,
141143
HelpText<"Perform context sensitive PGO instrumentation">, Group<grp_lld>;
142144
def cs_profile_path: Joined<["--"], "cs-profile-path=">,

lld/test/MachO/cgdata-generate.s

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# REQUIRES: aarch64
2+
3+
# RUN: rm -rf %t; split-file %s %t
4+
5+
# RUN: llvm-mc -filetype obj -triple arm64-apple-darwin %t/merge-1.s -o %t/merge-1.o
6+
# RUN: llvm-mc -filetype obj -triple arm64-apple-darwin %t/merge-2.s -o %t/merge-2.o
7+
# RUN: llvm-mc -filetype obj -triple arm64-apple-darwin %t/main.s -o %t/main.o
8+
9+
# This checks if the codegen data from the linker is identical to the merged codegen data
10+
# from each object file, which is obtained using the llvm-cgdata tool.
11+
# RUN: %no-arg-lld -dylib -arch arm64 -platform_version ios 14.0 15.0 -o %t/out \
12+
# RUN: %t/merge-1.o %t/merge-2.o %t/main.o --codegen-data-generate-path=%t/out-cgdata
13+
# RUN: llvm-cgdata merge %t/merge-1.o %t/merge-2.o %t/main.o -o %t/merge-cgdata
14+
# RUN: diff %t/out-cgdata %t/merge-cgdata
15+
16+
# Merge order doesn't matter. `main.o` is dropped due to missing __llvm_outline.
17+
# RUN: llvm-cgdata merge %t/merge-2.o %t/merge-1.o -o %t/merge-cgdata-shuffle
18+
# RUN: diff %t/out-cgdata %t/merge-cgdata-shuffle
19+
20+
# We can also generate the merged codegen data from the executable that is not dead-stripped.
21+
# RUN: llvm-objdump -h %t/out| FileCheck %s
22+
CHECK: __llvm_outline
23+
# RUN: llvm-cgdata merge %t/out -o %t/merge-cgdata-exe
24+
# RUN: diff %t/merge-cgdata-exe %t/merge-cgdata
25+
26+
# Dead-strip will remove __llvm_outline sections from the final executable.
27+
# But the codeden data is still correctly produced from the linker.
28+
# RUN: %no-arg-lld -dylib -arch arm64 -platform_version ios 14.0 15.0 -o %t/out-strip \
29+
# RUN: %t/merge-1.o %t/merge-2.o %t/main.o -dead_strip --codegen-data-generate-path=%t/out-cgdata-strip
30+
# RUN: llvm-cgdata merge %t/merge-1.o %t/merge-2.o %t/main.o -o %t/merge-cgdata-strip
31+
# RUN: diff %t/out-cgdata-strip %t/merge-cgdata-strip
32+
# RUN: diff %t/out-cgdata-strip %t/merge-cgdata
33+
34+
# Ensure no __llvm_outline section remains in the executable.
35+
# RUN: llvm-objdump -h %t/out-strip | FileCheck %s --check-prefix=STRIP
36+
STRIP-NOT: __llvm_outline
37+
38+
#--- merge-1.s
39+
# The .data is encoded in a binary form based on the following yaml form. See serialize() in OutlinedHashTreeRecord.cpp
40+
#---
41+
#0:
42+
# Hash: 0x0
43+
# Terminals: 0
44+
# SuccessorIds: [ 1 ]
45+
#1:
46+
# Hash: 0x1
47+
# Terminals: 0
48+
# SuccessorIds: [ 2 ]
49+
#2:
50+
# Hash: 0x2
51+
# Terminals: 4
52+
# SuccessorIds: [ ]
53+
#...
54+
.section __DATA,__llvm_outline
55+
_data:
56+
.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00
57+
58+
#--- merge-2.s
59+
# The .data is encoded in a binary form based on the following yaml form. See serialize() in OutlinedHashTreeRecord.cpp
60+
#---
61+
#0:
62+
# Hash: 0x0
63+
# Terminals: 0
64+
# SuccessorIds: [ 1 ]
65+
#1:
66+
# Hash: 0x1
67+
# Terminals: 0
68+
# SuccessorIds: [ 2 ]
69+
#2:
70+
# Hash: 0x3
71+
# Terminals: 5
72+
# SuccessorIds: [ ]
73+
#...
74+
.section __DATA,__llvm_outline
75+
_data:
76+
.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
77+
78+
#--- main.s
79+
.globl _main
80+
81+
.text
82+
_main:
83+
ret

0 commit comments

Comments
 (0)