Android Build Tools

This commit is contained in:
Isuru Samarathunga
2025-10-16 00:43:42 +05:30
parent f742dcfaff
commit 160bf65a1f
5549 changed files with 1752060 additions and 0 deletions

View File

@ -0,0 +1,81 @@
#!/usr/bin/env python
from __future__ import print_function
desc = """Generate the difference of two YAML files into a new YAML file (works on
pair of directories too). A new attribute 'Added' is set to True or False
depending whether the entry is added or removed from the first input to the
next.
The tools requires PyYAML."""
import yaml
# Try to use the C parser.
try:
from yaml import CLoader as Loader
except ImportError:
from yaml import Loader
import optrecord
import argparse
from collections import defaultdict
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=desc)
parser.add_argument(
"yaml_dir_or_file_1",
help="An optimization record file or a directory searched for optimization "
"record files that are used as the old version for the comparison",
)
parser.add_argument(
"yaml_dir_or_file_2",
help="An optimization record file or a directory searched for optimization "
"record files that are used as the new version for the comparison",
)
parser.add_argument(
"--jobs",
"-j",
default=None,
type=int,
help="Max job count (defaults to %(default)s, the current CPU count)",
)
parser.add_argument(
"--max-size",
"-m",
default=100000,
type=int,
help="Maximum number of remarks stored in an output file",
)
parser.add_argument(
"--no-progress-indicator",
"-n",
action="store_true",
default=False,
help="Do not display any indicator of how many YAML files were read.",
)
parser.add_argument("--output", "-o", default="diff{}.opt.yaml")
args = parser.parse_args()
files1 = optrecord.find_opt_files(args.yaml_dir_or_file_1)
files2 = optrecord.find_opt_files(args.yaml_dir_or_file_2)
print_progress = not args.no_progress_indicator
all_remarks1, _, _ = optrecord.gather_results(files1, args.jobs, print_progress)
all_remarks2, _, _ = optrecord.gather_results(files2, args.jobs, print_progress)
added = set(all_remarks2.values()) - set(all_remarks1.values())
removed = set(all_remarks1.values()) - set(all_remarks2.values())
for r in added:
r.Added = True
for r in removed:
r.Added = False
result = list(added | removed)
for r in result:
r.recover_yaml_structure()
for i in range(0, len(result), args.max_size):
with open(args.output.format(i / args.max_size), "w") as stream:
yaml.dump_all(result[i : i + args.max_size], stream)

View File

@ -0,0 +1,84 @@
#!/usr/bin/env python
from __future__ import print_function
desc = """Generate statistics about optimization records from the YAML files
generated with -fsave-optimization-record and -fdiagnostics-show-hotness.
The tools requires PyYAML and Pygments Python packages."""
import optrecord
import argparse
import operator
from collections import defaultdict
from multiprocessing import cpu_count, Pool
try:
from guppy import hpy
hp = hpy()
except ImportError:
print("Memory consumption not shown because guppy is not installed")
hp = None
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=desc)
parser.add_argument(
"yaml_dirs_or_files",
nargs="+",
help="List of optimization record files or directories searched "
"for optimization record files.",
)
parser.add_argument(
"--jobs",
"-j",
default=None,
type=int,
help="Max job count (defaults to %(default)s, the current CPU count)",
)
parser.add_argument(
"--no-progress-indicator",
"-n",
action="store_true",
default=False,
help="Do not display any indicator of how many YAML files were read.",
)
args = parser.parse_args()
print_progress = not args.no_progress_indicator
files = optrecord.find_opt_files(*args.yaml_dirs_or_files)
if not files:
parser.error("No *.opt.yaml files found")
sys.exit(1)
all_remarks, file_remarks, _ = optrecord.gather_results(
files, args.jobs, print_progress
)
if print_progress:
print("\n")
bypass = defaultdict(int)
byname = defaultdict(int)
for r in optrecord.itervalues(all_remarks):
bypass[r.Pass] += 1
byname[r.Pass + "/" + r.Name] += 1
total = len(all_remarks)
print("{:24s} {:10d}".format("Total number of remarks", total))
if hp:
h = hp.heap()
print("{:24s} {:10d}".format("Memory per remark", h.size / len(all_remarks)))
print("\n")
print("Top 10 remarks by pass:")
for (passname, count) in sorted(
bypass.items(), key=operator.itemgetter(1), reverse=True
)[:10]:
print(" {:30s} {:2.0f}%".format(passname, count * 100.0 / total))
print("\nTop 10 remarks:")
for (name, count) in sorted(
byname.items(), key=operator.itemgetter(1), reverse=True
)[:10]:
print(" {:30s} {:2.0f}%".format(name, count * 100.0 / total))

