diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index a97e93470987c..0cc4db1e637ce 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -412,6 +412,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__aarch64__"); } + if (getTriple().isLFI()) + Builder.defineMacro("__LFI__"); + // Inline assembly supports AArch64 flag outputs. Builder.defineMacro("__GCC_ASM_FLAG_OUTPUTS__"); diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 8052659e9836b..522cb3ab92723 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -63,6 +63,7 @@ add_clang_library(clangDriver ToolChains/Hexagon.cpp ToolChains/HLSL.cpp ToolChains/Hurd.cpp + ToolChains/LFILinux.cpp ToolChains/Linux.cpp ToolChains/Managarm.cpp ToolChains/MipsLinux.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 9fd64d4aac514..b08ba837eec68 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -29,6 +29,7 @@ #include "ToolChains/Haiku.h" #include "ToolChains/Hexagon.h" #include "ToolChains/Hurd.h" +#include "ToolChains/LFILinux.h" #include "ToolChains/Lanai.h" #include "ToolChains/Linux.h" #include "ToolChains/MSP430.h" @@ -6864,6 +6865,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, TC = std::make_unique(*this, Target, Args); else if (Target.isWALI()) TC = std::make_unique(*this, Target, Args); + else if (Target.isLFI()) + TC = std::make_unique(*this, Target, + Args); else TC = std::make_unique(*this, Target, Args); break; diff --git a/clang/lib/Driver/ToolChains/LFILinux.cpp b/clang/lib/Driver/ToolChains/LFILinux.cpp new file mode 100644 index 0000000000000..f982504b96491 --- /dev/null +++ b/clang/lib/Driver/ToolChains/LFILinux.cpp @@ -0,0 +1,24 @@ +//===-- LFILinux.cpp - LFI ToolChain Implementations ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "LFILinux.h" +#include "clang/Driver/Driver.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace llvm::opt; + +ToolChain::CXXStdlibType LFILinuxToolChain::GetDefaultCXXStdlibType() const { + return ToolChain::CST_Libstdcxx; +} + +void LFILinuxToolChain::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + ToolChain::AddCXXStdlibLibArgs(Args, CmdArgs); + CmdArgs.push_back("-lc++abi"); +} diff --git a/clang/lib/Driver/ToolChains/LFILinux.h b/clang/lib/Driver/ToolChains/LFILinux.h new file mode 100644 index 0000000000000..30b6fb527eb0f --- /dev/null +++ b/clang/lib/Driver/ToolChains/LFILinux.h @@ -0,0 +1,37 @@ +//===--- LFILinux.h - LFI ToolChain Implementations -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LFI_LINUX_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LFI_LINUX_H + +#include "Linux.h" + +namespace clang { +namespace driver { +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY LFILinuxToolChain : public Linux { +public: + LFILinuxToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) + : Linux(D, Triple, Args) { + ExtraOpts.push_back("-z"); + ExtraOpts.push_back("separate-code"); + } + + CXXStdlibType GetDefaultCXXStdlibType() const override; + + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; +}; + +} // end namespace toolchains +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LFI_LINUX_H diff --git a/compiler-rt/cmake/builtin-config-ix.cmake b/compiler-rt/cmake/builtin-config-ix.cmake index eaff8135cff45..3298fe96cd236 100644 --- a/compiler-rt/cmake/builtin-config-ix.cmake +++ b/compiler-rt/cmake/builtin-config-ix.cmake @@ -78,7 +78,7 @@ else() endif() set(AMDGPU amdgcn) -set(ARM64 aarch64 arm64ec) +set(ARM64 aarch64 arm64ec aarch64_lfi) set(ARM32 arm armhf armv4t armv5te armv6 armv6m armv7m armv7em armv7 armv7s armv7k armv8m.base armv8m.main armv8.1m.main) set(AVR avr) set(HEXAGON hexagon) diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 6c226aa7d2d48..29c5a08b828cb 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -692,6 +692,7 @@ set(arm64_SOURCES ${aarch64_SOURCES}) set(arm64e_SOURCES ${aarch64_SOURCES}) set(arm64_32_SOURCES ${aarch64_SOURCES}) set(arm64ec_SOURCES ${aarch64_SOURCES}) +set(aarch64_lfi_SOURCES ${aarch64_SOURCES}) # macho_embedded archs set(armv6m_SOURCES ${thumb1_SOURCES}) diff --git a/llvm/docs/CodeGenerator.rst b/llvm/docs/CodeGenerator.rst index a74f16d7e9477..dbd55767dcdfd 100644 --- a/llvm/docs/CodeGenerator.rst +++ b/llvm/docs/CodeGenerator.rst @@ -2492,3 +2492,10 @@ The AMDGPU backend The AMDGPU code generator lives in the ``lib/Target/AMDGPU`` directory. This code generator is capable of targeting a variety of AMD GPU processors. Refer to :doc:`AMDGPUUsage` for more information. + +The Lightweight Fault Isolation (LFI) backend +--------------------------------------------- + +LFI is a backend that allows programs compiled for the target to run in a +sandboxed environment that is within the same address space as host code. Refer +to :doc:`LFI` for more information about the LFI backend. diff --git a/llvm/docs/LFI.rst b/llvm/docs/LFI.rst new file mode 100644 index 0000000000000..55947c70eea66 --- /dev/null +++ b/llvm/docs/LFI.rst @@ -0,0 +1,414 @@ +========================================= +Lightweight Fault Isolation (LFI) in LLVM +========================================= + +.. contents:: + :local: + +Introduction +++++++++++++ + +Lightweight Fault Isolation (LFI) is a compiler-based sandboxing technology for +native code. Like WebAssembly and Native Client, LFI isolates sandboxed code in-process +(i.e., in the same address space as a host application). + +LFI is designed from the ground up to sandbox existing code, such as C/C++ +libraries (including assembly code) and device drivers. + +LFI aims for the following goals: + +* Compatibility: LFI can be used to sandbox nearly all existing C/C++/assembly + libraries unmodified (they just need to be recompiled). Sandboxed libraries + work with existing system call interfaces, and are compatible with existing + development tools such as profilers, debuggers, and sanitizers. +* Performance: LFI aims for minimal overhead vs. unsandboxed code. +* Security: The LFI runtime and compiler elements aim to be simple and + verifiable when possible. +* Usability: LFI aims to make it easy as possible to used retrofit sandboxing, + i.e., to migrate from unsandboxed to sandboxed libraries with minimal effort. + +When building a program for the LFI target the compiler is designed to ensure +that the program will only be able to access memory within a limited region of +the virtual address space, starting from where the program is loaded (the +current design sets this region to a size of 4GiB of virtual memory). Programs +built for the LFI target are restricted to using a subset of the instruction +set, designed so that the programs can be soundly confined to their sandbox +region. LFI programs must run inside of an "emulator" (usually called the LFI +runtime), responsible for initializing the sandbox region, loading the program, +and servicing system call requests, or other forms of runtime calls. + +LFI uses an architecture-specific sandboxing scheme based on the general +technique of Software-Based Fault Isolation (SFI). Initial support for LFI in +LLVM is focused on the AArch64 platform, with x86-64 support planned for the +future. The initial version of LFI for AArch64 is designed to support the +Armv8.1 AArch64 architecture. + +See `https://github.com/lfi-project `__ for +details about the LFI project and additional software needed to run LFI +programs. + +Compiler Requirements ++++++++++++++++++++++ + +When building for the ``aarch64_lfi`` target, the compiler must restrict use of +the instruction set to a subset of instructions, which are known to be safe +from a sandboxing perspective. To do this, we apply a set of simple rewrites at +the assembly language level to transform standard native AArch64 assembly into +LFI-compatible AArch64 assembly. + +These rewrites (also called "expansions") are applied at the very end of the +LLVM compilation pipeline (during the assembler step). This allows the rewrites +to be applied to hand-written assembly, including inline assembly. + +Compiler Options +================ + +The LFI target has several configuration options. + +* ``+lfi-loads``: enable sandboxing for loads (default: true). +* ``+lfi-stores``: enable sandboxing for stores (default: true). + +Use ``+nolfi-loads`` to create a "stores-only" sandbox that may read, but not +write, outside the sandbox region. + +Use ``+nolfi-loads+nolfi-stores`` to create a "jumps-only" sandbox that may +read/write outside the sandbox region but may not transfer control outside +(e.g., may not execute system calls directly). This is primarily useful in +combination with some other form of memory sandboxing, such as Intel MPK. + +Reserved Registers +================== + +The LFI target uses a custom ABI that reserves additional registers for the +platform. The registers are listed below, along with the security invariant +that must be maintained. + +* ``x27``: always holds the sandbox base address. +* ``x28``: always holds an address within the sandbox. +* ``sp``: always holds an address within the sandbox. +* ``x30``: always holds an address within the sandbox. +* ``x26``: scratch register. +* ``x25``: points to a thread-local virtual register file for storing runtime context information. + +Linker Support +============== + +In the initial version, LFI only supports static linking, and only supports +creating ``static-pie`` binaries. There is nothing that fundamentally precludes +support for dynamic linking on the LFI target, but such support would require +that the code generated by the linker for PLT entries be slightly modified in +order to conform to the LFI architecture subset. + +Assembly Rewrites +================= + +Terminology +~~~~~~~~~~~ + +In the following assembly rewrites, some shorthand is used. + +* ``xN`` or ``wN``: refers to any general-purpose non-reserved register. +* ``{a,b,c}``: matches any of ``a``, ``b``, or ``c``. +* ``LDSTr``: a load/store instruction that supports register-register addressing modes, with one source/destination register. +* ``LDSTx``: a load/store instruction not matched by ``LDSTr``. + +Control flow +~~~~~~~~~~~~ + +Indirect branches get rewritten to branch through register ``x28``, which must +always contain an address within the sandbox. An ``add`` is used to safely load +``x28`` with the destination address. Since ``ret`` uses ``x30`` by default, +which already must contain an address within the sandbox, it does not require +any rewrite. + ++--------------------+---------------------------+ +| Original | Rewritten | ++--------------------+---------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| {br,blr,ret} xN | add x28, x27, wN, uxtw | +| | {br,blr,ret} x28 | +| | | ++--------------------+---------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| ret | ret | +| | | ++--------------------+---------------------------+ + +Memory accesses +~~~~~~~~~~~~~~~ + +Memory accesses are rewritten to use the ``[x27, wM, uxtw]`` addressing mode if +it is available, which is automatically safe. Otherwise, rewrites fall back to +using ``x28`` along with an instruction to safely load it with the target +address. + ++---------------------------------+-------------------------------+ +| Original | Rewritten | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTr xN, [xM] | LDSTr xN, [x27, wM, uxtw] | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTr xN, [xM, #I] | add x28, x27, wM, uxtw | +| | LDSTr xN, [x28, #I] | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTr xN, [xM, #I]! | add xM, xM, #I | +| | LDSTr xN, [x27, wM, uxtw] | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTr xN, [xM], #I | LDSTr xN, [x27, wM, uxtw] | +| | add xM, xM, #I | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTr xN, [xM1, xM2] | add x26, xM1, xM2 | +| | LDSTr xN, [x27, w26, uxtw] | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTr xN, [xM1, xM2, MOD #I] | add x26, xM1, xM2, MOD #I | +| | LDSTr xN, [x27, w26, uxtw] | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTx ..., [xM] | add x28, x27, wM, uxtw | +| | LDSTx ..., [x28] | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTx ..., [xM, #I] | add x28, x27, wM, uxtw | +| | LDSTx ..., [x28, #I] | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTx ..., [xM, #I]! | add x28, x27, wM, uxtw | +| | LDSTx ..., [x28, #I] | +| | add xM, xM, #I | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTx ..., [xM], #I | add x28, x27, wM, uxtw | +| | LDSTx ..., [x28] | +| | add xM, xM, #I | +| | | ++---------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| LDSTx ..., [xM1], xM2 | add x28, x27, wM1, uxtw | +| | LDSTx ..., [x28] | +| | add xM1, xM1, xM2 | +| | | ++---------------------------------+-------------------------------+ + +Stack pointer modification +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When the stack pointer is modified, we write the modified value to a temporary, +before loading it back into ``sp`` with a safe ``add``. + ++------------------------------+-------------------------------+ +| Original | Rewritten | ++------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| mov sp, xN | add sp, x27, wN, uxtw | +| | | ++------------------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| {add,sub} sp, sp, {#I,xN} | {add,sub} x26, sp, {#I,xN} | +| | add sp, x27, w26, uxtw | +| | | ++------------------------------+-------------------------------+ + +Link register modification +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When the link register is modified, we write the modified value to a +temporary, before loading it back into ``x30`` with a safe ``add``. + ++-----------------------+----------------------------+ +| Original | Rewritten | ++-----------------------+----------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| ldr x30, [...] | ldr x26, [...] | +| | add x30, x27, w26, uxtw | +| | | ++-----------------------+----------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| ldp xN, x30, [...] | ldp xN, x26, [...] | +| | add x30, x27, w26, uxtw | +| | | ++-----------------------+----------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| ldp x30, xN, [...] | ldp x26, xN, [...] | +| | add x30, x27, w26, uxtw | +| | | ++-----------------------+----------------------------+ + +System instructions +~~~~~~~~~~~~~~~~~~~ + +System calls are rewritten into a sequence that loads the address of the first +runtime call entrypoint and jumps to it. The runtime call entrypoint table is +stored at the start of the sandbox, so it can be referenced by ``x27``. The +rewrite also saves and restores the link register, since it is used for +branching into the runtime. + ++-----------------+----------------------------+ +| Original | Rewritten | ++-----------------+----------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| svc #0 | mov w26, w30 | +| | ldr x30, [x27] | +| | blr x30 | +| | add x30, x27, w26, uxtw | +| | | ++-----------------+----------------------------+ + +Thread-local storage +~~~~~~~~~~~~~~~~~~~~ + +TLS accesses are rewritten into accesses offset from ``x25``, which is a +reserved register that points to a virtual register file, with a location for +storing the sandbox's thread pointer. ``TP`` is the offset into that virtual +register file where the thread pointer is stored. + ++----------------------+-----------------------+ +| Original | Rewritten | ++----------------------+-----------------------+ +| .. code-block:: | .. code-block:: | +| | | +| mrs xN, tpidr_el0 | ldr xN, [x25, #TP] | +| | | ++----------------------+-----------------------+ +| .. code-block:: | .. code-block:: | +| | | +| mrs tpidr_el0, xN | str xN, [x25, #TP] | +| | | ++----------------------+-----------------------+ + +Optimizations +============= + +Basic guard elimination +~~~~~~~~~~~~~~~~~~~~~~~ + +If a register is guarded multiple times in the same basic block without any +modifications to it during the intervening instructions, then subsequent guards +can be removed. + ++---------------------------+---------------------------+ +| Original | Rewritten | ++---------------------------+---------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| add x28, x27, wN, uxtw | add x28, x27, wN, uxtw | +| ldur xN, [x28] | ldur xN, [x28] | +| add x28, x27, wN, uxtw | ldur xN, [x28, #8] | +| ldur xN, [x28, #8] | ldur xN, [x28, #16] | +| add x28, x27, wN, uxtw | | +| ldur xN, [x28, #16] | | +| | | ++---------------------------+---------------------------+ + +Address generation +~~~~~~~~~~~~~~~~~~ + +Addresses to global symbols in position-independent executables are frequently +generated via ``adrp`` followed by ``ldr``. Since the address generated by +``adrp`` can be statically guaranteed to be within the sandbox, it is safe to +directly target ``x28`` for these sequences. This allows the omission of a +guard instruction before the ``ldr``. + ++----------------------+-----------------------+ +| Original | Rewritten | ++----------------------+-----------------------+ +| .. code-block:: | .. code-block:: | +| | | +| adrp xN, target | adrp x28, target | +| ldr xN, [xN, imm] | ldr xN, [x28, imm] | +| | | ++----------------------+-----------------------+ + +Stack guard elimination +~~~~~~~~~~~~~~~~~~~~~~~ + +**Note**: this optimization has not been implemented. + +If the stack pointer is modified by adding/subtracting a small immediate, and +then later used to perform a memory access without any intervening jumps, then +the guard on the stack pointer modification can be removed. This is because the +load/store is guaranteed to trap if the stack pointer has been moved outside of +the sandbox region. + ++---------------------------+---------------------------+ +| Original | Rewritten | ++---------------------------+---------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| add x26, sp, #8 | add sp, sp, #8 | +| add sp, x27, w26, uxtw | ... (same basic block) | +| ... (same basic block) | ldr xN, [sp] | +| ldr xN, [sp] | | +| | | ++---------------------------+---------------------------+ + +Guard hoisting +~~~~~~~~~~~~~~ + +**Note**: this optimization has not been implemented. + +In certain cases, guards may be hoisted outside of loops. + ++-----------------------+-------------------------------+ +| Original | Rewritten | ++-----------------------+-------------------------------+ +| .. code-block:: | .. code-block:: | +| | | +| mov w8, #10 | mov w8, #10 | +| mov w9, #0 | mov w9, #0 | +| .loop: | add x28, x27, wM, uxtw | +| add w9, w9, #1 | .loop: | +| ldr xN, [xM] | add w9, w9, #1 | +| cmp w9, w8 | ldr xN, [x28] | +| b.lt .loop | cmp w9, w8 | +| .end: | b.lt .loop | +| | .end: | +| | | ++-----------------------+-------------------------------+ + +References +++++++++++ + +For more information, please see the following resources: + +* `LFI project page `__ +* `LFI RFC `__ +* `LFI paper `__ + +Contact info: + +* Zachary Yedidia - zyedidia@cs.stanford.edu +* Tal Garfinkel - tgarfinkel@google.com +* Sharjeel Khan - sharjeelkhan@google.com diff --git a/llvm/docs/UserGuides.rst b/llvm/docs/UserGuides.rst index 0551c8b60a62d..d3ca2f69016c1 100644 --- a/llvm/docs/UserGuides.rst +++ b/llvm/docs/UserGuides.rst @@ -49,6 +49,7 @@ intermediate LLVM representation. InstrProfileFormat InstrRefDebugInfo KeyInstructionsDebugInfo + LFI LinkTimeOptimization LoopTerminology MarkdownQuickstartTemplate @@ -309,3 +310,6 @@ Additional Topics :doc:`Telemetry` This document describes the Telemetry framework in LLVM. + +:doc:`LFI ` + This document describes the Lightweight Fault Isolation (LFI) target in LLVM. diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 11b76cd183108..02ac0de7e8734 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -153,6 +153,7 @@ class Triple { AArch64SubArch_arm64e, AArch64SubArch_arm64ec, + AArch64SubArch_lfi, KalimbaSubArch_v3, KalimbaSubArch_v4, @@ -938,6 +939,12 @@ class Triple { return getArch() == Triple::arm || getArch() == Triple::armeb; } + /// Tests whether the target is LFI. + bool isLFI() const { + return getArch() == Triple::aarch64 && + getSubArch() == Triple::AArch64SubArch_lfi; + } + /// Tests whether the target supports the EHABI exception /// handling standard. bool isTargetEHABICompatible() const { diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index f3cf222038072..93e4bfa202990 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -461,6 +461,17 @@ AArch64RegisterInfo::getStrictlyReservedRegs(const MachineFunction &MF) const { markSuperRegs(Reserved, i); } + if (MF.getSubtarget().isLFI()) { + markSuperRegs(Reserved, AArch64::W28); + markSuperRegs(Reserved, AArch64::W27); + markSuperRegs(Reserved, AArch64::W26); + markSuperRegs(Reserved, AArch64::W25); + if (!MF.getProperties().hasNoVRegs()) { + markSuperRegs(Reserved, AArch64::LR); + markSuperRegs(Reserved, AArch64::W30); + } + } + for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) { if (MF.getSubtarget().isXRegisterReserved(i)) markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i)); diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index ab4004e30f629..54dc556652ff3 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -293,6 +293,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo { bool isTargetAndroid() const { return TargetTriple.isAndroid(); } bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); } bool isWindowsArm64EC() const { return TargetTriple.isWindowsArm64EC(); } + bool isLFI() const { return TargetTriple.isLFI(); } bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); } bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 11ba9ee32f66a..2577b15b19992 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -116,6 +116,8 @@ StringRef Triple::getArchName(ArchType Kind, SubArchType SubArch) { return "arm64ec"; if (SubArch == AArch64SubArch_arm64e) return "arm64e"; + if (SubArch == AArch64SubArch_lfi) + return "aarch64_lfi"; break; case Triple::spirv: switch (SubArch) { @@ -594,6 +596,7 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("aarch64", Triple::aarch64) .Case("aarch64_be", Triple::aarch64_be) .Case("aarch64_32", Triple::aarch64_32) + .Case("aarch64_lfi", Triple::aarch64) .Case("arc", Triple::arc) .Case("arm64", Triple::aarch64) .Case("arm64_32", Triple::aarch64_32) @@ -832,6 +835,9 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { if (SubArchName == "arm64ec") return Triple::AArch64SubArch_arm64ec; + if (SubArchName == "aarch64_lfi") + return Triple::AArch64SubArch_lfi; + if (SubArchName.starts_with("spirv")) return StringSwitch(SubArchName) .EndsWith("v1.0", Triple::SPIRVSubArch_v10)