Skip to content

Commit d580ed0

Browse files
Merge branch 'users/boomanaiden154/refactor-buildkite-shell-scripts' into users/boomanaiden154/github-actions-linux-pipeline
2 parents 86d4a9b + b54681c commit d580ed0

File tree

920 files changed

+33443
-12686
lines changed

Some content is hidden

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

920 files changed

+33443
-12686
lines changed

.ci/generate_test_report.py

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# python3 -m unittest discover -p generate_test_report.py
66

77
import argparse
8+
import os
89
import subprocess
910
import unittest
1011
from io import StringIO
@@ -267,6 +268,46 @@ def test_report_dont_list_failures(self):
267268
),
268269
)
269270

271+
def test_report_dont_list_failures_link_to_log(self):
272+
self.assertEqual(
273+
_generate_report(
274+
"Foo",
275+
[
276+
junit_from_xml(
277+
dedent(
278+
"""\
279+
<?xml version="1.0" encoding="UTF-8"?>
280+
<testsuites time="0.02">
281+
<testsuite name="Bar" tests="1" failures="1" skipped="0" time="0.02">
282+
<testcase classname="Bar/test_1" name="test_1" time="0.02">
283+
<failure><![CDATA[Output goes here]]></failure>
284+
</testcase>
285+
</testsuite>
286+
</testsuites>"""
287+
)
288+
)
289+
],
290+
list_failures=False,
291+
buildkite_info={
292+
"BUILDKITE_ORGANIZATION_SLUG": "organization_slug",
293+
"BUILDKITE_PIPELINE_SLUG": "pipeline_slug",
294+
"BUILDKITE_BUILD_NUMBER": "build_number",
295+
"BUILDKITE_JOB_ID": "job_id",
296+
},
297+
),
298+
(
299+
dedent(
300+
"""\
301+
# Foo
302+
303+
* 1 test failed
304+
305+
Failed tests and their output was too large to report. [Download](https://buildkite.com/organizations/organization_slug/pipelines/pipeline_slug/builds/build_number/jobs/job_id/download.txt) the build's log file to see the details."""
306+
),
307+
"error",
308+
),
309+
)
310+
270311
def test_report_size_limit(self):
271312
self.assertEqual(
272313
_generate_report(
@@ -308,7 +349,13 @@ def test_report_size_limit(self):
308349
# listed. This minimal report will always fit into an annotation.
309350
# If include failures is False, total number of test will be reported but their names
310351
# and output will not be.
311-
def _generate_report(title, junit_objects, size_limit=1024 * 1024, list_failures=True):
352+
def _generate_report(
353+
title,
354+
junit_objects,
355+
size_limit=1024 * 1024,
356+
list_failures=True,
357+
buildkite_info=None,
358+
):
312359
if not junit_objects:
313360
return ("", "success")
314361

@@ -354,11 +401,21 @@ def plural(num_tests):
354401
report.append(f"* {tests_failed} {plural(tests_failed)} failed")
355402

356403
if not list_failures:
404+
if buildkite_info is not None:
405+
log_url = (
406+
"https://buildkite.com/organizations/{BUILDKITE_ORGANIZATION_SLUG}/"
407+
"pipelines/{BUILDKITE_PIPELINE_SLUG}/builds/{BUILDKITE_BUILD_NUMBER}/"
408+
"jobs/{BUILDKITE_JOB_ID}/download.txt".format(**buildkite_info)
409+
)
410+
download_text = f"[Download]({log_url})"
411+
else:
412+
download_text = "Download"
413+
357414
report.extend(
358415
[
359416
"",
360417
"Failed tests and their output was too large to report. "
361-
"Download the build's log file to see the details.",
418+
f"{download_text} the build's log file to see the details.",
362419
]
363420
)
364421
elif failures:
@@ -381,13 +438,23 @@ def plural(num_tests):
381438

382439
report = "\n".join(report)
383440
if len(report.encode("utf-8")) > size_limit:
384-
return _generate_report(title, junit_objects, size_limit, list_failures=False)
441+
return _generate_report(
442+
title,
443+
junit_objects,
444+
size_limit,
445+
list_failures=False,
446+
buildkite_info=buildkite_info,
447+
)
385448

386449
return report, style
387450

388451

389-
def generate_report(title, junit_files):
390-
return _generate_report(title, [JUnitXml.fromfile(p) for p in junit_files])
452+
def generate_report(title, junit_files, buildkite_info):
453+
return _generate_report(
454+
title,
455+
[JUnitXml.fromfile(p) for p in junit_files],
456+
buildkite_info=buildkite_info,
457+
)
391458

392459

393460
if __name__ == "__main__":
@@ -399,7 +466,18 @@ def generate_report(title, junit_files):
399466
parser.add_argument("junit_files", help="Paths to JUnit report files.", nargs="*")
400467
args = parser.parse_args()
401468

402-
report, style = generate_report(args.title, args.junit_files)
469+
# All of these are required to build a link to download the log file.
470+
env_var_names = [
471+
"BUILDKITE_ORGANIZATION_SLUG",
472+
"BUILDKITE_PIPELINE_SLUG",
473+
"BUILDKITE_BUILD_NUMBER",
474+
"BUILDKITE_JOB_ID",
475+
]
476+
buildkite_info = {k: v for k, v in os.environ.items() if k in env_var_names}
477+
if len(buildkite_info) != len(env_var_names):
478+
buildkite_info = None
479+
480+
report, style = generate_report(args.title, args.junit_files, buildkite_info)
403481

404482
if report:
405483
p = subprocess.Popen(

bolt/docs/BinaryAnalysis.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# BOLT-based binary analysis
2+
3+
As part of post-link-time optimizing, BOLT needs to perform a range of analyses
4+
on binaries such as recontructing control flow graphs, and more.
5+
6+
The `llvm-bolt-binary-analysis` tool enables running requested binary analyses
7+
on binaries, and generating reports. It does this by building on top of the
8+
analyses implemented in the BOLT libraries.
9+
10+
## Which binary analyses are implemented?
11+
12+
At the moment, no binary analyses are implemented.
13+
14+
The goal is to make it easy using a plug-in framework to add your own analyses.
15+
16+
## How to add your own binary analysis
17+
18+
_TODO: this section needs to be written. Ideally, we should have a simple
19+
"example" or "template" analysis that can be the starting point for implementing
20+
custom analyses_

bolt/include/bolt/Core/DIEBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ class DIEBuilder {
162162

163163
/// Clone an attribute in reference format.
164164
void cloneDieOffsetReferenceAttribute(
165-
DIE &Die, const DWARFUnit &U, const DWARFDie &InputDIE,
165+
DIE &Die, DWARFUnit &U, const DWARFDie &InputDIE,
166166
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, uint64_t Ref);
167167

168168
/// Clone an attribute in block format.

bolt/include/bolt/Core/DebugNames.h

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ class DWARF5AcceleratorTable {
7272
return std::move(FullTableBuffer);
7373
}
7474
/// Adds a DIE that is referenced across CUs.
75-
void addCrossCUDie(const DIE *Die) {
76-
CrossCUDies.insert({Die->getOffset(), Die});
75+
void addCrossCUDie(DWARFUnit *Unit, const DIE *Die) {
76+
CrossCUDies.insert({Die->getOffset(), {Unit, Die}});
7777
}
7878
/// Returns true if the DIE can generate an entry for a cross cu reference.
7979
/// This only checks TAGs of a DIE because when this is invoked DIE might not
@@ -145,7 +145,7 @@ class DWARF5AcceleratorTable {
145145
llvm::DenseMap<uint64_t, uint32_t> CUOffsetsToPatch;
146146
// Contains a map of Entry ID to Entry relative offset.
147147
llvm::DenseMap<uint64_t, uint32_t> EntryRelativeOffsets;
148-
llvm::DenseMap<uint64_t, const DIE *> CrossCUDies;
148+
llvm::DenseMap<uint64_t, std::pair<DWARFUnit *, const DIE *>> CrossCUDies;
149149
/// Adds Unit to either CUList, LocalTUList or ForeignTUList.
150150
/// Input Unit being processed, and DWO ID if Unit is being processed comes
151151
/// from a DWO section.
@@ -191,6 +191,29 @@ class DWARF5AcceleratorTable {
191191
void emitData();
192192
/// Emit augmentation string.
193193
void emitAugmentationString() const;
194+
/// Creates a new entry for a given DIE.
195+
std::optional<BOLTDWARF5AccelTableData *>
196+
addEntry(DWARFUnit &DU, const DIE &CurrDie,
197+
const std::optional<uint64_t> &DWOID,
198+
const std::optional<BOLTDWARF5AccelTableData *> &Parent,
199+
const std::optional<std::string> &Name,
200+
const uint32_t NumberParentsInChain);
201+
/// Returns UnitID for a given DWARFUnit.
202+
uint32_t getUnitID(const DWARFUnit &Unit,
203+
const std::optional<uint64_t> &DWOID, bool &IsTU);
204+
std::optional<std::string> getName(DWARFUnit &DU,
205+
const std::optional<uint64_t> &DWOID,
206+
const std::string &NameToUse,
207+
DIEValue ValName);
208+
/// Processes a DIE with references to other DIEs for DW_AT_name and
209+
/// DW_AT_linkage_name resolution.
210+
/// If DW_AT_name exists method creates a new entry for this DIE and returns
211+
/// it.
212+
std::optional<BOLTDWARF5AccelTableData *> processReferencedDie(
213+
DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t> &DWOID,
214+
const std::optional<BOLTDWARF5AccelTableData *> &Parent,
215+
const std::string &NameToUse, const uint32_t NumberParentsInChain,
216+
const dwarf::Attribute &Attr);
194217
};
195218
} // namespace bolt
196219
} // namespace llvm

bolt/include/bolt/Rewrite/RewriteInstance.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ class RewriteInstance {
164164

165165
void preregisterSections();
166166

167+
/// run analyses requested in binary analysis mode.
168+
void runBinaryAnalyses();
169+
167170
/// Run optimizations that operate at the binary, or post-linker, level.
168171
void runOptimizationPasses();
169172

bolt/include/bolt/Utils/CommandLineOpts.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
namespace opts {
1919

2020
extern bool HeatmapMode;
21+
extern bool BinaryAnalysisMode;
2122

2223
extern llvm::cl::OptionCategory BoltCategory;
2324
extern llvm::cl::OptionCategory BoltDiffCategory;
@@ -27,6 +28,7 @@ extern llvm::cl::OptionCategory BoltOutputCategory;
2728
extern llvm::cl::OptionCategory AggregatorCategory;
2829
extern llvm::cl::OptionCategory BoltInstrCategory;
2930
extern llvm::cl::OptionCategory HeatmapCategory;
31+
extern llvm::cl::OptionCategory BinaryAnalysisCategory;
3032

3133
extern llvm::cl::opt<unsigned> AlignText;
3234
extern llvm::cl::opt<unsigned> AlignFunctions;

bolt/lib/Core/BinaryEmitter.cpp

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,17 @@ BreakFunctionNames("break-funcs",
4646
cl::Hidden,
4747
cl::cat(BoltCategory));
4848

49-
static cl::list<std::string>
50-
FunctionPadSpec("pad-funcs",
51-
cl::CommaSeparated,
52-
cl::desc("list of functions to pad with amount of bytes"),
53-
cl::value_desc("func1:pad1,func2:pad2,func3:pad3,..."),
54-
cl::Hidden,
55-
cl::cat(BoltCategory));
49+
cl::list<std::string>
50+
FunctionPadSpec("pad-funcs", cl::CommaSeparated,
51+
cl::desc("list of functions to pad with amount of bytes"),
52+
cl::value_desc("func1:pad1,func2:pad2,func3:pad3,..."),
53+
cl::Hidden, cl::cat(BoltCategory));
54+
55+
cl::list<std::string> FunctionPadBeforeSpec(
56+
"pad-funcs-before", cl::CommaSeparated,
57+
cl::desc("list of functions to pad with amount of bytes"),
58+
cl::value_desc("func1:pad1,func2:pad2,func3:pad3,..."), cl::Hidden,
59+
cl::cat(BoltCategory));
5660

5761
static cl::opt<bool> MarkFuncs(
5862
"mark-funcs",
@@ -70,11 +74,12 @@ X86AlignBranchBoundaryHotOnly("x86-align-branch-boundary-hot-only",
7074
cl::init(true),
7175
cl::cat(BoltOptCategory));
7276

73-
size_t padFunction(const BinaryFunction &Function) {
77+
size_t padFunction(const cl::list<std::string> &Spec,
78+
const BinaryFunction &Function) {
7479
static std::map<std::string, size_t> FunctionPadding;
7580

76-
if (FunctionPadding.empty() && !FunctionPadSpec.empty()) {
77-
for (std::string &Spec : FunctionPadSpec) {
81+
if (FunctionPadding.empty() && !Spec.empty()) {
82+
for (const std::string &Spec : Spec) {
7883
size_t N = Spec.find(':');
7984
if (N == std::string::npos)
8085
continue;
@@ -319,6 +324,32 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
319324
Streamer.emitCodeAlignment(Function.getAlign(), &*BC.STI);
320325
}
321326

327+
if (size_t Padding =
328+
opts::padFunction(opts::FunctionPadBeforeSpec, Function)) {
329+
// Handle padFuncsBefore after the above alignment logic but before
330+
// symbol addresses are decided.
331+
if (!BC.HasRelocations) {
332+
BC.errs() << "BOLT-ERROR: -pad-before-funcs is not supported in "
333+
<< "non-relocation mode\n";
334+
exit(1);
335+
}
336+
337+
// Preserve Function.getMinAlign().
338+
if (!isAligned(Function.getMinAlign(), Padding)) {
339+
BC.errs() << "BOLT-ERROR: user-requested " << Padding
340+
<< " padding bytes before function " << Function
341+
<< " is not a multiple of the minimum function alignment ("
342+
<< Function.getMinAlign().value() << ").\n";
343+
exit(1);
344+
}
345+
346+
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: padding before function " << Function
347+
<< " with " << Padding << " bytes\n");
348+
349+
// Since the padding is not executed, it can be null bytes.
350+
Streamer.emitFill(Padding, 0);
351+
}
352+
322353
MCContext &Context = Streamer.getContext();
323354
const MCAsmInfo *MAI = Context.getAsmInfo();
324355

@@ -373,7 +404,7 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
373404
emitFunctionBody(Function, FF, /*EmitCodeOnly=*/false);
374405

375406
// Emit padding if requested.
376-
if (size_t Padding = opts::padFunction(Function)) {
407+
if (size_t Padding = opts::padFunction(opts::FunctionPadSpec, Function)) {
377408
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: padding function " << Function << " with "
378409
<< Padding << " bytes\n");
379410
Streamer.emitFill(Padding, MAI->getTextAlignFillValue());

bolt/lib/Core/DIEBuilder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ DWARFDie DIEBuilder::resolveDIEReference(
622622
}
623623

624624
void DIEBuilder::cloneDieOffsetReferenceAttribute(
625-
DIE &Die, const DWARFUnit &U, const DWARFDie &InputDIE,
625+
DIE &Die, DWARFUnit &U, const DWARFDie &InputDIE,
626626
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, uint64_t Ref) {
627627
DIE *NewRefDie = nullptr;
628628
DWARFUnit *RefUnit = nullptr;
@@ -654,7 +654,7 @@ void DIEBuilder::cloneDieOffsetReferenceAttribute(
654654
// Adding referenced DIE to DebugNames to be used when entries are created
655655
// that contain cross cu references.
656656
if (DebugNamesTable.canGenerateEntryWithCrossCUReference(U, Die, AttrSpec))
657-
DebugNamesTable.addCrossCUDie(DieInfo.Die);
657+
DebugNamesTable.addCrossCUDie(&U, DieInfo.Die);
658658
// no matter forward reference or backward reference, we are supposed
659659
// to calculate them in `finish` due to the possible modification of
660660
// the DIE.

0 commit comments

Comments
 (0)