View File

@ -0,0 +1,471 @@
#!/usr/bin/env python
from __future__ import print_function
import argparse
import errno
import functools
import html
import io
from multiprocessing import cpu_count
import os.path
import re
import shutil
import sys
from pygments import highlight
from pygments.lexers.c_cpp import CppLexer
from pygments.formatters import HtmlFormatter
import optpmap
import optrecord
desc = """Generate HTML output to visualize optimization records from the YAML files
generated with -fsave-optimization-record and -fdiagnostics-show-hotness.
The tools requires PyYAML and Pygments Python packages."""
# This allows passing the global context to the child processes.
class Context:
def __init__(self, caller_loc=dict()):
# Map function names to their source location for function where inlining happened
self.caller_loc = caller_loc
context = Context()
def suppress(remark):
if remark.Name == "sil.Specialized":
return remark.getArgDict()["Function"][0].startswith('"Swift.')
elif remark.Name == "sil.Inlined":
return remark.getArgDict()["Callee"][0].startswith(
('"Swift.', '"specialized Swift.')
)
return False
class SourceFileRenderer:
def __init__(self, source_dir, output_dir, filename, no_highlight):
self.filename = filename
existing_filename = None
if os.path.exists(filename):
existing_filename = filename
else:
fn = os.path.join(source_dir, filename)
if os.path.exists(fn):
existing_filename = fn
self.no_highlight = no_highlight
self.stream = io.open(
os.path.join(output_dir, optrecord.html_file_name(filename)),
"w",
encoding="utf-8",
)
if existing_filename:
self.source_stream = io.open(existing_filename, encoding="utf-8")
else:
self.source_stream = None
print(
"""
<html>
<h1>Unable to locate file {}</h1>
</html>
""".format(
filename
),
file=self.stream,
)
self.html_formatter = HtmlFormatter(encoding="utf-8")
self.cpp_lexer = CppLexer(stripnl=False)
def render_source_lines(self, stream, line_remarks):
file_text = stream.read()
if self.no_highlight:
html_highlighted = file_text
else:
html_highlighted = highlight(file_text, self.cpp_lexer, self.html_formatter)
# Note that the API is different between Python 2 and 3. On
# Python 3, pygments.highlight() returns a bytes object, so we
# have to decode. On Python 2, the output is str but since we
# support unicode characters and the output streams is unicode we
# decode too.
html_highlighted = html_highlighted.decode("utf-8")
# Take off the header and footer, these must be
# reapplied line-wise, within the page structure
html_highlighted = html_highlighted.replace(
'<div class="highlight"><pre>', ""
)
html_highlighted = html_highlighted.replace("</pre></div>", "")
for (linenum, html_line) in enumerate(html_highlighted.split("\n"), start=1):
print(
"""
<tr>
<td><a name=\"L{linenum}\">{linenum}</a></td>
<td></td>
<td></td>
<td><div class="highlight"><pre>{html_line}</pre></div></td>
</tr>""".format(
**locals()
),
file=self.stream,
)
for remark in line_remarks.get(linenum, []):
if not suppress(remark):
self.render_inline_remarks(remark, html_line)
def render_inline_remarks(self, r, line):
inlining_context = r.DemangledFunctionName
dl = context.caller_loc.get(r.Function)
if dl:
dl_dict = dict(list(dl))
link = optrecord.make_link(dl_dict["File"], dl_dict["Line"] - 2)
inlining_context = "<a href={link}>{r.DemangledFunctionName}</a>".format(
**locals()
)
# Column is the number of characters *including* tabs, keep those and
# replace everything else with spaces.
indent = line[: max(r.Column, 1) - 1]
indent = re.sub("\S", " ", indent)
# Create expanded message and link if we have a multiline message.
lines = r.message.split("\n")
if len(lines) > 1:
expand_link = '<a style="text-decoration: none;" href="" onclick="toggleExpandedMessage(this); return false;">+</a>'
message = lines[0]
expand_message = """
<div class="full-info" style="display:none;">
<div class="col-left"><pre style="display:inline">{}</pre></div>
<div class="expanded col-left"><pre>{}</pre></div>
</div>""".format(
indent, "\n".join(lines[1:])
)
else:
expand_link = ""
expand_message = ""
message = r.message
print(
"""
<tr>
<td></td>
<td>{r.RelativeHotness}</td>
<td class=\"column-entry-{r.color}\">{r.PassWithDiffPrefix}</td>
<td><pre style="display:inline">{indent}</pre><span class=\"column-entry-yellow\">{expand_link} {message}&nbsp;</span>{expand_message}</td>
<td class=\"column-entry-yellow\">{inlining_context}</td>
</tr>""".format(
**locals()
),
file=self.stream,
)
def render(self, line_remarks):
if not self.source_stream:
return
print(
"""
<html>
<title>{}</title>
<meta charset="utf-8" />
<head>
<link rel='stylesheet' type='text/css' href='style.css'>
<script type="text/javascript">
/* Simple helper to show/hide the expanded message of a remark. */
function toggleExpandedMessage(e) {{
var FullTextElems = e.parentElement.parentElement.getElementsByClassName("full-info");
if (!FullTextElems || FullTextElems.length < 1) {{
return false;
}}
var FullText = FullTextElems[0];
if (FullText.style.display == 'none') {{
e.innerHTML = '-';
FullText.style.display = 'block';
}} else {{
e.innerHTML = '+';
FullText.style.display = 'none';
}}
}}
</script>
</head>
<body>
<div class="centered">
<table class="source">
<thead>
<tr>
<th style="width: 2%">Line</td>
<th style="width: 3%">Hotness</td>
<th style="width: 10%">Optimization</td>
<th style="width: 70%">Source</td>
<th style="width: 15%">Inline Context</td>
</tr>
</thead>
<tbody>""".format(
os.path.basename(self.filename)
),
file=self.stream,
)
self.render_source_lines(self.source_stream, line_remarks)
print(
"""
</tbody>
</table>
</body>
</html>""",
file=self.stream,
)
class IndexRenderer:
def __init__(
self, output_dir, should_display_hotness, max_hottest_remarks_on_index
):
self.stream = io.open(
os.path.join(output_dir, "index.html"), "w", encoding="utf-8"
)
self.should_display_hotness = should_display_hotness
self.max_hottest_remarks_on_index = max_hottest_remarks_on_index
def render_entry(self, r, odd):
escaped_name = html.escape(r.DemangledFunctionName)
print(
"""
<tr>
<td class=\"column-entry-{odd}\"><a href={r.Link}>{r.DebugLocString}</a></td>
<td class=\"column-entry-{odd}\">{r.RelativeHotness}</td>
<td class=\"column-entry-{odd}\">{escaped_name}</td>
<td class=\"column-entry-{r.color}\">{r.PassWithDiffPrefix}</td>
</tr>""".format(
**locals()
),
file=self.stream,
)
def render(self, all_remarks):
print(
"""
<html>
<meta charset="utf-8" />
<head>
<link rel='stylesheet' type='text/css' href='style.css'>
</head>
<body>
<div class="centered">
<table>
<tr>
<td>Source Location</td>
<td>Hotness</td>
<td>Function</td>
<td>Pass</td>
</tr>""",
file=self.stream,
)
max_entries = None
if self.should_display_hotness:
max_entries = self.max_hottest_remarks_on_index
for i, remark in enumerate(all_remarks[:max_entries]):
if not suppress(remark):
self.render_entry(remark, i % 2)
print(
"""
</table>
</body>
</html>""",
file=self.stream,
)
def _render_file(source_dir, output_dir, ctx, no_highlight, entry, filter_):
global context
context = ctx
filename, remarks = entry
SourceFileRenderer(source_dir, output_dir, filename, no_highlight).render(remarks)
def map_remarks(all_remarks):
# Set up a map between function names and their source location for
# function where inlining happened
for remark in optrecord.itervalues(all_remarks):
if (
isinstance(remark, optrecord.Passed)
and remark.Pass == "inline"
and remark.Name == "Inlined"
):
for arg in remark.Args:
arg_dict = dict(list(arg))
caller = arg_dict.get("Caller")
if caller:
try:
context.caller_loc[caller] = arg_dict["DebugLoc"]
except KeyError:
pass
def generate_report(
all_remarks,
file_remarks,
source_dir,
output_dir,
no_highlight,
should_display_hotness,
max_hottest_remarks_on_index,
num_jobs,
should_print_progress,
):
try:
os.makedirs(output_dir)
except OSError as e:
if e.errno == errno.EEXIST and os.path.isdir(output_dir):
pass
else:
raise
if should_print_progress:
print("Rendering index page...")
if should_display_hotness:
sorted_remarks = sorted(
optrecord.itervalues(all_remarks),
key=lambda r: (
r.Hotness,
r.File,
r.Line,
r.Column,
r.PassWithDiffPrefix,
r.yaml_tag,
r.Function,
),
reverse=True,
)
else:
sorted_remarks = sorted(
optrecord.itervalues(all_remarks),
key=lambda r: (
r.File,
r.Line,
r.Column,
r.PassWithDiffPrefix,
r.yaml_tag,
r.Function,
),
)
IndexRenderer(
output_dir, should_display_hotness, max_hottest_remarks_on_index
).render(sorted_remarks)
shutil.copy(
os.path.join(os.path.dirname(os.path.realpath(__file__)), "style.css"),
output_dir,
)
_render_file_bound = functools.partial(
_render_file, source_dir, output_dir, context, no_highlight
)
if should_print_progress:
print("Rendering HTML files...")
optpmap.pmap(
_render_file_bound, file_remarks.items(), num_jobs, should_print_progress
)
def main():
parser = argparse.ArgumentParser(description=desc)
parser.add_argument(
"yaml_dirs_or_files",
nargs="+",
help="List of optimization record files or directories searched "
"for optimization record files.",
)
parser.add_argument(
"--output-dir",
"-o",
default="html",
help="Path to a directory where generated HTML files will be output. "
"If the directory does not already exist, it will be created. "
'"%(default)s" by default.',
)
parser.add_argument(
"--jobs",
"-j",
default=None,
type=int,
help="Max job count (defaults to %(default)s, the current CPU count)",
)
parser.add_argument("--source-dir", "-s", default="", help="set source directory")
parser.add_argument(
"--no-progress-indicator",
"-n",
action="store_true",
default=False,
help="Do not display any indicator of how many YAML files were read "
"or rendered into HTML.",
)
parser.add_argument(
"--max-hottest-remarks-on-index",
default=1000,
type=int,
help="Maximum number of the hottest remarks to appear on the index page",
)
parser.add_argument(
"--no-highlight",
action="store_true",
default=False,
help="Do not use a syntax highlighter when rendering the source code",
)
parser.add_argument(
"--demangler",
help="Set the demangler to be used (defaults to %s)"
% optrecord.Remark.default_demangler,
)
parser.add_argument(
"--filter",
default="",
help="Only display remarks from passes matching filter expression",
)
# Do not make this a global variable. Values needed to be propagated through
# to individual classes and functions to be portable with multiprocessing across
# Windows and non-Windows.
args = parser.parse_args()
print_progress = not args.no_progress_indicator
if args.demangler:
optrecord.Remark.set_demangler(args.demangler)
files = optrecord.find_opt_files(*args.yaml_dirs_or_files)
if not files:
parser.error("No *.opt.yaml files found")
sys.exit(1)
all_remarks, file_remarks, should_display_hotness = optrecord.gather_results(
files, args.jobs, print_progress, args.filter
)
map_remarks(all_remarks)
generate_report(
all_remarks,
file_remarks,
args.source_dir,
args.output_dir,
args.no_highlight,
should_display_hotness,
args.max_hottest_remarks_on_index,
args.jobs,
print_progress,
)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,63 @@
import sys
import multiprocessing
_current = None
_total = None
def _init(current, total):
global _current
global _total
_current = current
_total = total
def _wrapped_func(func_and_args):
func, argument, should_print_progress, filter_ = func_and_args
if should_print_progress:
with _current.get_lock():
_current.value += 1
sys.stdout.write("\r\t{} of {}".format(_current.value, _total.value))
sys.stdout.flush()
return func(argument, filter_)
def pmap(
func, iterable, processes, should_print_progress, filter_=None, *args, **kwargs
):
"""
A parallel map function that reports on its progress.
Applies `func` to every item of `iterable` and return a list of the
results. If `processes` is greater than one, a process pool is used to run
the functions in parallel. `should_print_progress` is a boolean value that
indicates whether a string 'N of M' should be printed to indicate how many
of the functions have finished being run.
"""
global _current
global _total
_current = multiprocessing.Value("i", 0)
_total = multiprocessing.Value("i", len(iterable))
func_and_args = [(func, arg, should_print_progress, filter_) for arg in iterable]
if processes == 1:
result = list(map(_wrapped_func, func_and_args, *args, **kwargs))
else:
pool = multiprocessing.Pool(
initializer=_init,
initargs=(
_current,
_total,
),
processes=processes,
)
result = pool.map(_wrapped_func, func_and_args, *args, **kwargs)
pool.close()
pool.join()
if should_print_progress:
sys.stdout.write("\r")
return result

