clang 24.0.0git
CIRABIClassifierX86_64.cpp
Go to the documentation of this file.
1//===- CIRABIClassifierX86_64.cpp - x86_64 System V classification --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the x86_64 System V classifier, which classifies with
10// the LLVM ABI Lowering Library's SysV x86_64 target.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CIRABIClassifier.h"
15
18#include "llvm/ADT/StringExtras.h"
19
20#include <algorithm>
21#include <array>
22
23using namespace mlir;
24using namespace mlir::abi;
25using namespace cir;
26
27/// The AVX level to classify \p func at: \p base, raised if the function's own
28/// recorded feature list enables a wider vector.
29static llvm::abi::X86AVXABILevel funcAvxLevel(cir::FuncOp func,
30 llvm::abi::X86AVXABILevel base) {
31 // Only a `target` attribute may raise the level. A multiversioned function
32 // carries a raised feature list too, and must stay at the module's level.
34
35 auto features = func->getAttrOfType<mlir::StringAttr>("cir.target-features");
36 if (!features)
37 return base;
38 // A '-' entry disables the feature, so match a whole '+' entry rather than
39 // searching for the name. avx512f implies avx, so both entries are present:
40 // return on the wider name so one pass suffices.
41 bool avx = false;
42 for (llvm::StringRef feature : llvm::split(features.getValue(), ',')) {
43 if (!feature.consume_front("+"))
44 continue;
45 if (feature == "avx512f")
46 return std::max(base, llvm::abi::X86AVXABILevel::AVX512);
47 avx |= feature == "avx";
48 }
49 return avx ? std::max(base, llvm::abi::X86AVXABILevel::AVX) : base;
50}
51
52namespace {
53
54class X86_64ABIClassifier final : public CIRABIClassifierCommon {
55public:
56 X86_64ABIClassifier(const mlir::DataLayout &dl, mlir::ModuleOp modOp,
57 const ABIClassifierOptions &options)
58 : CIRABIClassifierCommon(dl, modOp), baseAvxLevel(options.x86AvxAbiLevel),
59 allowsTargetAttrAvx(options.allowsX86TargetAttrAvx),
60 abiCompat(options.x86AbiCompat) {}
61
62 /// cir.va_arg is expanded into the SysV register-save-area / overflow-area
63 /// sequence, which reads the fetched type's classification as an unnamed
64 /// argument, as classic's X86_64ABIInfo::EmitVAArg does.
65 mlir::FailureOr<ArgClassification>
66 classifyVAArg(cir::VAArgOp vaArg) override {
67 return classifyVarArgType(
68 vaArg.getType(), getTargetInfo(vaArg->getParentOfType<cir::FuncOp>()),
69 [&]() { return vaArg->emitOpError(); });
70 }
71
72protected:
73 /// The AVX level starts at the module's and may be raised by
74 /// \p featureSource's recorded target features.
75 const llvm::abi::TargetInfo &
76 getTargetInfo(cir::FuncOp featureSource) override;
77
78private:
79 /// One library classifier per AVX level, built on first use. A
80 /// per-function target attribute can raise the level above the module's.
81 static constexpr unsigned numAvxLevels =
82 static_cast<unsigned>(llvm::abi::X86AVXABILevel::Last) + 1;
83 std::array<std::unique_ptr<llvm::abi::TargetInfo>, numAvxLevels> targets;
84
85 llvm::abi::X86AVXABILevel baseAvxLevel;
86 bool allowsTargetAttrAvx;
87
88 /// The x86_64 flags whose value depends on the target and the requested ABI
89 /// compatibility version.
90 llvm::abi::X86ABICompatInfo abiCompat;
91};
92
93const llvm::abi::TargetInfo &
94X86_64ABIClassifier::getTargetInfo(cir::FuncOp featureSource) {
95 llvm::abi::X86AVXABILevel level = baseAvxLevel;
96 assert(featureSource && "function required for getTargetInfo");
97 if (allowsTargetAttrAvx)
98 level = funcAvxLevel(featureSource, baseAvxLevel);
99 assert(static_cast<unsigned>(level) < numAvxLevels &&
100 "a new X86AVXABILevel must move X86AVXABILevel::Last");
101 std::unique_ptr<llvm::abi::TargetInfo> &slot =
102 targets[static_cast<unsigned>(level)];
103 if (!slot)
104 slot =
105 llvm::abi::createX86_64TargetInfo(typeMapper.getTypeBuilder(), level,
106 /*Has64BitPointers=*/true, abiCompat);
107 return *slot;
108}
109
110} // namespace
111
112std::unique_ptr<CIRABIClassifier>
113cir::createX86_64ABIClassifier(const mlir::DataLayout &dl, mlir::ModuleOp modOp,
114 const ABIClassifierOptions &options) {
115 return std::make_unique<X86_64ABIClassifier>(dl, modOp, options);
116}
static llvm::abi::X86AVXABILevel funcAvxLevel(cir::FuncOp func, llvm::abi::X86AVXABILevel base)
The AVX level to classify func at: base, raised if the function's own recorded feature list enables a...
Classifies through the LLVM ABI Lowering Library.
static bool allowsX86TargetAttrAvx(const llvm::Triple &triple, clang::LangOptions::ClangABI compat)
Whether __attribute__((target(...))) on a function may raise its AVX ABI level above the command line...
Definition CIRPasses.cpp:45
std::unique_ptr< CIRABIClassifier > createX86_64ABIClassifier(const mlir::DataLayout &dl, mlir::ModuleOp modOp, const ABIClassifierOptions &options)
The x86_64 System V classifier.
The target-specific settings a classifier needs beyond what it can read from the module.
static bool opFuncMultiVersioning()