Skip to content

Commit

Permalink
merge main into amd-staging
Browse files Browse the repository at this point in the history
Change-Id: I7987a7bb8c9f5efadab3abc4bbe3133914ce6a00
  • Loading branch information
Jenkins committed Sep 24, 2024
2 parents 21dc2c9 + 8ba334b commit 8c1a259
Show file tree
Hide file tree
Showing 93 changed files with 1,202 additions and 2,119 deletions.
2 changes: 2 additions & 0 deletions clang/test/Driver/relax.s
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
// RUN: llvm-readobj -r %t | FileCheck --check-prefix=REL %s

// REL: R_X86_64_REX_GOTPCRELX foo
// REL: R_X86_64_REX2_GOTPCRELX foo

movq foo@GOTPCREL(%rip), %rax
movq foo@GOTPCREL(%rip), %r16
8 changes: 4 additions & 4 deletions lld/COFF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ bool Writer::createThunks(OutputSection *os, int margin) {
// Recheck Chunks.size() each iteration, since we can insert more
// elements into it.
for (size_t i = 0; i != os->chunks.size(); ++i) {
SectionChunk *sc = dyn_cast_or_null<SectionChunk>(os->chunks[i]);
SectionChunk *sc = dyn_cast<SectionChunk>(os->chunks[i]);
if (!sc)
continue;
MachineTypes machine = sc->getMachine();
Expand Down Expand Up @@ -606,7 +606,7 @@ void Writer::createECCodeMap() {
// Verify that all relocations are in range, with no extra margin requirements.
bool Writer::verifyRanges(const std::vector<Chunk *> chunks) {
for (Chunk *c : chunks) {
SectionChunk *sc = dyn_cast_or_null<SectionChunk>(c);
SectionChunk *sc = dyn_cast<SectionChunk>(c);
if (!sc)
continue;
MachineTypes machine = sc->getMachine();
Expand Down Expand Up @@ -872,8 +872,8 @@ bool Writer::fixGnuImportChunks() {
if (!pSec->chunks.empty())
hasIdata = true;
llvm::stable_sort(pSec->chunks, [&](Chunk *s, Chunk *t) {
SectionChunk *sc1 = dyn_cast_or_null<SectionChunk>(s);
SectionChunk *sc2 = dyn_cast_or_null<SectionChunk>(t);
SectionChunk *sc1 = dyn_cast<SectionChunk>(s);
SectionChunk *sc2 = dyn_cast<SectionChunk>(t);
if (!sc1 || !sc2) {
// if SC1, order them ascending. If SC2 or both null,
// S is not less than T.
Expand Down
1 change: 1 addition & 0 deletions lldb/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ interesting areas to contribute to lldb.
resources/caveats
resources/projects
resources/lldbdap
resources/addinglanguagesupport
Public C++ API <https://lldb.llvm.org/cpp_reference/namespacelldb.html>
Private C++ API <https://lldb.llvm.org/cpp_reference/index.html>

Expand Down
95 changes: 95 additions & 0 deletions lldb/docs/resources/addinglanguagesupport.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Adding Programming Language Support

LLDB has been architected to make it straightforward to add support for a
programming language. Only a small enum in core LLDB needs to be modified to
make LLDB aware of a new programming language. Everything else can be supplied
in derived classes that need not even be present in the core LLDB repository.
This makes it convenient for developers adding language support in downstream
repositories since it practically eliminates the potential for merge conflicts.

The basic steps are:
* Add the language to the `LanguageType` enum.
* Add a `TypeSystem` for the language.
* Add expression evaluation support.

Additionally, you may want to create a `Language` and `LanguageRuntime` plugin
for your language, which enables support for advanced features like dynamic
typing and data formatting.

## Add the Language to the LanguageType enum

The `LanguageType` enum
(see [lldb-enumerations.h](https://github.com/llvm/llvm-project/blob/main/lldb/include/lldb/lldb-enumerations.h))
contains a list of every language known to LLDB. It is the one place where
support for a language must live that will need to merge cleanly with upstream
LLDB if you are developing your language support in a separate branch. When
adding support for a language previously unknown to LLDB, start by adding an
enumeration entry to `LanguageType`.

## Add a TypeSystem for the Language

Both [Module](https://github.com/llvm/llvm-project/blob/main/lldb/include/lldb/Core/Module.h)
and [Target](https://github.com/llvm/llvm-project/blob/main/lldb/include/lldb/Target/Target.h)
support the retrieval of a `TypeSystem` instance via `GetTypeSystemForLanguage()`.
For `Module`, this method is directly on the `Module` instance. For `Target`,
this is retrieved indirectly via the `TypeSystemMap` for the `Target` instance.

The `TypeSystem` instance returned by the `Target` is expected to be capable of
evaluating expressions, while the `TypeSystem` instance returned by the `Module`
is not. If you want to support expression evaluation for your language, you could
consider one of the following approaches:
* Implement a single `TypeSystem` class that supports evaluation when given an
optional `Target`, implementing all the expression evaluation methods on the
`TypeSystem`.
* Create multiple `TypeSystem` classes, one for evaluation and one for static
`Module` usage.

For clang and Swift, the latter approach was chosen. Primarily to make it
clearer that evaluation with the static `Module`-returned `TypeSystem` instances
make no sense, and have them error out on those calls. But either approach is
fine.

# Creating Types

Your `TypeSystem` will need an approach for creating types based on a set of
`Module`s. If your type info is going to come from DWARF info, you will want to
subclass [DWARFASTParser](https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h).


# Add Expression Evaluation Support

Expression Evaluation support is enabled by implementing the relevant methods on
a `TypeSystem`-derived class. Search for `Expression` in the
[TypeSystem header](https://github.com/llvm/llvm-project/blob/main/lldb/include/lldb/Symbol/TypeSystem.h)
to find the methods to implement.

# Type Completion

There are three levels of type completion, each requiring more type information:
1. Pointer size: When you have a forward decl or a reference, and that's all you
need. At this stage, the pointer size is all you need.
2. Layout info: You need the size of an instance of the type, but you still don't
need to know all the guts of the type.
3. Full type info: Here you need everything, because you're playing with
internals of it, such as modifying a member variable.

Ensure you never complete more of a type than is needed for a given situation.
This will keep your type system from doing more work than necessary.

# Language and LanguageRuntime Plugins

If you followed the steps outlined above, you already have taught LLDB a great
deal about your language. If your language's runtime model and fundamental data
types don't differ much from the C model, you are pretty much done.

However it is likely that your language offers its own data types for things
like strings and arrays, and probably has a notion of dynamic types, where the
effective type of a variable can only be known at runtime.

These tasks are covered by two plugins:
* a `LanguageRuntime` plugin, which provides LLDB with a dynamic view of your
language; this plugin answers questions that require a live process to acquire
information (for example dynamic type resolution).
* a `Language` plugin, which provides LLDB with a static view of your language;
questions that are statically knowable and do not require a process are
answered by this plugin (for example data formatters).
40 changes: 35 additions & 5 deletions lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ void ABIAArch64::AugmentRegisterInfo(

std::array<std::optional<uint32_t>, 32> x_regs;
std::array<std::optional<uint32_t>, 32> v_regs;
std::array<std::optional<uint32_t>, 32> z_regs;
std::optional<uint32_t> z_byte_size;

for (auto it : llvm::enumerate(regs)) {
lldb_private::DynamicRegisterInfo::Register &info = it.value();
Expand All @@ -157,16 +159,44 @@ void ABIAArch64::AugmentRegisterInfo(
x_regs[reg_num] = it.index();
else if (get_reg("v"))
v_regs[reg_num] = it.index();
else if (get_reg("z")) {
z_regs[reg_num] = it.index();
if (!z_byte_size)
z_byte_size = info.byte_size;
}
// if we have at least one subregister, abort
else if (get_reg("w") || get_reg("s") || get_reg("d"))
return;
}

// Create aliases for partial registers: wN for xN, and sN/dN for vN.
// Create aliases for partial registers.

// Wn for Xn.
addPartialRegisters(regs, x_regs, 8, "w{0}", 4, lldb::eEncodingUint,
lldb::eFormatHex);
addPartialRegisters(regs, v_regs, 16, "s{0}", 4, lldb::eEncodingIEEE754,
lldb::eFormatFloat);
addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754,
lldb::eFormatFloat);

auto bool_predicate = [](const auto &reg_num) { return bool(reg_num); };
bool saw_v_regs = std::any_of(v_regs.begin(), v_regs.end(), bool_predicate);
bool saw_z_regs = std::any_of(z_regs.begin(), z_regs.end(), bool_predicate);

// Sn/Dn for Vn.
if (saw_v_regs) {
addPartialRegisters(regs, v_regs, 16, "s{0}", 4, lldb::eEncodingIEEE754,
lldb::eFormatFloat);
addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754,
lldb::eFormatFloat);
} else if (saw_z_regs && z_byte_size) {
// When SVE is enabled, some debug stubs will not describe the Neon V
// registers because they can be read from the bottom 128 bits of the SVE
// registers.

// The size used here is the one sent by the debug server. This only needs
// to be correct right now. Later we will rely on the value of vg instead.
addPartialRegisters(regs, z_regs, *z_byte_size, "v{0}", 16,
lldb::eEncodingVector, lldb::eFormatVectorOfUInt8);
addPartialRegisters(regs, z_regs, *z_byte_size, "s{0}", 4,
lldb::eEncodingIEEE754, lldb::eFormatFloat);
addPartialRegisters(regs, z_regs, *z_byte_size, "d{0}", 8,
lldb::eEncodingIEEE754, lldb::eFormatFloat);
}
}
9 changes: 7 additions & 2 deletions lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4716,9 +4716,14 @@ bool ParseRegisters(
reg_info.encoding = eEncodingIEEE754;
} else if (gdb_type == "aarch64v" ||
llvm::StringRef(gdb_type).starts_with("vec") ||
gdb_type == "i387_ext" || gdb_type == "uint128") {
gdb_type == "i387_ext" || gdb_type == "uint128" ||
reg_info.byte_size > 16) {
// lldb doesn't handle 128-bit uints correctly (for ymm*h), so
// treat them as vector (similarly to xmm/ymm)
// treat them as vector (similarly to xmm/ymm).
// We can fall back to handling anything else <= 128 bit as an
// unsigned integer, more than that, call it a vector of bytes.
// This can happen if we don't recognise the type for AArc64 SVE
// registers.
reg_info.format = eFormatVectorOfUInt8;
reg_info.encoding = eEncodingVector;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
""" Check that when a debug server provides XML that only defines SVE Z registers,
and does not include Neon V registers, lldb creates sub-registers to represent
the V registers as the bottom 128 bits of the Z registers.
qemu-aarch64 is one such debug server.
This also doubles as a test that lldb has a fallback path for registers of
unknown type that are > 128 bits, as the SVE registers are here.
"""

from textwrap import dedent
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
from lldbsuite.test.gdbclientutils import *
from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase


class Responder(MockGDBServerResponder):
def __init__(self):
super().__init__()
self.vg = 4
self.pc = 0xA0A0A0A0A0A0A0A0

def qXferRead(self, obj, annex, offset, length):
if annex == "target.xml":
# Note that QEMU sends the current SVE size in XML and the debugger
# then reads vg to know the latest size.
return (
dedent(
"""\
<?xml version="1.0"?>
<target version="1.0">
<architecture>aarch64</architecture>
<feature name="org.gnu.gdb.aarch64.core">
<reg name="pc" regnum="0" bitsize="64"/>
<reg name="vg" regnum="1" bitsize="64"/>
<reg name="z0" regnum="2" bitsize="2048" type="not_a_type"/>
</feature>
</target>"""
),
False,
)

return (None,)

def readRegister(self, regnum):
return "E01"

def readRegisters(self):
return "".join(
[
# 64 bit PC.
f"{self.pc:x}",
# 64 bit vg
f"0{self.vg}00000000000000",
# Enough data for 256 and 512 bit SVE.
"".join([f"{n:02x}" * 4 for n in range(1, 17)]),
]
)

def cont(self):
# vg is expedited so that lldb can resize the SVE registers.
return f"T02thread:1ff0d;threads:1ff0d;thread-pcs:{self.pc};01:0{self.vg}00000000000000;"

def writeRegisters(self, registers_hex):
# We get a block of data containing values in regnum order.
self.vg = int(registers_hex[16:18])
return "OK"


class TestXMLRegisterFlags(GDBRemoteTestBase):
def check_regs(self, vg):
# Each 32 bit chunk repeats n.
z0_value = " ".join(
[" ".join([f"0x{n:02x}"] * 4) for n in range(1, (vg * 2) + 1)]
)

self.expect(
"register read vg z0 v0 s0 d0",
substrs=[
f" vg = 0x000000000000000{vg}\n"
" z0 = {" + z0_value + "}\n"
" v0 = {0x01 0x01 0x01 0x01 0x02 0x02 0x02 0x02 0x03 0x03 0x03 0x03 0x04 0x04 0x04 0x04}\n"
" s0 = 2.36942783E-38\n"
" d0 = 5.3779407333977203E-299\n"
],
)

self.expect("register read s0 --format uint32", substrs=["s0 = {0x01010101}"])
self.expect(
"register read d0 --format uint64",
substrs=["d0 = {0x0202020201010101}"],
)

@skipIfXmlSupportMissing
@skipIfRemote
@skipIfLLVMTargetMissing("AArch64")
def test_v_sub_registers(self):
self.server.responder = Responder()
target = self.dbg.CreateTarget("")

if self.TraceOn():
self.runCmd("log enable gdb-remote packets")
self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote packets"))

process = self.connect(target)
lldbutil.expect_state_changes(
self, self.dbg.GetListener(), process, [lldb.eStateStopped]
)

self.check_regs(4)

# Now increase the SVE length and continue. The mock will respond with a new
# vg and lldb will reconfigure the register defs. This should not break the
# sub-registers.

self.runCmd("register write vg 8")
self.expect("continue", substrs=["stop reason = signal SIGINT"])

self.check_regs(8)
4 changes: 1 addition & 3 deletions llvm/docs/AMDGPUUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -612,9 +612,7 @@ Generic processor code objects are versioned. See :ref:`amdgpu-generic-processor
- ``gfx1152``

SALU floating point instructions
and single-use VGPR hint
instructions are not available
on:
are not available on:

- ``gfx1150``
- ``gfx1151``
Expand Down
12 changes: 10 additions & 2 deletions llvm/docs/CMake.rst
Original file line number Diff line number Diff line change
Expand Up @@ -571,10 +571,12 @@ enabled sub-projects. Nearly all of these variable names begin with
Semicolon-separated list of projects to build, or *all* for building all
(clang, lldb, lld, polly, etc) projects. This flag assumes that projects
are checked out side-by-side and not nested, i.e. clang needs to be in
parallel of llvm instead of nested in `llvm/tools`. This feature allows
parallel of llvm instead of nested in ``llvm/tools``. This feature allows
to have one build for only LLVM and another for clang+llvm using the same
source checkout.

The full list is:

``clang;clang-tools-extra;cross-project-tests;libc;libclc;lld;lldb;openmp;polly;pstl``

**LLVM_ENABLE_RTTI**:BOOL
Expand All @@ -586,10 +588,16 @@ enabled sub-projects. Nearly all of these variable names begin with
It will build the builtins separately from the other runtimes to preserve
correct dependency ordering. If you want to build the runtimes using a system
compiler, see the `libc++ documentation <https://libcxx.llvm.org/BuildingLibcxx.html>`_.
Note: the list should not have duplicates with `LLVM_ENABLE_PROJECTS`.

.. note::
The list should not have duplicates with ``LLVM_ENABLE_PROJECTS``.

The full list is:

``compiler-rt;libc;libcxx;libcxxabi;libunwind;openmp``

To enable all of them, use:

``LLVM_ENABLE_RUNTIMES=all``

**LLVM_ENABLE_SPHINX**:BOOL
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ ELF_RELOC(R_X86_64_TLSDESC, 36)
ELF_RELOC(R_X86_64_IRELATIVE, 37)
ELF_RELOC(R_X86_64_GOTPCRELX, 41)
ELF_RELOC(R_X86_64_REX_GOTPCRELX, 42)
ELF_RELOC(R_X86_64_REX2_GOTPCRELX, 43)
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/ISDOpcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ enum NodeType {
/// be saturated against signed values, resulting in `S`, which will combine
/// to `TRUNCATE_SSAT_S`. If the value of C ranges from `0 to 255`, it will
/// be saturated against unsigned values, resulting in `U`, which will
/// combine to `TRUNATE_SSAT_U`. Similarly, in `truncate(umin(x, C))`, if
/// combine to `TRUNCATE_SSAT_U`. Similarly, in `truncate(umin(x, C))`, if
/// value of C ranges from `0 to 255`, it becomes `U` because it is saturated
/// for unsigned values. As a result, it combines to `TRUNCATE_USAT_U`.
TRUNCATE_SSAT_S, // saturate signed input to signed result -
Expand Down
Loading

0 comments on commit 8c1a259

Please sign in to comment.