View File

@ -0,0 +1,218 @@
.source {
table-layout: fixed;
width: 100%;
white-space: nowrap;
}
.source td {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.red {
background-color: #ffd0d0;
}
.cyan {
background-color: cyan;
}
body {
font-family: -apple-system, sans-serif;
}
pre {
margin-top: 0px !important;
margin-bottom: 0px !important;
}
.source-name-title {
padding: 5px 10px;
border-bottom: 1px solid #dbdbdb;
background-color: #eee;
line-height: 35px;
}
.centered {
display: table;
margin-left: left;
margin-right: auto;
border: 1px solid #dbdbdb;
border-radius: 3px;
}
.expansion-view {
background-color: rgba(0, 0, 0, 0);
margin-left: 0px;
margin-top: 5px;
margin-right: 5px;
margin-bottom: 5px;
border: 1px solid #dbdbdb;
border-radius: 3px;
}
table {
border-collapse: collapse;
}
.light-row {
background: #ffffff;
border: 1px solid #dbdbdb;
}
.column-entry {
text-align: right;
}
.column-entry-left {
text-align: left;
}
.column-entry-white {
text-align: right;
background-color: #ffffff;
}
.column-entry-red {
text-align: right;
background-color: #ffd0d0;
}
.column-entry-green {
text-align: right;
background-color: #d0ffd0;
}
.column-entry-yellow {
text-align: left;
background-color: #ffe1a6;
}
.column-entry-0 {
background-color: #ffffff;
}
.column-entry-1 {
background-color: #eeeeee;
}
.line-number {
text-align: right;
color: #aaa;
}
.covered-line {
text-align: right;
color: #0080ff;
}
.uncovered-line {
text-align: right;
color: #ff3300;
}
.tooltip {
position: relative;
display: inline;
background-color: #b3e6ff;
text-decoration: none;
}
.tooltip span.tooltip-content {
position: absolute;
width: 100px;
margin-left: -50px;
color: #FFFFFF;
background: #000000;
height: 30px;
line-height: 30px;
text-align: center;
visibility: hidden;
border-radius: 6px;
}
.tooltip span.tooltip-content:after {
content: '';
position: absolute;
top: 100%;
left: 50%;
margin-left: -8px;
width: 0; height: 0;
border-top: 8px solid #000000;
border-right: 8px solid transparent;
border-left: 8px solid transparent;
}
:hover.tooltip span.tooltip-content {
visibility: visible;
opacity: 0.8;
bottom: 30px;
left: 50%;
z-index: 999;
}
th, td {
vertical-align: top;
padding: 2px 5px;
border-collapse: collapse;
border-right: solid 1px #eee;
border-left: solid 1px #eee;
}
td:first-child {
border-left: none;
}
td:last-child {
border-right: none;
}
.expanded {
background-color: #f2f2f2;
padding-top: 5px;
padding-left: 5px;
}
.col-left {
float: left;
margin-bottom: -99999px;
padding-bottom: 99999px;
}
/* Generated with pygmentize -S colorful -f html >> style.css */
.hll { background-color: #ffffcc }
.c { color: #888888 } /* Comment */
.err { color: #FF0000; background-color: #FFAAAA } /* Error */
.k { color: #008800; font-weight: bold } /* Keyword */
.o { color: #333333 } /* Operator */
.ch { color: #888888 } /* Comment.Hashbang */
.cm { color: #888888 } /* Comment.Multiline */
.cp { color: #557799 } /* Comment.Preproc */
.cpf { color: #888888 } /* Comment.PreprocFile */
.c1 { color: #888888 } /* Comment.Single */
.cs { color: #cc0000; font-weight: bold } /* Comment.Special */
.gd { color: #A00000 } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gr { color: #FF0000 } /* Generic.Error */
.gh { color: #000080; font-weight: bold } /* Generic.Heading */
.gi { color: #00A000 } /* Generic.Inserted */
.go { color: #888888 } /* Generic.Output */
.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.gt { color: #0044DD } /* Generic.Traceback */
.kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.kp { color: #003388; font-weight: bold } /* Keyword.Pseudo */
.kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.kt { color: #333399; font-weight: bold } /* Keyword.Type */
.m { color: #6600EE; font-weight: bold } /* Literal.Number */
.s { background-color: #fff0f0 } /* Literal.String */
.na { color: #0000CC } /* Name.Attribute */
.nb { color: #007020 } /* Name.Builtin */
.nc { color: #BB0066; font-weight: bold } /* Name.Class */
.no { color: #003366; font-weight: bold } /* Name.Constant */
.nd { color: #555555; font-weight: bold } /* Name.Decorator */
.ni { color: #880000; font-weight: bold } /* Name.Entity */
.ne { color: #FF0000; font-weight: bold } /* Name.Exception */
.nf { color: #0066BB; font-weight: bold } /* Name.Function */
.nl { color: #997700; font-weight: bold } /* Name.Label */
.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.nt { color: #007700 } /* Name.Tag */
.nv { color: #996633 } /* Name.Variable */
.ow { color: #000000; font-weight: bold } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mb { color: #6600EE; font-weight: bold } /* Literal.Number.Bin */
.mf { color: #6600EE; font-weight: bold } /* Literal.Number.Float */
.mh { color: #005588; font-weight: bold } /* Literal.Number.Hex */
.mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.mo { color: #4400EE; font-weight: bold } /* Literal.Number.Oct */
.sb { background-color: #fff0f0 } /* Literal.String.Backtick */
.sc { color: #0044DD } /* Literal.String.Char */
.sd { color: #DD4422 } /* Literal.String.Doc */
.s2 { background-color: #fff0f0 } /* Literal.String.Double */
.se { color: #666666; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */
.sh { background-color: #fff0f0 } /* Literal.String.Heredoc */
.si { background-color: #eeeeee } /* Literal.String.Interpol */
.sx { color: #DD2200; background-color: #fff0f0 } /* Literal.String.Other */
.sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */
.s1 { background-color: #fff0f0 } /* Literal.String.Single */
.ss { color: #AA6600 } /* Literal.String.Symbol */
.bp { color: #007020 } /* Name.Builtin.Pseudo */
.vc { color: #336699 } /* Name.Variable.Class */
.vg { color: #dd7700; font-weight: bold } /* Name.Variable.Global */
.vi { color: #3333BB } /* Name.Variable.Instance */
.il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */