109467b48Spatrick //===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This class wraps target description classes used by the various code
1009467b48Spatrick // generation TableGen backends. This makes it easier to access the data and
1109467b48Spatrick // provides a single place that needs to check it for validity. All of these
1209467b48Spatrick // classes abort on error conditions.
1309467b48Spatrick //
1409467b48Spatrick //===----------------------------------------------------------------------===//
1509467b48Spatrick
1609467b48Spatrick #include "CodeGenTarget.h"
17*d415bd75Srobert #include "CodeGenInstruction.h"
1809467b48Spatrick #include "CodeGenIntrinsics.h"
1909467b48Spatrick #include "CodeGenSchedule.h"
2009467b48Spatrick #include "llvm/ADT/STLExtras.h"
2109467b48Spatrick #include "llvm/Support/CommandLine.h"
2209467b48Spatrick #include "llvm/TableGen/Error.h"
2309467b48Spatrick #include "llvm/TableGen/Record.h"
2409467b48Spatrick #include <algorithm>
2509467b48Spatrick using namespace llvm;
2609467b48Spatrick
2709467b48Spatrick cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
2809467b48Spatrick cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");
2909467b48Spatrick
3009467b48Spatrick static cl::opt<unsigned>
3109467b48Spatrick AsmParserNum("asmparsernum", cl::init(0),
3209467b48Spatrick cl::desc("Make -gen-asm-parser emit assembly parser #N"),
3309467b48Spatrick cl::cat(AsmParserCat));
3409467b48Spatrick
3509467b48Spatrick static cl::opt<unsigned>
3609467b48Spatrick AsmWriterNum("asmwriternum", cl::init(0),
3709467b48Spatrick cl::desc("Make -gen-asm-writer emit assembly writer #N"),
3809467b48Spatrick cl::cat(AsmWriterCat));
3909467b48Spatrick
4009467b48Spatrick /// getValueType - Return the MVT::SimpleValueType that the specified TableGen
4109467b48Spatrick /// record corresponds to.
getValueType(Record * Rec)4209467b48Spatrick MVT::SimpleValueType llvm::getValueType(Record *Rec) {
4309467b48Spatrick return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
4409467b48Spatrick }
4509467b48Spatrick
getName(MVT::SimpleValueType T)4609467b48Spatrick StringRef llvm::getName(MVT::SimpleValueType T) {
4709467b48Spatrick switch (T) {
4809467b48Spatrick case MVT::Other: return "UNKNOWN";
4909467b48Spatrick case MVT::iPTR: return "TLI.getPointerTy()";
5009467b48Spatrick case MVT::iPTRAny: return "TLI.getPointerTy()";
5109467b48Spatrick default: return getEnumName(T);
5209467b48Spatrick }
5309467b48Spatrick }
5409467b48Spatrick
getEnumName(MVT::SimpleValueType T)5509467b48Spatrick StringRef llvm::getEnumName(MVT::SimpleValueType T) {
56*d415bd75Srobert // clang-format off
5709467b48Spatrick switch (T) {
5809467b48Spatrick case MVT::Other: return "MVT::Other";
5909467b48Spatrick case MVT::i1: return "MVT::i1";
60*d415bd75Srobert case MVT::i2: return "MVT::i2";
61*d415bd75Srobert case MVT::i4: return "MVT::i4";
6209467b48Spatrick case MVT::i8: return "MVT::i8";
6309467b48Spatrick case MVT::i16: return "MVT::i16";
6409467b48Spatrick case MVT::i32: return "MVT::i32";
6509467b48Spatrick case MVT::i64: return "MVT::i64";
6609467b48Spatrick case MVT::i128: return "MVT::i128";
6709467b48Spatrick case MVT::Any: return "MVT::Any";
6809467b48Spatrick case MVT::iAny: return "MVT::iAny";
6909467b48Spatrick case MVT::fAny: return "MVT::fAny";
7009467b48Spatrick case MVT::vAny: return "MVT::vAny";
7109467b48Spatrick case MVT::f16: return "MVT::f16";
72097a140dSpatrick case MVT::bf16: return "MVT::bf16";
7309467b48Spatrick case MVT::f32: return "MVT::f32";
7409467b48Spatrick case MVT::f64: return "MVT::f64";
7509467b48Spatrick case MVT::f80: return "MVT::f80";
7609467b48Spatrick case MVT::f128: return "MVT::f128";
7709467b48Spatrick case MVT::ppcf128: return "MVT::ppcf128";
7809467b48Spatrick case MVT::x86mmx: return "MVT::x86mmx";
7973471bf0Spatrick case MVT::x86amx: return "MVT::x86amx";
8073471bf0Spatrick case MVT::i64x8: return "MVT::i64x8";
8109467b48Spatrick case MVT::Glue: return "MVT::Glue";
8209467b48Spatrick case MVT::isVoid: return "MVT::isVoid";
8309467b48Spatrick case MVT::v1i1: return "MVT::v1i1";
8409467b48Spatrick case MVT::v2i1: return "MVT::v2i1";
8509467b48Spatrick case MVT::v4i1: return "MVT::v4i1";
8609467b48Spatrick case MVT::v8i1: return "MVT::v8i1";
8709467b48Spatrick case MVT::v16i1: return "MVT::v16i1";
8809467b48Spatrick case MVT::v32i1: return "MVT::v32i1";
8909467b48Spatrick case MVT::v64i1: return "MVT::v64i1";
9009467b48Spatrick case MVT::v128i1: return "MVT::v128i1";
9173471bf0Spatrick case MVT::v256i1: return "MVT::v256i1";
9209467b48Spatrick case MVT::v512i1: return "MVT::v512i1";
9309467b48Spatrick case MVT::v1024i1: return "MVT::v1024i1";
94*d415bd75Srobert case MVT::v2048i1: return "MVT::v2048i1";
95*d415bd75Srobert case MVT::v128i2: return "MVT::v128i2";
96*d415bd75Srobert case MVT::v256i2: return "MVT::v256i2";
97*d415bd75Srobert case MVT::v64i4: return "MVT::v64i4";
98*d415bd75Srobert case MVT::v128i4: return "MVT::v128i4";
9909467b48Spatrick case MVT::v1i8: return "MVT::v1i8";
10009467b48Spatrick case MVT::v2i8: return "MVT::v2i8";
10109467b48Spatrick case MVT::v4i8: return "MVT::v4i8";
10209467b48Spatrick case MVT::v8i8: return "MVT::v8i8";
10309467b48Spatrick case MVT::v16i8: return "MVT::v16i8";
10409467b48Spatrick case MVT::v32i8: return "MVT::v32i8";
10509467b48Spatrick case MVT::v64i8: return "MVT::v64i8";
10609467b48Spatrick case MVT::v128i8: return "MVT::v128i8";
10709467b48Spatrick case MVT::v256i8: return "MVT::v256i8";
10873471bf0Spatrick case MVT::v512i8: return "MVT::v512i8";
10973471bf0Spatrick case MVT::v1024i8: return "MVT::v1024i8";
11009467b48Spatrick case MVT::v1i16: return "MVT::v1i16";
11109467b48Spatrick case MVT::v2i16: return "MVT::v2i16";
11209467b48Spatrick case MVT::v3i16: return "MVT::v3i16";
11309467b48Spatrick case MVT::v4i16: return "MVT::v4i16";
11409467b48Spatrick case MVT::v8i16: return "MVT::v8i16";
11509467b48Spatrick case MVT::v16i16: return "MVT::v16i16";
11609467b48Spatrick case MVT::v32i16: return "MVT::v32i16";
11709467b48Spatrick case MVT::v64i16: return "MVT::v64i16";
11809467b48Spatrick case MVT::v128i16: return "MVT::v128i16";
11973471bf0Spatrick case MVT::v256i16: return "MVT::v256i16";
12073471bf0Spatrick case MVT::v512i16: return "MVT::v512i16";
12109467b48Spatrick case MVT::v1i32: return "MVT::v1i32";
12209467b48Spatrick case MVT::v2i32: return "MVT::v2i32";
12309467b48Spatrick case MVT::v3i32: return "MVT::v3i32";
12409467b48Spatrick case MVT::v4i32: return "MVT::v4i32";
12509467b48Spatrick case MVT::v5i32: return "MVT::v5i32";
12673471bf0Spatrick case MVT::v6i32: return "MVT::v6i32";
12773471bf0Spatrick case MVT::v7i32: return "MVT::v7i32";
12809467b48Spatrick case MVT::v8i32: return "MVT::v8i32";
129*d415bd75Srobert case MVT::v9i32: return "MVT::v9i32";
130*d415bd75Srobert case MVT::v10i32: return "MVT::v10i32";
131*d415bd75Srobert case MVT::v11i32: return "MVT::v11i32";
132*d415bd75Srobert case MVT::v12i32: return "MVT::v12i32";
13309467b48Spatrick case MVT::v16i32: return "MVT::v16i32";
13409467b48Spatrick case MVT::v32i32: return "MVT::v32i32";
13509467b48Spatrick case MVT::v64i32: return "MVT::v64i32";
13609467b48Spatrick case MVT::v128i32: return "MVT::v128i32";
13709467b48Spatrick case MVT::v256i32: return "MVT::v256i32";
13809467b48Spatrick case MVT::v512i32: return "MVT::v512i32";
13909467b48Spatrick case MVT::v1024i32: return "MVT::v1024i32";
14009467b48Spatrick case MVT::v2048i32: return "MVT::v2048i32";
14109467b48Spatrick case MVT::v1i64: return "MVT::v1i64";
14209467b48Spatrick case MVT::v2i64: return "MVT::v2i64";
14373471bf0Spatrick case MVT::v3i64: return "MVT::v3i64";
14409467b48Spatrick case MVT::v4i64: return "MVT::v4i64";
14509467b48Spatrick case MVT::v8i64: return "MVT::v8i64";
14609467b48Spatrick case MVT::v16i64: return "MVT::v16i64";
14709467b48Spatrick case MVT::v32i64: return "MVT::v32i64";
14873471bf0Spatrick case MVT::v64i64: return "MVT::v64i64";
14973471bf0Spatrick case MVT::v128i64: return "MVT::v128i64";
15073471bf0Spatrick case MVT::v256i64: return "MVT::v256i64";
15109467b48Spatrick case MVT::v1i128: return "MVT::v1i128";
15273471bf0Spatrick case MVT::v1f16: return "MVT::v1f16";
15309467b48Spatrick case MVT::v2f16: return "MVT::v2f16";
15409467b48Spatrick case MVT::v3f16: return "MVT::v3f16";
15509467b48Spatrick case MVT::v4f16: return "MVT::v4f16";
15609467b48Spatrick case MVT::v8f16: return "MVT::v8f16";
15709467b48Spatrick case MVT::v16f16: return "MVT::v16f16";
15809467b48Spatrick case MVT::v32f16: return "MVT::v32f16";
159097a140dSpatrick case MVT::v64f16: return "MVT::v64f16";
160097a140dSpatrick case MVT::v128f16: return "MVT::v128f16";
16173471bf0Spatrick case MVT::v256f16: return "MVT::v256f16";
16273471bf0Spatrick case MVT::v512f16: return "MVT::v512f16";
163097a140dSpatrick case MVT::v2bf16: return "MVT::v2bf16";
164097a140dSpatrick case MVT::v3bf16: return "MVT::v3bf16";
165097a140dSpatrick case MVT::v4bf16: return "MVT::v4bf16";
166097a140dSpatrick case MVT::v8bf16: return "MVT::v8bf16";
167097a140dSpatrick case MVT::v16bf16: return "MVT::v16bf16";
168097a140dSpatrick case MVT::v32bf16: return "MVT::v32bf16";
169097a140dSpatrick case MVT::v64bf16: return "MVT::v64bf16";
170097a140dSpatrick case MVT::v128bf16: return "MVT::v128bf16";
17109467b48Spatrick case MVT::v1f32: return "MVT::v1f32";
17209467b48Spatrick case MVT::v2f32: return "MVT::v2f32";
17309467b48Spatrick case MVT::v3f32: return "MVT::v3f32";
17409467b48Spatrick case MVT::v4f32: return "MVT::v4f32";
17509467b48Spatrick case MVT::v5f32: return "MVT::v5f32";
17673471bf0Spatrick case MVT::v6f32: return "MVT::v6f32";
17773471bf0Spatrick case MVT::v7f32: return "MVT::v7f32";
17809467b48Spatrick case MVT::v8f32: return "MVT::v8f32";
179*d415bd75Srobert case MVT::v9f32: return "MVT::v9f32";
180*d415bd75Srobert case MVT::v10f32: return "MVT::v10f32";
181*d415bd75Srobert case MVT::v11f32: return "MVT::v11f32";
182*d415bd75Srobert case MVT::v12f32: return "MVT::v12f32";
18309467b48Spatrick case MVT::v16f32: return "MVT::v16f32";
18409467b48Spatrick case MVT::v32f32: return "MVT::v32f32";
18509467b48Spatrick case MVT::v64f32: return "MVT::v64f32";
18609467b48Spatrick case MVT::v128f32: return "MVT::v128f32";
18709467b48Spatrick case MVT::v256f32: return "MVT::v256f32";
18809467b48Spatrick case MVT::v512f32: return "MVT::v512f32";
18909467b48Spatrick case MVT::v1024f32: return "MVT::v1024f32";
19009467b48Spatrick case MVT::v2048f32: return "MVT::v2048f32";
19109467b48Spatrick case MVT::v1f64: return "MVT::v1f64";
19209467b48Spatrick case MVT::v2f64: return "MVT::v2f64";
19373471bf0Spatrick case MVT::v3f64: return "MVT::v3f64";
19409467b48Spatrick case MVT::v4f64: return "MVT::v4f64";
19509467b48Spatrick case MVT::v8f64: return "MVT::v8f64";
196097a140dSpatrick case MVT::v16f64: return "MVT::v16f64";
197097a140dSpatrick case MVT::v32f64: return "MVT::v32f64";
19873471bf0Spatrick case MVT::v64f64: return "MVT::v64f64";
19973471bf0Spatrick case MVT::v128f64: return "MVT::v128f64";
20073471bf0Spatrick case MVT::v256f64: return "MVT::v256f64";
20109467b48Spatrick case MVT::nxv1i1: return "MVT::nxv1i1";
20209467b48Spatrick case MVT::nxv2i1: return "MVT::nxv2i1";
20309467b48Spatrick case MVT::nxv4i1: return "MVT::nxv4i1";
20409467b48Spatrick case MVT::nxv8i1: return "MVT::nxv8i1";
20509467b48Spatrick case MVT::nxv16i1: return "MVT::nxv16i1";
20609467b48Spatrick case MVT::nxv32i1: return "MVT::nxv32i1";
207097a140dSpatrick case MVT::nxv64i1: return "MVT::nxv64i1";
20809467b48Spatrick case MVT::nxv1i8: return "MVT::nxv1i8";
20909467b48Spatrick case MVT::nxv2i8: return "MVT::nxv2i8";
21009467b48Spatrick case MVT::nxv4i8: return "MVT::nxv4i8";
21109467b48Spatrick case MVT::nxv8i8: return "MVT::nxv8i8";
21209467b48Spatrick case MVT::nxv16i8: return "MVT::nxv16i8";
21309467b48Spatrick case MVT::nxv32i8: return "MVT::nxv32i8";
214097a140dSpatrick case MVT::nxv64i8: return "MVT::nxv64i8";
21509467b48Spatrick case MVT::nxv1i16: return "MVT::nxv1i16";
21609467b48Spatrick case MVT::nxv2i16: return "MVT::nxv2i16";
21709467b48Spatrick case MVT::nxv4i16: return "MVT::nxv4i16";
21809467b48Spatrick case MVT::nxv8i16: return "MVT::nxv8i16";
21909467b48Spatrick case MVT::nxv16i16: return "MVT::nxv16i16";
22009467b48Spatrick case MVT::nxv32i16: return "MVT::nxv32i16";
22109467b48Spatrick case MVT::nxv1i32: return "MVT::nxv1i32";
22209467b48Spatrick case MVT::nxv2i32: return "MVT::nxv2i32";
22309467b48Spatrick case MVT::nxv4i32: return "MVT::nxv4i32";
22409467b48Spatrick case MVT::nxv8i32: return "MVT::nxv8i32";
22509467b48Spatrick case MVT::nxv16i32: return "MVT::nxv16i32";
226097a140dSpatrick case MVT::nxv32i32: return "MVT::nxv32i32";
22709467b48Spatrick case MVT::nxv1i64: return "MVT::nxv1i64";
22809467b48Spatrick case MVT::nxv2i64: return "MVT::nxv2i64";
22909467b48Spatrick case MVT::nxv4i64: return "MVT::nxv4i64";
23009467b48Spatrick case MVT::nxv8i64: return "MVT::nxv8i64";
23109467b48Spatrick case MVT::nxv16i64: return "MVT::nxv16i64";
232097a140dSpatrick case MVT::nxv32i64: return "MVT::nxv32i64";
233097a140dSpatrick case MVT::nxv1f16: return "MVT::nxv1f16";
23409467b48Spatrick case MVT::nxv2f16: return "MVT::nxv2f16";
23509467b48Spatrick case MVT::nxv4f16: return "MVT::nxv4f16";
23609467b48Spatrick case MVT::nxv8f16: return "MVT::nxv8f16";
237097a140dSpatrick case MVT::nxv16f16: return "MVT::nxv16f16";
238097a140dSpatrick case MVT::nxv32f16: return "MVT::nxv32f16";
23973471bf0Spatrick case MVT::nxv1bf16: return "MVT::nxv1bf16";
240097a140dSpatrick case MVT::nxv2bf16: return "MVT::nxv2bf16";
241097a140dSpatrick case MVT::nxv4bf16: return "MVT::nxv4bf16";
242097a140dSpatrick case MVT::nxv8bf16: return "MVT::nxv8bf16";
243*d415bd75Srobert case MVT::nxv16bf16: return "MVT::nxv16bf16";
244*d415bd75Srobert case MVT::nxv32bf16: return "MVT::nxv32bf16";
24509467b48Spatrick case MVT::nxv1f32: return "MVT::nxv1f32";
24609467b48Spatrick case MVT::nxv2f32: return "MVT::nxv2f32";
24709467b48Spatrick case MVT::nxv4f32: return "MVT::nxv4f32";
24809467b48Spatrick case MVT::nxv8f32: return "MVT::nxv8f32";
24909467b48Spatrick case MVT::nxv16f32: return "MVT::nxv16f32";
25009467b48Spatrick case MVT::nxv1f64: return "MVT::nxv1f64";
25109467b48Spatrick case MVT::nxv2f64: return "MVT::nxv2f64";
25209467b48Spatrick case MVT::nxv4f64: return "MVT::nxv4f64";
25309467b48Spatrick case MVT::nxv8f64: return "MVT::nxv8f64";
25409467b48Spatrick case MVT::token: return "MVT::token";
25509467b48Spatrick case MVT::Metadata: return "MVT::Metadata";
25609467b48Spatrick case MVT::iPTR: return "MVT::iPTR";
25709467b48Spatrick case MVT::iPTRAny: return "MVT::iPTRAny";
25809467b48Spatrick case MVT::Untyped: return "MVT::Untyped";
25973471bf0Spatrick case MVT::funcref: return "MVT::funcref";
26073471bf0Spatrick case MVT::externref: return "MVT::externref";
26109467b48Spatrick default: llvm_unreachable("ILLEGAL VALUE TYPE!");
26209467b48Spatrick }
263*d415bd75Srobert // clang-format on
26409467b48Spatrick }
26509467b48Spatrick
26609467b48Spatrick /// getQualifiedName - Return the name of the specified record, with a
26709467b48Spatrick /// namespace qualifier if the record contains one.
26809467b48Spatrick ///
getQualifiedName(const Record * R)26909467b48Spatrick std::string llvm::getQualifiedName(const Record *R) {
27009467b48Spatrick std::string Namespace;
27109467b48Spatrick if (R->getValue("Namespace"))
272097a140dSpatrick Namespace = std::string(R->getValueAsString("Namespace"));
273097a140dSpatrick if (Namespace.empty())
274097a140dSpatrick return std::string(R->getName());
27509467b48Spatrick return Namespace + "::" + R->getName().str();
27609467b48Spatrick }
27709467b48Spatrick
27809467b48Spatrick
27909467b48Spatrick /// getTarget - Return the current instance of the Target class.
28009467b48Spatrick ///
CodeGenTarget(RecordKeeper & records)28109467b48Spatrick CodeGenTarget::CodeGenTarget(RecordKeeper &records)
28209467b48Spatrick : Records(records), CGH(records) {
28309467b48Spatrick std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
28409467b48Spatrick if (Targets.size() == 0)
28573471bf0Spatrick PrintFatalError("No 'Target' subclasses defined!");
28609467b48Spatrick if (Targets.size() != 1)
28773471bf0Spatrick PrintFatalError("Multiple subclasses of Target defined!");
28809467b48Spatrick TargetRec = Targets[0];
28909467b48Spatrick }
29009467b48Spatrick
~CodeGenTarget()29109467b48Spatrick CodeGenTarget::~CodeGenTarget() {
29209467b48Spatrick }
29309467b48Spatrick
getName() const29473471bf0Spatrick StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }
29509467b48Spatrick
29673471bf0Spatrick /// getInstNamespace - Find and return the target machine's instruction
29773471bf0Spatrick /// namespace. The namespace is cached because it is requested multiple times.
getInstNamespace() const29809467b48Spatrick StringRef CodeGenTarget::getInstNamespace() const {
29973471bf0Spatrick if (InstNamespace.empty()) {
30009467b48Spatrick for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) {
30173471bf0Spatrick // We are not interested in the "TargetOpcode" namespace.
30273471bf0Spatrick if (Inst->Namespace != "TargetOpcode") {
30373471bf0Spatrick InstNamespace = Inst->Namespace;
30473471bf0Spatrick break;
30573471bf0Spatrick }
30673471bf0Spatrick }
30709467b48Spatrick }
30809467b48Spatrick
30973471bf0Spatrick return InstNamespace;
31073471bf0Spatrick }
31173471bf0Spatrick
getRegNamespace() const31273471bf0Spatrick StringRef CodeGenTarget::getRegNamespace() const {
31373471bf0Spatrick auto &RegClasses = RegBank->getRegClasses();
31473471bf0Spatrick return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";
31509467b48Spatrick }
31609467b48Spatrick
getInstructionSet() const31709467b48Spatrick Record *CodeGenTarget::getInstructionSet() const {
31809467b48Spatrick return TargetRec->getValueAsDef("InstructionSet");
31909467b48Spatrick }
32009467b48Spatrick
getAllowRegisterRenaming() const32109467b48Spatrick bool CodeGenTarget::getAllowRegisterRenaming() const {
32209467b48Spatrick return TargetRec->getValueAsInt("AllowRegisterRenaming");
32309467b48Spatrick }
32409467b48Spatrick
32509467b48Spatrick /// getAsmParser - Return the AssemblyParser definition for this target.
32609467b48Spatrick ///
getAsmParser() const32709467b48Spatrick Record *CodeGenTarget::getAsmParser() const {
32809467b48Spatrick std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
32909467b48Spatrick if (AsmParserNum >= LI.size())
33009467b48Spatrick PrintFatalError("Target does not have an AsmParser #" +
33109467b48Spatrick Twine(AsmParserNum) + "!");
33209467b48Spatrick return LI[AsmParserNum];
33309467b48Spatrick }
33409467b48Spatrick
33509467b48Spatrick /// getAsmParserVariant - Return the AssemblyParserVariant definition for
33609467b48Spatrick /// this target.
33709467b48Spatrick ///
getAsmParserVariant(unsigned i) const33809467b48Spatrick Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
33909467b48Spatrick std::vector<Record*> LI =
34009467b48Spatrick TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
34109467b48Spatrick if (i >= LI.size())
34209467b48Spatrick PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) +
34309467b48Spatrick "!");
34409467b48Spatrick return LI[i];
34509467b48Spatrick }
34609467b48Spatrick
34709467b48Spatrick /// getAsmParserVariantCount - Return the AssemblyParserVariant definition
34809467b48Spatrick /// available for this target.
34909467b48Spatrick ///
getAsmParserVariantCount() const35009467b48Spatrick unsigned CodeGenTarget::getAsmParserVariantCount() const {
35109467b48Spatrick std::vector<Record*> LI =
35209467b48Spatrick TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
35309467b48Spatrick return LI.size();
35409467b48Spatrick }
35509467b48Spatrick
35609467b48Spatrick /// getAsmWriter - Return the AssemblyWriter definition for this target.
35709467b48Spatrick ///
getAsmWriter() const35809467b48Spatrick Record *CodeGenTarget::getAsmWriter() const {
35909467b48Spatrick std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
36009467b48Spatrick if (AsmWriterNum >= LI.size())
36109467b48Spatrick PrintFatalError("Target does not have an AsmWriter #" +
36209467b48Spatrick Twine(AsmWriterNum) + "!");
36309467b48Spatrick return LI[AsmWriterNum];
36409467b48Spatrick }
36509467b48Spatrick
getRegBank() const36609467b48Spatrick CodeGenRegBank &CodeGenTarget::getRegBank() const {
36709467b48Spatrick if (!RegBank)
36809467b48Spatrick RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes());
36909467b48Spatrick return *RegBank;
37009467b48Spatrick }
37109467b48Spatrick
getSuperRegForSubReg(const ValueTypeByHwMode & ValueTy,CodeGenRegBank & RegBank,const CodeGenSubRegIndex * SubIdx,bool MustBeAllocatable) const372*d415bd75Srobert std::optional<CodeGenRegisterClass *> CodeGenTarget::getSuperRegForSubReg(
373*d415bd75Srobert const ValueTypeByHwMode &ValueTy, CodeGenRegBank &RegBank,
374*d415bd75Srobert const CodeGenSubRegIndex *SubIdx, bool MustBeAllocatable) const {
37509467b48Spatrick std::vector<CodeGenRegisterClass *> Candidates;
37609467b48Spatrick auto &RegClasses = RegBank.getRegClasses();
37709467b48Spatrick
37809467b48Spatrick // Try to find a register class which supports ValueTy, and also contains
37909467b48Spatrick // SubIdx.
38009467b48Spatrick for (CodeGenRegisterClass &RC : RegClasses) {
38109467b48Spatrick // Is there a subclass of this class which contains this subregister index?
38209467b48Spatrick CodeGenRegisterClass *SubClassWithSubReg = RC.getSubClassWithSubReg(SubIdx);
38309467b48Spatrick if (!SubClassWithSubReg)
38409467b48Spatrick continue;
38509467b48Spatrick
38609467b48Spatrick // We have a class. Check if it supports this value type.
38773471bf0Spatrick if (!llvm::is_contained(SubClassWithSubReg->VTs, ValueTy))
38873471bf0Spatrick continue;
38973471bf0Spatrick
39073471bf0Spatrick // If necessary, check that it is allocatable.
39173471bf0Spatrick if (MustBeAllocatable && !SubClassWithSubReg->Allocatable)
39209467b48Spatrick continue;
39309467b48Spatrick
39409467b48Spatrick // We have a register class which supports both the value type and
39509467b48Spatrick // subregister index. Remember it.
39609467b48Spatrick Candidates.push_back(SubClassWithSubReg);
39709467b48Spatrick }
39809467b48Spatrick
39909467b48Spatrick // If we didn't find anything, we're done.
40009467b48Spatrick if (Candidates.empty())
401*d415bd75Srobert return std::nullopt;
40209467b48Spatrick
40309467b48Spatrick // Find and return the largest of our candidate classes.
40409467b48Spatrick llvm::stable_sort(Candidates, [&](const CodeGenRegisterClass *A,
40509467b48Spatrick const CodeGenRegisterClass *B) {
40609467b48Spatrick if (A->getMembers().size() > B->getMembers().size())
40709467b48Spatrick return true;
40809467b48Spatrick
40909467b48Spatrick if (A->getMembers().size() < B->getMembers().size())
41009467b48Spatrick return false;
41109467b48Spatrick
41209467b48Spatrick // Order by name as a tie-breaker.
41309467b48Spatrick return StringRef(A->getName()) < B->getName();
41409467b48Spatrick });
41509467b48Spatrick
41609467b48Spatrick return Candidates[0];
41709467b48Spatrick }
41809467b48Spatrick
ReadRegAltNameIndices() const41909467b48Spatrick void CodeGenTarget::ReadRegAltNameIndices() const {
42009467b48Spatrick RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
42109467b48Spatrick llvm::sort(RegAltNameIndices, LessRecord());
42209467b48Spatrick }
42309467b48Spatrick
42409467b48Spatrick /// getRegisterByName - If there is a register with the specific AsmName,
42509467b48Spatrick /// return it.
getRegisterByName(StringRef Name) const42609467b48Spatrick const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
42773471bf0Spatrick return getRegBank().getRegistersByName().lookup(Name);
42809467b48Spatrick }
42909467b48Spatrick
getRegisterVTs(Record * R) const43009467b48Spatrick std::vector<ValueTypeByHwMode> CodeGenTarget::getRegisterVTs(Record *R)
43109467b48Spatrick const {
43209467b48Spatrick const CodeGenRegister *Reg = getRegBank().getReg(R);
43309467b48Spatrick std::vector<ValueTypeByHwMode> Result;
43409467b48Spatrick for (const auto &RC : getRegBank().getRegClasses()) {
43509467b48Spatrick if (RC.contains(Reg)) {
43609467b48Spatrick ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes();
43773471bf0Spatrick llvm::append_range(Result, InVTs);
43809467b48Spatrick }
43909467b48Spatrick }
44009467b48Spatrick
44109467b48Spatrick // Remove duplicates.
44209467b48Spatrick llvm::sort(Result);
44309467b48Spatrick Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
44409467b48Spatrick return Result;
44509467b48Spatrick }
44609467b48Spatrick
44709467b48Spatrick
ReadLegalValueTypes() const44809467b48Spatrick void CodeGenTarget::ReadLegalValueTypes() const {
44909467b48Spatrick for (const auto &RC : getRegBank().getRegClasses())
45073471bf0Spatrick llvm::append_range(LegalValueTypes, RC.VTs);
45109467b48Spatrick
45209467b48Spatrick // Remove duplicates.
45309467b48Spatrick llvm::sort(LegalValueTypes);
45409467b48Spatrick LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
45509467b48Spatrick LegalValueTypes.end()),
45609467b48Spatrick LegalValueTypes.end());
45709467b48Spatrick }
45809467b48Spatrick
getSchedModels() const45909467b48Spatrick CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
46009467b48Spatrick if (!SchedModels)
46109467b48Spatrick SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this);
46209467b48Spatrick return *SchedModels;
46309467b48Spatrick }
46409467b48Spatrick
ReadInstructions() const46509467b48Spatrick void CodeGenTarget::ReadInstructions() const {
46609467b48Spatrick std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
46709467b48Spatrick if (Insts.size() <= 2)
46809467b48Spatrick PrintFatalError("No 'Instruction' subclasses defined!");
46909467b48Spatrick
47009467b48Spatrick // Parse the instructions defined in the .td file.
47109467b48Spatrick for (unsigned i = 0, e = Insts.size(); i != e; ++i)
47209467b48Spatrick Instructions[Insts[i]] = std::make_unique<CodeGenInstruction>(Insts[i]);
47309467b48Spatrick }
47409467b48Spatrick
47509467b48Spatrick static const CodeGenInstruction *
GetInstByName(const char * Name,const DenseMap<const Record *,std::unique_ptr<CodeGenInstruction>> & Insts,RecordKeeper & Records)47609467b48Spatrick GetInstByName(const char *Name,
47709467b48Spatrick const DenseMap<const Record*,
47809467b48Spatrick std::unique_ptr<CodeGenInstruction>> &Insts,
47909467b48Spatrick RecordKeeper &Records) {
48009467b48Spatrick const Record *Rec = Records.getDef(Name);
48109467b48Spatrick
48209467b48Spatrick const auto I = Insts.find(Rec);
48309467b48Spatrick if (!Rec || I == Insts.end())
48409467b48Spatrick PrintFatalError(Twine("Could not find '") + Name + "' instruction!");
48509467b48Spatrick return I->second.get();
48609467b48Spatrick }
48709467b48Spatrick
488*d415bd75Srobert static const char *FixedInstrs[] = {
48909467b48Spatrick #define HANDLE_TARGET_OPCODE(OPC) #OPC,
49009467b48Spatrick #include "llvm/Support/TargetOpcodes.def"
49109467b48Spatrick nullptr};
49209467b48Spatrick
getNumFixedInstructions()49309467b48Spatrick unsigned CodeGenTarget::getNumFixedInstructions() {
494*d415bd75Srobert return std::size(FixedInstrs) - 1;
49509467b48Spatrick }
49609467b48Spatrick
49709467b48Spatrick /// Return all of the instructions defined by the target, ordered by
49809467b48Spatrick /// their enum value.
ComputeInstrsByEnum() const49909467b48Spatrick void CodeGenTarget::ComputeInstrsByEnum() const {
50009467b48Spatrick const auto &Insts = getInstructions();
50109467b48Spatrick for (const char *const *p = FixedInstrs; *p; ++p) {
50209467b48Spatrick const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
50309467b48Spatrick assert(Instr && "Missing target independent instruction");
50409467b48Spatrick assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
50509467b48Spatrick InstrsByEnum.push_back(Instr);
50609467b48Spatrick }
50709467b48Spatrick unsigned EndOfPredefines = InstrsByEnum.size();
50809467b48Spatrick assert(EndOfPredefines == getNumFixedInstructions() &&
50909467b48Spatrick "Missing generic opcode");
51009467b48Spatrick
51109467b48Spatrick for (const auto &I : Insts) {
51209467b48Spatrick const CodeGenInstruction *CGI = I.second.get();
51309467b48Spatrick if (CGI->Namespace != "TargetOpcode") {
51409467b48Spatrick InstrsByEnum.push_back(CGI);
51509467b48Spatrick if (CGI->TheDef->getValueAsBit("isPseudo"))
51609467b48Spatrick ++NumPseudoInstructions;
51709467b48Spatrick }
51809467b48Spatrick }
51909467b48Spatrick
52009467b48Spatrick assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
52109467b48Spatrick
52209467b48Spatrick // All of the instructions are now in random order based on the map iteration.
52309467b48Spatrick llvm::sort(
52409467b48Spatrick InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
52509467b48Spatrick [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
52609467b48Spatrick const auto &D1 = *Rec1->TheDef;
52709467b48Spatrick const auto &D2 = *Rec2->TheDef;
52809467b48Spatrick return std::make_tuple(!D1.getValueAsBit("isPseudo"), D1.getName()) <
52909467b48Spatrick std::make_tuple(!D2.getValueAsBit("isPseudo"), D2.getName());
53009467b48Spatrick });
53109467b48Spatrick }
53209467b48Spatrick
53309467b48Spatrick
53409467b48Spatrick /// isLittleEndianEncoding - Return whether this target encodes its instruction
53509467b48Spatrick /// in little-endian format, i.e. bits laid out in the order [0..n]
53609467b48Spatrick ///
isLittleEndianEncoding() const53709467b48Spatrick bool CodeGenTarget::isLittleEndianEncoding() const {
53809467b48Spatrick return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
53909467b48Spatrick }
54009467b48Spatrick
54109467b48Spatrick /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
54209467b48Spatrick /// encodings, reverse the bit order of all instructions.
reverseBitsForLittleEndianEncoding()54309467b48Spatrick void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
54409467b48Spatrick if (!isLittleEndianEncoding())
54509467b48Spatrick return;
54609467b48Spatrick
54709467b48Spatrick std::vector<Record *> Insts =
54809467b48Spatrick Records.getAllDerivedDefinitions("InstructionEncoding");
54909467b48Spatrick for (Record *R : Insts) {
55009467b48Spatrick if (R->getValueAsString("Namespace") == "TargetOpcode" ||
55109467b48Spatrick R->getValueAsBit("isPseudo"))
55209467b48Spatrick continue;
55309467b48Spatrick
55409467b48Spatrick BitsInit *BI = R->getValueAsBitsInit("Inst");
55509467b48Spatrick
55609467b48Spatrick unsigned numBits = BI->getNumBits();
55709467b48Spatrick
55809467b48Spatrick SmallVector<Init *, 16> NewBits(numBits);
55909467b48Spatrick
56009467b48Spatrick for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
56109467b48Spatrick unsigned bitSwapIdx = numBits - bit - 1;
56209467b48Spatrick Init *OrigBit = BI->getBit(bit);
56309467b48Spatrick Init *BitSwap = BI->getBit(bitSwapIdx);
56409467b48Spatrick NewBits[bit] = BitSwap;
56509467b48Spatrick NewBits[bitSwapIdx] = OrigBit;
56609467b48Spatrick }
56709467b48Spatrick if (numBits % 2) {
56809467b48Spatrick unsigned middle = (numBits + 1) / 2;
56909467b48Spatrick NewBits[middle] = BI->getBit(middle);
57009467b48Spatrick }
57109467b48Spatrick
572*d415bd75Srobert BitsInit *NewBI = BitsInit::get(Records, NewBits);
57309467b48Spatrick
57409467b48Spatrick // Update the bits in reversed order so that emitInstrOpBits will get the
57509467b48Spatrick // correct endianness.
57609467b48Spatrick R->getValue("Inst")->setValue(NewBI);
57709467b48Spatrick }
57809467b48Spatrick }
57909467b48Spatrick
58009467b48Spatrick /// guessInstructionProperties - Return true if it's OK to guess instruction
58109467b48Spatrick /// properties instead of raising an error.
58209467b48Spatrick ///
58309467b48Spatrick /// This is configurable as a temporary migration aid. It will eventually be
58409467b48Spatrick /// permanently false.
guessInstructionProperties() const58509467b48Spatrick bool CodeGenTarget::guessInstructionProperties() const {
58609467b48Spatrick return getInstructionSet()->getValueAsBit("guessInstructionProperties");
58709467b48Spatrick }
58809467b48Spatrick
58909467b48Spatrick //===----------------------------------------------------------------------===//
59009467b48Spatrick // ComplexPattern implementation
59109467b48Spatrick //
ComplexPattern(Record * R)59209467b48Spatrick ComplexPattern::ComplexPattern(Record *R) {
593*d415bd75Srobert Ty = R->getValueAsDef("Ty");
59409467b48Spatrick NumOperands = R->getValueAsInt("NumOperands");
595097a140dSpatrick SelectFunc = std::string(R->getValueAsString("SelectFunc"));
59609467b48Spatrick RootNodes = R->getValueAsListOfDefs("RootNodes");
59709467b48Spatrick
59809467b48Spatrick // FIXME: This is a hack to statically increase the priority of patterns which
59909467b48Spatrick // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
60009467b48Spatrick // possible pattern match we'll need to dynamically calculate the complexity
60109467b48Spatrick // of all patterns a dag can potentially map to.
60209467b48Spatrick int64_t RawComplexity = R->getValueAsInt("Complexity");
60309467b48Spatrick if (RawComplexity == -1)
60409467b48Spatrick Complexity = NumOperands * 3;
60509467b48Spatrick else
60609467b48Spatrick Complexity = RawComplexity;
60709467b48Spatrick
60809467b48Spatrick // FIXME: Why is this different from parseSDPatternOperatorProperties?
60909467b48Spatrick // Parse the properties.
61009467b48Spatrick Properties = 0;
61109467b48Spatrick std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
61209467b48Spatrick for (unsigned i = 0, e = PropList.size(); i != e; ++i)
61309467b48Spatrick if (PropList[i]->getName() == "SDNPHasChain") {
61409467b48Spatrick Properties |= 1 << SDNPHasChain;
61509467b48Spatrick } else if (PropList[i]->getName() == "SDNPOptInGlue") {
61609467b48Spatrick Properties |= 1 << SDNPOptInGlue;
61709467b48Spatrick } else if (PropList[i]->getName() == "SDNPMayStore") {
61809467b48Spatrick Properties |= 1 << SDNPMayStore;
61909467b48Spatrick } else if (PropList[i]->getName() == "SDNPMayLoad") {
62009467b48Spatrick Properties |= 1 << SDNPMayLoad;
62109467b48Spatrick } else if (PropList[i]->getName() == "SDNPSideEffect") {
62209467b48Spatrick Properties |= 1 << SDNPSideEffect;
62309467b48Spatrick } else if (PropList[i]->getName() == "SDNPMemOperand") {
62409467b48Spatrick Properties |= 1 << SDNPMemOperand;
62509467b48Spatrick } else if (PropList[i]->getName() == "SDNPVariadic") {
62609467b48Spatrick Properties |= 1 << SDNPVariadic;
62709467b48Spatrick } else if (PropList[i]->getName() == "SDNPWantRoot") {
62809467b48Spatrick Properties |= 1 << SDNPWantRoot;
62909467b48Spatrick } else if (PropList[i]->getName() == "SDNPWantParent") {
63009467b48Spatrick Properties |= 1 << SDNPWantParent;
63109467b48Spatrick } else {
63209467b48Spatrick PrintFatalError(R->getLoc(), "Unsupported SD Node property '" +
63309467b48Spatrick PropList[i]->getName() +
63409467b48Spatrick "' on ComplexPattern '" + R->getName() +
63509467b48Spatrick "'!");
63609467b48Spatrick }
63709467b48Spatrick }
63809467b48Spatrick
63909467b48Spatrick //===----------------------------------------------------------------------===//
64009467b48Spatrick // CodeGenIntrinsic Implementation
64109467b48Spatrick //===----------------------------------------------------------------------===//
64209467b48Spatrick
CodeGenIntrinsicTable(const RecordKeeper & RC)64309467b48Spatrick CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {
64473471bf0Spatrick std::vector<Record *> IntrProperties =
64573471bf0Spatrick RC.getAllDerivedDefinitions("IntrinsicProperty");
64609467b48Spatrick
64773471bf0Spatrick std::vector<Record *> DefaultProperties;
64873471bf0Spatrick for (Record *Rec : IntrProperties)
64973471bf0Spatrick if (Rec->getValueAsBit("IsDefault"))
65073471bf0Spatrick DefaultProperties.push_back(Rec);
65173471bf0Spatrick
65273471bf0Spatrick std::vector<Record *> Defs = RC.getAllDerivedDefinitions("Intrinsic");
65309467b48Spatrick Intrinsics.reserve(Defs.size());
65409467b48Spatrick
65509467b48Spatrick for (unsigned I = 0, e = Defs.size(); I != e; ++I)
65673471bf0Spatrick Intrinsics.push_back(CodeGenIntrinsic(Defs[I], DefaultProperties));
65709467b48Spatrick
65809467b48Spatrick llvm::sort(Intrinsics,
65909467b48Spatrick [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
66009467b48Spatrick return std::tie(LHS.TargetPrefix, LHS.Name) <
66109467b48Spatrick std::tie(RHS.TargetPrefix, RHS.Name);
66209467b48Spatrick });
66309467b48Spatrick Targets.push_back({"", 0, 0});
66409467b48Spatrick for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
66509467b48Spatrick if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
66609467b48Spatrick Targets.back().Count = I - Targets.back().Offset;
66709467b48Spatrick Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});
66809467b48Spatrick }
66909467b48Spatrick Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
67009467b48Spatrick }
67109467b48Spatrick
CodeGenIntrinsic(Record * R,std::vector<Record * > DefaultProperties)67273471bf0Spatrick CodeGenIntrinsic::CodeGenIntrinsic(Record *R,
67373471bf0Spatrick std::vector<Record *> DefaultProperties) {
67409467b48Spatrick TheDef = R;
675097a140dSpatrick std::string DefName = std::string(R->getName());
67609467b48Spatrick ArrayRef<SMLoc> DefLoc = R->getLoc();
67709467b48Spatrick Properties = 0;
67809467b48Spatrick isOverloaded = false;
67909467b48Spatrick isCommutative = false;
68009467b48Spatrick canThrow = false;
68109467b48Spatrick isNoReturn = false;
682*d415bd75Srobert isNoCallback = false;
683097a140dSpatrick isNoSync = false;
684097a140dSpatrick isNoFree = false;
68509467b48Spatrick isWillReturn = false;
68609467b48Spatrick isCold = false;
68709467b48Spatrick isNoDuplicate = false;
68873471bf0Spatrick isNoMerge = false;
68909467b48Spatrick isConvergent = false;
69009467b48Spatrick isSpeculatable = false;
69109467b48Spatrick hasSideEffects = false;
69209467b48Spatrick
693*d415bd75Srobert if (DefName.size() <= 4 || DefName.substr(0, 4) != "int_")
69409467b48Spatrick PrintFatalError(DefLoc,
69509467b48Spatrick "Intrinsic '" + DefName + "' does not start with 'int_'!");
69609467b48Spatrick
697*d415bd75Srobert EnumName = DefName.substr(4);
69809467b48Spatrick
699*d415bd75Srobert if (R->getValue("ClangBuiltinName")) // Ignore a missing ClangBuiltinName field.
700*d415bd75Srobert ClangBuiltinName = std::string(R->getValueAsString("ClangBuiltinName"));
70109467b48Spatrick if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field.
702097a140dSpatrick MSBuiltinName = std::string(R->getValueAsString("MSBuiltinName"));
70309467b48Spatrick
704097a140dSpatrick TargetPrefix = std::string(R->getValueAsString("TargetPrefix"));
705097a140dSpatrick Name = std::string(R->getValueAsString("LLVMName"));
70609467b48Spatrick
70709467b48Spatrick if (Name == "") {
70809467b48Spatrick // If an explicit name isn't specified, derive one from the DefName.
70909467b48Spatrick Name = "llvm.";
71009467b48Spatrick
71109467b48Spatrick for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
71209467b48Spatrick Name += (EnumName[i] == '_') ? '.' : EnumName[i];
71309467b48Spatrick } else {
71409467b48Spatrick // Verify it starts with "llvm.".
715*d415bd75Srobert if (Name.size() <= 5 || Name.substr(0, 5) != "llvm.")
71609467b48Spatrick PrintFatalError(DefLoc, "Intrinsic '" + DefName +
71709467b48Spatrick "'s name does not start with 'llvm.'!");
71809467b48Spatrick }
71909467b48Spatrick
72009467b48Spatrick // If TargetPrefix is specified, make sure that Name starts with
72109467b48Spatrick // "llvm.<targetprefix>.".
72209467b48Spatrick if (!TargetPrefix.empty()) {
72309467b48Spatrick if (Name.size() < 6+TargetPrefix.size() ||
724*d415bd75Srobert Name.substr(5, 1 + TargetPrefix.size()) != (TargetPrefix + "."))
72509467b48Spatrick PrintFatalError(DefLoc, "Intrinsic '" + DefName +
72609467b48Spatrick "' does not start with 'llvm." +
72709467b48Spatrick TargetPrefix + ".'!");
72809467b48Spatrick }
72909467b48Spatrick
73009467b48Spatrick ListInit *RetTypes = R->getValueAsListInit("RetTypes");
73109467b48Spatrick ListInit *ParamTypes = R->getValueAsListInit("ParamTypes");
73209467b48Spatrick
73309467b48Spatrick // First collate a list of overloaded types.
73409467b48Spatrick std::vector<MVT::SimpleValueType> OverloadedVTs;
73509467b48Spatrick for (ListInit *TypeList : {RetTypes, ParamTypes}) {
73609467b48Spatrick for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
73709467b48Spatrick Record *TyEl = TypeList->getElementAsRecord(i);
73809467b48Spatrick assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
73909467b48Spatrick
74009467b48Spatrick if (TyEl->isSubClassOf("LLVMMatchType"))
74109467b48Spatrick continue;
74209467b48Spatrick
74309467b48Spatrick MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT"));
74409467b48Spatrick if (MVT(VT).isOverloaded()) {
74509467b48Spatrick OverloadedVTs.push_back(VT);
74609467b48Spatrick isOverloaded = true;
74709467b48Spatrick }
74809467b48Spatrick }
74909467b48Spatrick }
75009467b48Spatrick
75109467b48Spatrick // Parse the list of return types.
75209467b48Spatrick ListInit *TypeList = RetTypes;
75309467b48Spatrick for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
75409467b48Spatrick Record *TyEl = TypeList->getElementAsRecord(i);
75509467b48Spatrick assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
75609467b48Spatrick MVT::SimpleValueType VT;
75709467b48Spatrick if (TyEl->isSubClassOf("LLVMMatchType")) {
75809467b48Spatrick unsigned MatchTy = TyEl->getValueAsInt("Number");
75909467b48Spatrick assert(MatchTy < OverloadedVTs.size() &&
76009467b48Spatrick "Invalid matching number!");
76109467b48Spatrick VT = OverloadedVTs[MatchTy];
76209467b48Spatrick // It only makes sense to use the extended and truncated vector element
76309467b48Spatrick // variants with iAny types; otherwise, if the intrinsic is not
76409467b48Spatrick // overloaded, all the types can be specified directly.
76509467b48Spatrick assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
76609467b48Spatrick !TyEl->isSubClassOf("LLVMTruncatedType")) ||
76709467b48Spatrick VT == MVT::iAny || VT == MVT::vAny) &&
76809467b48Spatrick "Expected iAny or vAny type");
76909467b48Spatrick } else {
77009467b48Spatrick VT = getValueType(TyEl->getValueAsDef("VT"));
77109467b48Spatrick }
77209467b48Spatrick
77309467b48Spatrick // Reject invalid types.
77409467b48Spatrick if (VT == MVT::isVoid)
77509467b48Spatrick PrintFatalError(DefLoc, "Intrinsic '" + DefName +
77609467b48Spatrick " has void in result type list!");
77709467b48Spatrick
77809467b48Spatrick IS.RetVTs.push_back(VT);
77909467b48Spatrick IS.RetTypeDefs.push_back(TyEl);
78009467b48Spatrick }
78109467b48Spatrick
78209467b48Spatrick // Parse the list of parameter types.
78309467b48Spatrick TypeList = ParamTypes;
78409467b48Spatrick for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
78509467b48Spatrick Record *TyEl = TypeList->getElementAsRecord(i);
78609467b48Spatrick assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
78709467b48Spatrick MVT::SimpleValueType VT;
78809467b48Spatrick if (TyEl->isSubClassOf("LLVMMatchType")) {
78909467b48Spatrick unsigned MatchTy = TyEl->getValueAsInt("Number");
79009467b48Spatrick if (MatchTy >= OverloadedVTs.size()) {
79109467b48Spatrick PrintError(R->getLoc(),
79209467b48Spatrick "Parameter #" + Twine(i) + " has out of bounds matching "
79309467b48Spatrick "number " + Twine(MatchTy));
79409467b48Spatrick PrintFatalError(DefLoc,
79509467b48Spatrick Twine("ParamTypes is ") + TypeList->getAsString());
79609467b48Spatrick }
79709467b48Spatrick VT = OverloadedVTs[MatchTy];
79809467b48Spatrick // It only makes sense to use the extended and truncated vector element
79909467b48Spatrick // variants with iAny types; otherwise, if the intrinsic is not
80009467b48Spatrick // overloaded, all the types can be specified directly.
80109467b48Spatrick assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
802097a140dSpatrick !TyEl->isSubClassOf("LLVMTruncatedType")) ||
80309467b48Spatrick VT == MVT::iAny || VT == MVT::vAny) &&
80409467b48Spatrick "Expected iAny or vAny type");
80509467b48Spatrick } else
80609467b48Spatrick VT = getValueType(TyEl->getValueAsDef("VT"));
80709467b48Spatrick
80809467b48Spatrick // Reject invalid types.
80909467b48Spatrick if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
81009467b48Spatrick PrintFatalError(DefLoc, "Intrinsic '" + DefName +
81109467b48Spatrick " has void in result type list!");
81209467b48Spatrick
81309467b48Spatrick IS.ParamVTs.push_back(VT);
81409467b48Spatrick IS.ParamTypeDefs.push_back(TyEl);
81509467b48Spatrick }
81609467b48Spatrick
81709467b48Spatrick // Parse the intrinsic properties.
81809467b48Spatrick ListInit *PropList = R->getValueAsListInit("IntrProperties");
81909467b48Spatrick for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
82009467b48Spatrick Record *Property = PropList->getElementAsRecord(i);
82109467b48Spatrick assert(Property->isSubClassOf("IntrinsicProperty") &&
82209467b48Spatrick "Expected a property!");
82309467b48Spatrick
82473471bf0Spatrick setProperty(Property);
82509467b48Spatrick }
82609467b48Spatrick
82773471bf0Spatrick // Set default properties to true.
82873471bf0Spatrick setDefaultProperties(R, DefaultProperties);
82973471bf0Spatrick
83009467b48Spatrick // Also record the SDPatternOperator Properties.
83109467b48Spatrick Properties = parseSDPatternOperatorProperties(R);
83209467b48Spatrick
83309467b48Spatrick // Sort the argument attributes for later benefit.
834*d415bd75Srobert for (auto &Attrs : ArgumentAttributes)
835*d415bd75Srobert llvm::sort(Attrs);
83609467b48Spatrick }
83709467b48Spatrick
setDefaultProperties(Record * R,std::vector<Record * > DefaultProperties)83873471bf0Spatrick void CodeGenIntrinsic::setDefaultProperties(
83973471bf0Spatrick Record *R, std::vector<Record *> DefaultProperties) {
84073471bf0Spatrick // opt-out of using default attributes.
84173471bf0Spatrick if (R->getValueAsBit("DisableDefaultAttributes"))
84273471bf0Spatrick return;
84373471bf0Spatrick
84473471bf0Spatrick for (Record *Rec : DefaultProperties)
84573471bf0Spatrick setProperty(Rec);
84673471bf0Spatrick }
84773471bf0Spatrick
setProperty(Record * R)84873471bf0Spatrick void CodeGenIntrinsic::setProperty(Record *R) {
84973471bf0Spatrick if (R->getName() == "IntrNoMem")
850*d415bd75Srobert ME = MemoryEffects::none();
85173471bf0Spatrick else if (R->getName() == "IntrReadMem") {
852*d415bd75Srobert if (ME.onlyWritesMemory())
85373471bf0Spatrick PrintFatalError(TheDef->getLoc(),
85473471bf0Spatrick Twine("IntrReadMem cannot be used after IntrNoMem or "
85573471bf0Spatrick "IntrWriteMem. Default is ReadWrite"));
856*d415bd75Srobert ME &= MemoryEffects::readOnly();
85773471bf0Spatrick } else if (R->getName() == "IntrWriteMem") {
858*d415bd75Srobert if (ME.onlyReadsMemory())
85973471bf0Spatrick PrintFatalError(TheDef->getLoc(),
86073471bf0Spatrick Twine("IntrWriteMem cannot be used after IntrNoMem or "
86173471bf0Spatrick "IntrReadMem. Default is ReadWrite"));
862*d415bd75Srobert ME &= MemoryEffects::writeOnly();
86373471bf0Spatrick } else if (R->getName() == "IntrArgMemOnly")
864*d415bd75Srobert ME &= MemoryEffects::argMemOnly();
86573471bf0Spatrick else if (R->getName() == "IntrInaccessibleMemOnly")
866*d415bd75Srobert ME &= MemoryEffects::inaccessibleMemOnly();
86773471bf0Spatrick else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
868*d415bd75Srobert ME &= MemoryEffects::inaccessibleOrArgMemOnly();
86973471bf0Spatrick else if (R->getName() == "Commutative")
87073471bf0Spatrick isCommutative = true;
87173471bf0Spatrick else if (R->getName() == "Throws")
87273471bf0Spatrick canThrow = true;
87373471bf0Spatrick else if (R->getName() == "IntrNoDuplicate")
87473471bf0Spatrick isNoDuplicate = true;
87573471bf0Spatrick else if (R->getName() == "IntrNoMerge")
87673471bf0Spatrick isNoMerge = true;
87773471bf0Spatrick else if (R->getName() == "IntrConvergent")
87873471bf0Spatrick isConvergent = true;
87973471bf0Spatrick else if (R->getName() == "IntrNoReturn")
88073471bf0Spatrick isNoReturn = true;
881*d415bd75Srobert else if (R->getName() == "IntrNoCallback")
882*d415bd75Srobert isNoCallback = true;
88373471bf0Spatrick else if (R->getName() == "IntrNoSync")
88473471bf0Spatrick isNoSync = true;
88573471bf0Spatrick else if (R->getName() == "IntrNoFree")
88673471bf0Spatrick isNoFree = true;
88773471bf0Spatrick else if (R->getName() == "IntrWillReturn")
88873471bf0Spatrick isWillReturn = !isNoReturn;
88973471bf0Spatrick else if (R->getName() == "IntrCold")
89073471bf0Spatrick isCold = true;
89173471bf0Spatrick else if (R->getName() == "IntrSpeculatable")
89273471bf0Spatrick isSpeculatable = true;
89373471bf0Spatrick else if (R->getName() == "IntrHasSideEffects")
89473471bf0Spatrick hasSideEffects = true;
89573471bf0Spatrick else if (R->isSubClassOf("NoCapture")) {
89673471bf0Spatrick unsigned ArgNo = R->getValueAsInt("ArgNo");
897*d415bd75Srobert addArgAttribute(ArgNo, NoCapture);
89873471bf0Spatrick } else if (R->isSubClassOf("NoAlias")) {
89973471bf0Spatrick unsigned ArgNo = R->getValueAsInt("ArgNo");
900*d415bd75Srobert addArgAttribute(ArgNo, NoAlias);
90173471bf0Spatrick } else if (R->isSubClassOf("NoUndef")) {
90273471bf0Spatrick unsigned ArgNo = R->getValueAsInt("ArgNo");
903*d415bd75Srobert addArgAttribute(ArgNo, NoUndef);
904*d415bd75Srobert } else if (R->isSubClassOf("NonNull")) {
905*d415bd75Srobert unsigned ArgNo = R->getValueAsInt("ArgNo");
906*d415bd75Srobert addArgAttribute(ArgNo, NonNull);
90773471bf0Spatrick } else if (R->isSubClassOf("Returned")) {
90873471bf0Spatrick unsigned ArgNo = R->getValueAsInt("ArgNo");
909*d415bd75Srobert addArgAttribute(ArgNo, Returned);
91073471bf0Spatrick } else if (R->isSubClassOf("ReadOnly")) {
91173471bf0Spatrick unsigned ArgNo = R->getValueAsInt("ArgNo");
912*d415bd75Srobert addArgAttribute(ArgNo, ReadOnly);
91373471bf0Spatrick } else if (R->isSubClassOf("WriteOnly")) {
91473471bf0Spatrick unsigned ArgNo = R->getValueAsInt("ArgNo");
915*d415bd75Srobert addArgAttribute(ArgNo, WriteOnly);
91673471bf0Spatrick } else if (R->isSubClassOf("ReadNone")) {
91773471bf0Spatrick unsigned ArgNo = R->getValueAsInt("ArgNo");
918*d415bd75Srobert addArgAttribute(ArgNo, ReadNone);
91973471bf0Spatrick } else if (R->isSubClassOf("ImmArg")) {
92073471bf0Spatrick unsigned ArgNo = R->getValueAsInt("ArgNo");
921*d415bd75Srobert addArgAttribute(ArgNo, ImmArg);
92273471bf0Spatrick } else if (R->isSubClassOf("Align")) {
92373471bf0Spatrick unsigned ArgNo = R->getValueAsInt("ArgNo");
92473471bf0Spatrick uint64_t Align = R->getValueAsInt("Align");
925*d415bd75Srobert addArgAttribute(ArgNo, Alignment, Align);
92673471bf0Spatrick } else
92773471bf0Spatrick llvm_unreachable("Unknown property!");
92873471bf0Spatrick }
92973471bf0Spatrick
isParamAPointer(unsigned ParamIdx) const93009467b48Spatrick bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
93109467b48Spatrick if (ParamIdx >= IS.ParamVTs.size())
93209467b48Spatrick return false;
93309467b48Spatrick MVT ParamType = MVT(IS.ParamVTs[ParamIdx]);
93409467b48Spatrick return ParamType == MVT::iPTR || ParamType == MVT::iPTRAny;
93509467b48Spatrick }
93609467b48Spatrick
isParamImmArg(unsigned ParamIdx) const93709467b48Spatrick bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const {
938097a140dSpatrick // Convert argument index to attribute index starting from `FirstArgIndex`.
939*d415bd75Srobert ++ParamIdx;
940*d415bd75Srobert if (ParamIdx >= ArgumentAttributes.size())
941*d415bd75Srobert return false;
942*d415bd75Srobert ArgAttribute Val{ImmArg, 0};
943*d415bd75Srobert return std::binary_search(ArgumentAttributes[ParamIdx].begin(),
944*d415bd75Srobert ArgumentAttributes[ParamIdx].end(), Val);
945*d415bd75Srobert }
946*d415bd75Srobert
addArgAttribute(unsigned Idx,ArgAttrKind AK,uint64_t V)947*d415bd75Srobert void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK,
948*d415bd75Srobert uint64_t V) {
949*d415bd75Srobert if (Idx >= ArgumentAttributes.size())
950*d415bd75Srobert ArgumentAttributes.resize(Idx + 1);
951*d415bd75Srobert ArgumentAttributes[Idx].emplace_back(AK, V);
95209467b48Spatrick }
953