1 1.1 joerg //===- MveEmitter.cpp - Generate arm_mve.h for use with clang -*- C++ -*-=====// 2 1.1 joerg // 3 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 joerg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 joerg // 7 1.1 joerg //===----------------------------------------------------------------------===// 8 1.1 joerg // 9 1.1 joerg // This set of linked tablegen backends is responsible for emitting the bits 10 1.1 joerg // and pieces that implement <arm_mve.h>, which is defined by the ACLE standard 11 1.1 joerg // and provides a set of types and functions for (more or less) direct access 12 1.1 joerg // to the MVE instruction set, including the scalar shifts as well as the 13 1.1 joerg // vector instructions. 14 1.1 joerg // 15 1.1 joerg // MVE's standard intrinsic functions are unusual in that they have a system of 16 1.1 joerg // polymorphism. For example, the function vaddq() can behave like vaddq_u16(), 17 1.1 joerg // vaddq_f32(), vaddq_s8(), etc., depending on the types of the vector 18 1.1 joerg // arguments you give it. 19 1.1 joerg // 20 1.1 joerg // This constrains the implementation strategies. The usual approach to making 21 1.1 joerg // the user-facing functions polymorphic would be to either use 22 1.1 joerg // __attribute__((overloadable)) to make a set of vaddq() functions that are 23 1.1 joerg // all inline wrappers on the underlying clang builtins, or to define a single 24 1.1 joerg // vaddq() macro which expands to an instance of _Generic. 25 1.1 joerg // 26 1.1 joerg // The inline-wrappers approach would work fine for most intrinsics, except for 27 1.1 joerg // the ones that take an argument required to be a compile-time constant, 28 1.1 joerg // because if you wrap an inline function around a call to a builtin, the 29 1.1 joerg // constant nature of the argument is not passed through. 30 1.1 joerg // 31 1.1 joerg // The _Generic approach can be made to work with enough effort, but it takes a 32 1.1 joerg // lot of machinery, because of the design feature of _Generic that even the 33 1.1 joerg // untaken branches are required to pass all front-end validity checks such as 34 1.1 joerg // type-correctness. You can work around that by nesting further _Generics all 35 1.1 joerg // over the place to coerce things to the right type in untaken branches, but 36 1.1 joerg // what you get out is complicated, hard to guarantee its correctness, and 37 1.1 joerg // worst of all, gives _completely unreadable_ error messages if the user gets 38 1.1 joerg // the types wrong for an intrinsic call. 39 1.1 joerg // 40 1.1 joerg // Therefore, my strategy is to introduce a new __attribute__ that allows a 41 1.1 joerg // function to be mapped to a clang builtin even though it doesn't have the 42 1.1 joerg // same name, and then declare all the user-facing MVE function names with that 43 1.1 joerg // attribute, mapping each one directly to the clang builtin. And the 44 1.1 joerg // polymorphic ones have __attribute__((overloadable)) as well. So once the 45 1.1 joerg // compiler has resolved the overload, it knows the internal builtin ID of the 46 1.1 joerg // selected function, and can check the immediate arguments against that; and 47 1.1 joerg // if the user gets the types wrong in a call to a polymorphic intrinsic, they 48 1.1 joerg // get a completely clear error message showing all the declarations of that 49 1.1 joerg // function in the header file and explaining why each one doesn't fit their 50 1.1 joerg // call. 51 1.1 joerg // 52 1.1 joerg // The downside of this is that if every clang builtin has to correspond 53 1.1 joerg // exactly to a user-facing ACLE intrinsic, then you can't save work in the 54 1.1 joerg // frontend by doing it in the header file: CGBuiltin.cpp has to do the entire 55 1.1 joerg // job of converting an ACLE intrinsic call into LLVM IR. So the Tablegen 56 1.1 joerg // description for an MVE intrinsic has to contain a full description of the 57 1.1 joerg // sequence of IRBuilder calls that clang will need to make. 58 1.1 joerg // 59 1.1 joerg //===----------------------------------------------------------------------===// 60 1.1 joerg 61 1.1 joerg #include "llvm/ADT/APInt.h" 62 1.1 joerg #include "llvm/ADT/StringRef.h" 63 1.1.1.2 joerg #include "llvm/ADT/StringSwitch.h" 64 1.1 joerg #include "llvm/Support/Casting.h" 65 1.1 joerg #include "llvm/Support/raw_ostream.h" 66 1.1 joerg #include "llvm/TableGen/Error.h" 67 1.1 joerg #include "llvm/TableGen/Record.h" 68 1.1.1.2 joerg #include "llvm/TableGen/StringToOffsetTable.h" 69 1.1 joerg #include <cassert> 70 1.1 joerg #include <cstddef> 71 1.1 joerg #include <cstdint> 72 1.1 joerg #include <list> 73 1.1 joerg #include <map> 74 1.1 joerg #include <memory> 75 1.1 joerg #include <set> 76 1.1 joerg #include <string> 77 1.1 joerg #include <vector> 78 1.1 joerg 79 1.1 joerg using namespace llvm; 80 1.1 joerg 81 1.1 joerg namespace { 82 1.1 joerg 83 1.1.1.2 joerg class EmitterBase; 84 1.1 joerg class Result; 85 1.1 joerg 86 1.1 joerg // ----------------------------------------------------------------------------- 87 1.1 joerg // A system of classes to represent all the types we'll need to deal with in 88 1.1 joerg // the prototypes of intrinsics. 89 1.1 joerg // 90 1.1 joerg // Query methods include finding out the C name of a type; the "LLVM name" in 91 1.1 joerg // the sense of a C++ code snippet that can be used in the codegen function; 92 1.1 joerg // the suffix that represents the type in the ACLE intrinsic naming scheme 93 1.1 joerg // (e.g. 's32' represents int32_t in intrinsics such as vaddq_s32); whether the 94 1.1 joerg // type is floating-point related (hence should be under #ifdef in the MVE 95 1.1 joerg // header so that it isn't included in integer-only MVE mode); and the type's 96 1.1 joerg // size in bits. Not all subtypes support all these queries. 97 1.1 joerg 98 1.1 joerg class Type { 99 1.1 joerg public: 100 1.1 joerg enum class TypeKind { 101 1.1 joerg // Void appears as a return type (for store intrinsics, which are pure 102 1.1 joerg // side-effect). It's also used as the parameter type in the Tablegen 103 1.1 joerg // when an intrinsic doesn't need to come in various suffixed forms like 104 1.1 joerg // vfooq_s8,vfooq_u16,vfooq_f32. 105 1.1 joerg Void, 106 1.1 joerg 107 1.1 joerg // Scalar is used for ordinary int and float types of all sizes. 108 1.1 joerg Scalar, 109 1.1 joerg 110 1.1 joerg // Vector is used for anything that occupies exactly one MVE vector 111 1.1 joerg // register, i.e. {uint,int,float}NxM_t. 112 1.1 joerg Vector, 113 1.1 joerg 114 1.1 joerg // MultiVector is used for the {uint,int,float}NxMxK_t types used by the 115 1.1 joerg // interleaving load/store intrinsics v{ld,st}{2,4}q. 116 1.1 joerg MultiVector, 117 1.1 joerg 118 1.1 joerg // Predicate is used by all the predicated intrinsics. Its C 119 1.1 joerg // representation is mve_pred16_t (which is just an alias for uint16_t). 120 1.1 joerg // But we give more detail here, by indicating that a given predicate 121 1.1 joerg // instruction is logically regarded as a vector of i1 containing the 122 1.1 joerg // same number of lanes as the input vector type. So our Predicate type 123 1.1 joerg // comes with a lane count, which we use to decide which kind of <n x i1> 124 1.1 joerg // we'll invoke the pred_i2v IR intrinsic to translate it into. 125 1.1 joerg Predicate, 126 1.1 joerg 127 1.1 joerg // Pointer is used for pointer types (obviously), and comes with a flag 128 1.1 joerg // indicating whether it's a pointer to a const or mutable instance of 129 1.1 joerg // the pointee type. 130 1.1 joerg Pointer, 131 1.1 joerg }; 132 1.1 joerg 133 1.1 joerg private: 134 1.1 joerg const TypeKind TKind; 135 1.1 joerg 136 1.1 joerg protected: 137 1.1 joerg Type(TypeKind K) : TKind(K) {} 138 1.1 joerg 139 1.1 joerg public: 140 1.1 joerg TypeKind typeKind() const { return TKind; } 141 1.1 joerg virtual ~Type() = default; 142 1.1 joerg virtual bool requiresFloat() const = 0; 143 1.1.1.2 joerg virtual bool requiresMVE() const = 0; 144 1.1 joerg virtual unsigned sizeInBits() const = 0; 145 1.1 joerg virtual std::string cName() const = 0; 146 1.1 joerg virtual std::string llvmName() const { 147 1.1 joerg PrintFatalError("no LLVM type name available for type " + cName()); 148 1.1 joerg } 149 1.1.1.2 joerg virtual std::string acleSuffix(std::string) const { 150 1.1 joerg PrintFatalError("no ACLE suffix available for this type"); 151 1.1 joerg } 152 1.1 joerg }; 153 1.1 joerg 154 1.1 joerg enum class ScalarTypeKind { SignedInt, UnsignedInt, Float }; 155 1.1 joerg inline std::string toLetter(ScalarTypeKind kind) { 156 1.1 joerg switch (kind) { 157 1.1 joerg case ScalarTypeKind::SignedInt: 158 1.1 joerg return "s"; 159 1.1 joerg case ScalarTypeKind::UnsignedInt: 160 1.1 joerg return "u"; 161 1.1 joerg case ScalarTypeKind::Float: 162 1.1 joerg return "f"; 163 1.1 joerg } 164 1.1 joerg llvm_unreachable("Unhandled ScalarTypeKind enum"); 165 1.1 joerg } 166 1.1 joerg inline std::string toCPrefix(ScalarTypeKind kind) { 167 1.1 joerg switch (kind) { 168 1.1 joerg case ScalarTypeKind::SignedInt: 169 1.1 joerg return "int"; 170 1.1 joerg case ScalarTypeKind::UnsignedInt: 171 1.1 joerg return "uint"; 172 1.1 joerg case ScalarTypeKind::Float: 173 1.1 joerg return "float"; 174 1.1 joerg } 175 1.1 joerg llvm_unreachable("Unhandled ScalarTypeKind enum"); 176 1.1 joerg } 177 1.1 joerg 178 1.1 joerg class VoidType : public Type { 179 1.1 joerg public: 180 1.1 joerg VoidType() : Type(TypeKind::Void) {} 181 1.1 joerg unsigned sizeInBits() const override { return 0; } 182 1.1 joerg bool requiresFloat() const override { return false; } 183 1.1.1.2 joerg bool requiresMVE() const override { return false; } 184 1.1 joerg std::string cName() const override { return "void"; } 185 1.1 joerg 186 1.1 joerg static bool classof(const Type *T) { return T->typeKind() == TypeKind::Void; } 187 1.1.1.2 joerg std::string acleSuffix(std::string) const override { return ""; } 188 1.1 joerg }; 189 1.1 joerg 190 1.1 joerg class PointerType : public Type { 191 1.1 joerg const Type *Pointee; 192 1.1 joerg bool Const; 193 1.1 joerg 194 1.1 joerg public: 195 1.1 joerg PointerType(const Type *Pointee, bool Const) 196 1.1 joerg : Type(TypeKind::Pointer), Pointee(Pointee), Const(Const) {} 197 1.1 joerg unsigned sizeInBits() const override { return 32; } 198 1.1 joerg bool requiresFloat() const override { return Pointee->requiresFloat(); } 199 1.1.1.2 joerg bool requiresMVE() const override { return Pointee->requiresMVE(); } 200 1.1 joerg std::string cName() const override { 201 1.1 joerg std::string Name = Pointee->cName(); 202 1.1 joerg 203 1.1 joerg // The syntax for a pointer in C is different when the pointee is 204 1.1 joerg // itself a pointer. The MVE intrinsics don't contain any double 205 1.1 joerg // pointers, so we don't need to worry about that wrinkle. 206 1.1 joerg assert(!isa<PointerType>(Pointee) && "Pointer to pointer not supported"); 207 1.1 joerg 208 1.1 joerg if (Const) 209 1.1 joerg Name = "const " + Name; 210 1.1 joerg return Name + " *"; 211 1.1 joerg } 212 1.1.1.2 joerg std::string llvmName() const override { 213 1.1.1.2 joerg return "llvm::PointerType::getUnqual(" + Pointee->llvmName() + ")"; 214 1.1.1.2 joerg } 215 1.1 joerg 216 1.1 joerg static bool classof(const Type *T) { 217 1.1 joerg return T->typeKind() == TypeKind::Pointer; 218 1.1 joerg } 219 1.1 joerg }; 220 1.1 joerg 221 1.1 joerg // Base class for all the types that have a name of the form 222 1.1 joerg // [prefix][numbers]_t, like int32_t, uint16x8_t, float32x4x2_t. 223 1.1 joerg // 224 1.1 joerg // For this sub-hierarchy we invent a cNameBase() method which returns the 225 1.1 joerg // whole name except for the trailing "_t", so that Vector and MultiVector can 226 1.1 joerg // append an extra "x2" or whatever to their element type's cNameBase(). Then 227 1.1 joerg // the main cName() query method puts "_t" on the end for the final type name. 228 1.1 joerg 229 1.1 joerg class CRegularNamedType : public Type { 230 1.1 joerg using Type::Type; 231 1.1 joerg virtual std::string cNameBase() const = 0; 232 1.1 joerg 233 1.1 joerg public: 234 1.1 joerg std::string cName() const override { return cNameBase() + "_t"; } 235 1.1 joerg }; 236 1.1 joerg 237 1.1 joerg class ScalarType : public CRegularNamedType { 238 1.1 joerg ScalarTypeKind Kind; 239 1.1 joerg unsigned Bits; 240 1.1.1.2 joerg std::string NameOverride; 241 1.1 joerg 242 1.1 joerg public: 243 1.1 joerg ScalarType(const Record *Record) : CRegularNamedType(TypeKind::Scalar) { 244 1.1 joerg Kind = StringSwitch<ScalarTypeKind>(Record->getValueAsString("kind")) 245 1.1 joerg .Case("s", ScalarTypeKind::SignedInt) 246 1.1 joerg .Case("u", ScalarTypeKind::UnsignedInt) 247 1.1 joerg .Case("f", ScalarTypeKind::Float); 248 1.1 joerg Bits = Record->getValueAsInt("size"); 249 1.1.1.2 joerg NameOverride = std::string(Record->getValueAsString("nameOverride")); 250 1.1 joerg } 251 1.1 joerg unsigned sizeInBits() const override { return Bits; } 252 1.1 joerg ScalarTypeKind kind() const { return Kind; } 253 1.1 joerg std::string suffix() const { return toLetter(Kind) + utostr(Bits); } 254 1.1 joerg std::string cNameBase() const override { 255 1.1 joerg return toCPrefix(Kind) + utostr(Bits); 256 1.1 joerg } 257 1.1.1.2 joerg std::string cName() const override { 258 1.1.1.2 joerg if (NameOverride.empty()) 259 1.1.1.2 joerg return CRegularNamedType::cName(); 260 1.1.1.2 joerg return NameOverride; 261 1.1.1.2 joerg } 262 1.1 joerg std::string llvmName() const override { 263 1.1 joerg if (Kind == ScalarTypeKind::Float) { 264 1.1 joerg if (Bits == 16) 265 1.1 joerg return "HalfTy"; 266 1.1 joerg if (Bits == 32) 267 1.1 joerg return "FloatTy"; 268 1.1 joerg if (Bits == 64) 269 1.1 joerg return "DoubleTy"; 270 1.1 joerg PrintFatalError("bad size for floating type"); 271 1.1 joerg } 272 1.1 joerg return "Int" + utostr(Bits) + "Ty"; 273 1.1 joerg } 274 1.1.1.2 joerg std::string acleSuffix(std::string overrideLetter) const override { 275 1.1.1.2 joerg return "_" + (overrideLetter.size() ? overrideLetter : toLetter(Kind)) 276 1.1.1.2 joerg + utostr(Bits); 277 1.1 joerg } 278 1.1 joerg bool isInteger() const { return Kind != ScalarTypeKind::Float; } 279 1.1 joerg bool requiresFloat() const override { return !isInteger(); } 280 1.1.1.2 joerg bool requiresMVE() const override { return false; } 281 1.1.1.2 joerg bool hasNonstandardName() const { return !NameOverride.empty(); } 282 1.1 joerg 283 1.1 joerg static bool classof(const Type *T) { 284 1.1 joerg return T->typeKind() == TypeKind::Scalar; 285 1.1 joerg } 286 1.1 joerg }; 287 1.1 joerg 288 1.1 joerg class VectorType : public CRegularNamedType { 289 1.1 joerg const ScalarType *Element; 290 1.1 joerg unsigned Lanes; 291 1.1 joerg 292 1.1 joerg public: 293 1.1.1.2 joerg VectorType(const ScalarType *Element, unsigned Lanes) 294 1.1.1.2 joerg : CRegularNamedType(TypeKind::Vector), Element(Element), Lanes(Lanes) {} 295 1.1.1.2 joerg unsigned sizeInBits() const override { return Lanes * Element->sizeInBits(); } 296 1.1 joerg unsigned lanes() const { return Lanes; } 297 1.1 joerg bool requiresFloat() const override { return Element->requiresFloat(); } 298 1.1.1.2 joerg bool requiresMVE() const override { return true; } 299 1.1 joerg std::string cNameBase() const override { 300 1.1 joerg return Element->cNameBase() + "x" + utostr(Lanes); 301 1.1 joerg } 302 1.1 joerg std::string llvmName() const override { 303 1.1.1.2 joerg return "llvm::FixedVectorType::get(" + Element->llvmName() + ", " + 304 1.1 joerg utostr(Lanes) + ")"; 305 1.1 joerg } 306 1.1 joerg 307 1.1 joerg static bool classof(const Type *T) { 308 1.1 joerg return T->typeKind() == TypeKind::Vector; 309 1.1 joerg } 310 1.1 joerg }; 311 1.1 joerg 312 1.1 joerg class MultiVectorType : public CRegularNamedType { 313 1.1 joerg const VectorType *Element; 314 1.1 joerg unsigned Registers; 315 1.1 joerg 316 1.1 joerg public: 317 1.1 joerg MultiVectorType(unsigned Registers, const VectorType *Element) 318 1.1 joerg : CRegularNamedType(TypeKind::MultiVector), Element(Element), 319 1.1 joerg Registers(Registers) {} 320 1.1 joerg unsigned sizeInBits() const override { 321 1.1 joerg return Registers * Element->sizeInBits(); 322 1.1 joerg } 323 1.1 joerg unsigned registers() const { return Registers; } 324 1.1 joerg bool requiresFloat() const override { return Element->requiresFloat(); } 325 1.1.1.2 joerg bool requiresMVE() const override { return true; } 326 1.1 joerg std::string cNameBase() const override { 327 1.1 joerg return Element->cNameBase() + "x" + utostr(Registers); 328 1.1 joerg } 329 1.1 joerg 330 1.1 joerg // MultiVectorType doesn't override llvmName, because we don't expect to do 331 1.1 joerg // automatic code generation for the MVE intrinsics that use it: the {vld2, 332 1.1 joerg // vld4, vst2, vst4} family are the only ones that use these types, so it was 333 1.1 joerg // easier to hand-write the codegen for dealing with these structs than to 334 1.1 joerg // build in lots of extra automatic machinery that would only be used once. 335 1.1 joerg 336 1.1 joerg static bool classof(const Type *T) { 337 1.1 joerg return T->typeKind() == TypeKind::MultiVector; 338 1.1 joerg } 339 1.1 joerg }; 340 1.1 joerg 341 1.1 joerg class PredicateType : public CRegularNamedType { 342 1.1 joerg unsigned Lanes; 343 1.1 joerg 344 1.1 joerg public: 345 1.1 joerg PredicateType(unsigned Lanes) 346 1.1 joerg : CRegularNamedType(TypeKind::Predicate), Lanes(Lanes) {} 347 1.1 joerg unsigned sizeInBits() const override { return 16; } 348 1.1 joerg std::string cNameBase() const override { return "mve_pred16"; } 349 1.1 joerg bool requiresFloat() const override { return false; }; 350 1.1.1.2 joerg bool requiresMVE() const override { return true; } 351 1.1 joerg std::string llvmName() const override { 352 1.1 joerg // Use <4 x i1> instead of <2 x i1> for two-lane vector types. See 353 1.1 joerg // the comment in llvm/lib/Target/ARM/ARMInstrMVE.td for further 354 1.1 joerg // explanation. 355 1.1 joerg unsigned ModifiedLanes = (Lanes == 2 ? 4 : Lanes); 356 1.1 joerg 357 1.1.1.2 joerg return "llvm::FixedVectorType::get(Builder.getInt1Ty(), " + 358 1.1 joerg utostr(ModifiedLanes) + ")"; 359 1.1 joerg } 360 1.1 joerg 361 1.1 joerg static bool classof(const Type *T) { 362 1.1 joerg return T->typeKind() == TypeKind::Predicate; 363 1.1 joerg } 364 1.1 joerg }; 365 1.1 joerg 366 1.1 joerg // ----------------------------------------------------------------------------- 367 1.1 joerg // Class to facilitate merging together the code generation for many intrinsics 368 1.1 joerg // by means of varying a few constant or type parameters. 369 1.1 joerg // 370 1.1 joerg // Most obviously, the intrinsics in a single parametrised family will have 371 1.1 joerg // code generation sequences that only differ in a type or two, e.g. vaddq_s8 372 1.1 joerg // and vaddq_u16 will look the same apart from putting a different vector type 373 1.1 joerg // in the call to CGM.getIntrinsic(). But also, completely different intrinsics 374 1.1 joerg // will often code-generate in the same way, with only a different choice of 375 1.1 joerg // _which_ IR intrinsic they lower to (e.g. vaddq_m_s8 and vmulq_m_s8), but 376 1.1 joerg // marshalling the arguments and return values of the IR intrinsic in exactly 377 1.1 joerg // the same way. And others might differ only in some other kind of constant, 378 1.1 joerg // such as a lane index. 379 1.1 joerg // 380 1.1 joerg // So, when we generate the IR-building code for all these intrinsics, we keep 381 1.1 joerg // track of every value that could possibly be pulled out of the code and 382 1.1 joerg // stored ahead of time in a local variable. Then we group together intrinsics 383 1.1 joerg // by textual equivalence of the code that would result if _all_ those 384 1.1 joerg // parameters were stored in local variables. That gives us maximal sets that 385 1.1 joerg // can be implemented by a single piece of IR-building code by changing 386 1.1 joerg // parameter values ahead of time. 387 1.1 joerg // 388 1.1 joerg // After we've done that, we do a second pass in which we only allocate _some_ 389 1.1 joerg // of the parameters into local variables, by tracking which ones have the same 390 1.1 joerg // values as each other (so that a single variable can be reused) and which 391 1.1 joerg // ones are the same across the whole set (so that no variable is needed at 392 1.1 joerg // all). 393 1.1 joerg // 394 1.1 joerg // Hence the class below. Its allocParam method is invoked during code 395 1.1 joerg // generation by every method of a Result subclass (see below) that wants to 396 1.1 joerg // give it the opportunity to pull something out into a switchable parameter. 397 1.1 joerg // It returns a variable name for the parameter, or (if it's being used in the 398 1.1 joerg // second pass once we've decided that some parameters don't need to be stored 399 1.1 joerg // in variables after all) it might just return the input expression unchanged. 400 1.1 joerg 401 1.1 joerg struct CodeGenParamAllocator { 402 1.1 joerg // Accumulated during code generation 403 1.1 joerg std::vector<std::string> *ParamTypes = nullptr; 404 1.1 joerg std::vector<std::string> *ParamValues = nullptr; 405 1.1 joerg 406 1.1 joerg // Provided ahead of time in pass 2, to indicate which parameters are being 407 1.1 joerg // assigned to what. This vector contains an entry for each call to 408 1.1 joerg // allocParam expected during code gen (which we counted up in pass 1), and 409 1.1 joerg // indicates the number of the parameter variable that should be returned, or 410 1.1 joerg // -1 if this call shouldn't allocate a parameter variable at all. 411 1.1 joerg // 412 1.1 joerg // We rely on the recursive code generation working identically in passes 1 413 1.1 joerg // and 2, so that the same list of calls to allocParam happen in the same 414 1.1 joerg // order. That guarantees that the parameter numbers recorded in pass 1 will 415 1.1.1.2 joerg // match the entries in this vector that store what EmitterBase::EmitBuiltinCG 416 1.1 joerg // decided to do about each one in pass 2. 417 1.1 joerg std::vector<int> *ParamNumberMap = nullptr; 418 1.1 joerg 419 1.1 joerg // Internally track how many things we've allocated 420 1.1 joerg unsigned nparams = 0; 421 1.1 joerg 422 1.1 joerg std::string allocParam(StringRef Type, StringRef Value) { 423 1.1 joerg unsigned ParamNumber; 424 1.1 joerg 425 1.1 joerg if (!ParamNumberMap) { 426 1.1 joerg // In pass 1, unconditionally assign a new parameter variable to every 427 1.1 joerg // value we're asked to process. 428 1.1 joerg ParamNumber = nparams++; 429 1.1 joerg } else { 430 1.1 joerg // In pass 2, consult the map provided by the caller to find out which 431 1.1 joerg // variable we should be keeping things in. 432 1.1 joerg int MapValue = (*ParamNumberMap)[nparams++]; 433 1.1 joerg if (MapValue < 0) 434 1.1.1.2 joerg return std::string(Value); 435 1.1 joerg ParamNumber = MapValue; 436 1.1 joerg } 437 1.1 joerg 438 1.1 joerg // If we've allocated a new parameter variable for the first time, store 439 1.1 joerg // its type and value to be retrieved after codegen. 440 1.1 joerg if (ParamTypes && ParamTypes->size() == ParamNumber) 441 1.1.1.2 joerg ParamTypes->push_back(std::string(Type)); 442 1.1 joerg if (ParamValues && ParamValues->size() == ParamNumber) 443 1.1.1.2 joerg ParamValues->push_back(std::string(Value)); 444 1.1 joerg 445 1.1 joerg // Unimaginative naming scheme for parameter variables. 446 1.1 joerg return "Param" + utostr(ParamNumber); 447 1.1 joerg } 448 1.1 joerg }; 449 1.1 joerg 450 1.1 joerg // ----------------------------------------------------------------------------- 451 1.1 joerg // System of classes that represent all the intermediate values used during 452 1.1 joerg // code-generation for an intrinsic. 453 1.1 joerg // 454 1.1 joerg // The base class 'Result' can represent a value of the LLVM type 'Value', or 455 1.1 joerg // sometimes 'Address' (for loads/stores, including an alignment requirement). 456 1.1 joerg // 457 1.1 joerg // In the case where the Tablegen provides a value in the codegen dag as a 458 1.1 joerg // plain integer literal, the Result object we construct here will be one that 459 1.1 joerg // returns true from hasIntegerConstantValue(). This allows the generated C++ 460 1.1 joerg // code to use the constant directly in contexts which can take a literal 461 1.1 joerg // integer, such as Builder.CreateExtractValue(thing, 1), without going to the 462 1.1 joerg // effort of calling llvm::ConstantInt::get() and then pulling the constant 463 1.1 joerg // back out of the resulting llvm:Value later. 464 1.1 joerg 465 1.1 joerg class Result { 466 1.1 joerg public: 467 1.1 joerg // Convenient shorthand for the pointer type we'll be using everywhere. 468 1.1 joerg using Ptr = std::shared_ptr<Result>; 469 1.1 joerg 470 1.1 joerg private: 471 1.1 joerg Ptr Predecessor; 472 1.1 joerg std::string VarName; 473 1.1 joerg bool VarNameUsed = false; 474 1.1 joerg unsigned Visited = 0; 475 1.1 joerg 476 1.1 joerg public: 477 1.1 joerg virtual ~Result() = default; 478 1.1 joerg using Scope = std::map<std::string, Ptr>; 479 1.1 joerg virtual void genCode(raw_ostream &OS, CodeGenParamAllocator &) const = 0; 480 1.1 joerg virtual bool hasIntegerConstantValue() const { return false; } 481 1.1 joerg virtual uint32_t integerConstantValue() const { return 0; } 482 1.1.1.2 joerg virtual bool hasIntegerValue() const { return false; } 483 1.1.1.2 joerg virtual std::string getIntegerValue(const std::string &) { 484 1.1.1.2 joerg llvm_unreachable("non-working Result::getIntegerValue called"); 485 1.1.1.2 joerg } 486 1.1 joerg virtual std::string typeName() const { return "Value *"; } 487 1.1 joerg 488 1.1 joerg // Mostly, when a code-generation operation has a dependency on prior 489 1.1 joerg // operations, it's because it uses the output values of those operations as 490 1.1 joerg // inputs. But there's one exception, which is the use of 'seq' in Tablegen 491 1.1 joerg // to indicate that operations have to be performed in sequence regardless of 492 1.1 joerg // whether they use each others' output values. 493 1.1 joerg // 494 1.1 joerg // So, the actual generation of code is done by depth-first search, using the 495 1.1 joerg // prerequisites() method to get a list of all the other Results that have to 496 1.1 joerg // be computed before this one. That method divides into the 'predecessor', 497 1.1 joerg // set by setPredecessor() while processing a 'seq' dag node, and the list 498 1.1 joerg // returned by 'morePrerequisites', which each subclass implements to return 499 1.1 joerg // a list of the Results it uses as input to whatever its own computation is 500 1.1 joerg // doing. 501 1.1 joerg 502 1.1 joerg virtual void morePrerequisites(std::vector<Ptr> &output) const {} 503 1.1 joerg std::vector<Ptr> prerequisites() const { 504 1.1 joerg std::vector<Ptr> ToRet; 505 1.1 joerg if (Predecessor) 506 1.1 joerg ToRet.push_back(Predecessor); 507 1.1 joerg morePrerequisites(ToRet); 508 1.1 joerg return ToRet; 509 1.1 joerg } 510 1.1 joerg 511 1.1 joerg void setPredecessor(Ptr p) { 512 1.1.1.2 joerg // If the user has nested one 'seq' node inside another, and this 513 1.1.1.2 joerg // method is called on the return value of the inner 'seq' (i.e. 514 1.1.1.2 joerg // the final item inside it), then we can't link _this_ node to p, 515 1.1.1.2 joerg // because it already has a predecessor. Instead, walk the chain 516 1.1.1.2 joerg // until we find the first item in the inner seq, and link that to 517 1.1.1.2 joerg // p, so that nesting seqs has the obvious effect of linking 518 1.1.1.2 joerg // everything together into one long sequential chain. 519 1.1.1.2 joerg Result *r = this; 520 1.1.1.2 joerg while (r->Predecessor) 521 1.1.1.2 joerg r = r->Predecessor.get(); 522 1.1.1.2 joerg r->Predecessor = p; 523 1.1 joerg } 524 1.1 joerg 525 1.1 joerg // Each Result will be assigned a variable name in the output code, but not 526 1.1 joerg // all those variable names will actually be used (e.g. the return value of 527 1.1 joerg // Builder.CreateStore has void type, so nobody will want to refer to it). To 528 1.1 joerg // prevent annoying compiler warnings, we track whether each Result's 529 1.1 joerg // variable name was ever actually mentioned in subsequent statements, so 530 1.1 joerg // that it can be left out of the final generated code. 531 1.1 joerg std::string varname() { 532 1.1 joerg VarNameUsed = true; 533 1.1 joerg return VarName; 534 1.1 joerg } 535 1.1.1.2 joerg void setVarname(const StringRef s) { VarName = std::string(s); } 536 1.1 joerg bool varnameUsed() const { return VarNameUsed; } 537 1.1 joerg 538 1.1.1.2 joerg // Emit code to generate this result as a Value *. 539 1.1.1.2 joerg virtual std::string asValue() { 540 1.1.1.2 joerg return varname(); 541 1.1.1.2 joerg } 542 1.1.1.2 joerg 543 1.1 joerg // Code generation happens in multiple passes. This method tracks whether a 544 1.1 joerg // Result has yet been visited in a given pass, without the need for a 545 1.1 joerg // tedious loop in between passes that goes through and resets a 'visited' 546 1.1 joerg // flag back to false: you just set Pass=1 the first time round, and Pass=2 547 1.1 joerg // the second time. 548 1.1 joerg bool needsVisiting(unsigned Pass) { 549 1.1 joerg bool ToRet = Visited < Pass; 550 1.1 joerg Visited = Pass; 551 1.1 joerg return ToRet; 552 1.1 joerg } 553 1.1 joerg }; 554 1.1 joerg 555 1.1 joerg // Result subclass that retrieves one of the arguments to the clang builtin 556 1.1 joerg // function. In cases where the argument has pointer type, we call 557 1.1 joerg // EmitPointerWithAlignment and store the result in a variable of type Address, 558 1.1 joerg // so that load and store IR nodes can know the right alignment. Otherwise, we 559 1.1 joerg // call EmitScalarExpr. 560 1.1 joerg // 561 1.1 joerg // There are aggregate parameters in the MVE intrinsics API, but we don't deal 562 1.1 joerg // with them in this Tablegen back end: they only arise in the vld2q/vld4q and 563 1.1 joerg // vst2q/vst4q family, which is few enough that we just write the code by hand 564 1.1 joerg // for those in CGBuiltin.cpp. 565 1.1 joerg class BuiltinArgResult : public Result { 566 1.1 joerg public: 567 1.1 joerg unsigned ArgNum; 568 1.1 joerg bool AddressType; 569 1.1.1.2 joerg bool Immediate; 570 1.1.1.2 joerg BuiltinArgResult(unsigned ArgNum, bool AddressType, bool Immediate) 571 1.1.1.2 joerg : ArgNum(ArgNum), AddressType(AddressType), Immediate(Immediate) {} 572 1.1 joerg void genCode(raw_ostream &OS, CodeGenParamAllocator &) const override { 573 1.1 joerg OS << (AddressType ? "EmitPointerWithAlignment" : "EmitScalarExpr") 574 1.1 joerg << "(E->getArg(" << ArgNum << "))"; 575 1.1 joerg } 576 1.1 joerg std::string typeName() const override { 577 1.1 joerg return AddressType ? "Address" : Result::typeName(); 578 1.1 joerg } 579 1.1.1.2 joerg // Emit code to generate this result as a Value *. 580 1.1.1.2 joerg std::string asValue() override { 581 1.1.1.2 joerg if (AddressType) 582 1.1.1.2 joerg return "(" + varname() + ".getPointer())"; 583 1.1.1.2 joerg return Result::asValue(); 584 1.1.1.2 joerg } 585 1.1.1.2 joerg bool hasIntegerValue() const override { return Immediate; } 586 1.1.1.2 joerg std::string getIntegerValue(const std::string &IntType) override { 587 1.1.1.2 joerg return "GetIntegerConstantValue<" + IntType + ">(E->getArg(" + 588 1.1.1.2 joerg utostr(ArgNum) + "), getContext())"; 589 1.1.1.2 joerg } 590 1.1 joerg }; 591 1.1 joerg 592 1.1 joerg // Result subclass for an integer literal appearing in Tablegen. This may need 593 1.1 joerg // to be turned into an llvm::Result by means of llvm::ConstantInt::get(), or 594 1.1 joerg // it may be used directly as an integer, depending on which IRBuilder method 595 1.1 joerg // it's being passed to. 596 1.1 joerg class IntLiteralResult : public Result { 597 1.1 joerg public: 598 1.1 joerg const ScalarType *IntegerType; 599 1.1 joerg uint32_t IntegerValue; 600 1.1 joerg IntLiteralResult(const ScalarType *IntegerType, uint32_t IntegerValue) 601 1.1 joerg : IntegerType(IntegerType), IntegerValue(IntegerValue) {} 602 1.1 joerg void genCode(raw_ostream &OS, 603 1.1 joerg CodeGenParamAllocator &ParamAlloc) const override { 604 1.1 joerg OS << "llvm::ConstantInt::get(" 605 1.1 joerg << ParamAlloc.allocParam("llvm::Type *", IntegerType->llvmName()) 606 1.1 joerg << ", "; 607 1.1 joerg OS << ParamAlloc.allocParam(IntegerType->cName(), utostr(IntegerValue)) 608 1.1 joerg << ")"; 609 1.1 joerg } 610 1.1 joerg bool hasIntegerConstantValue() const override { return true; } 611 1.1 joerg uint32_t integerConstantValue() const override { return IntegerValue; } 612 1.1 joerg }; 613 1.1 joerg 614 1.1 joerg // Result subclass representing a cast between different integer types. We use 615 1.1 joerg // our own ScalarType abstraction as the representation of the target type, 616 1.1 joerg // which gives both size and signedness. 617 1.1 joerg class IntCastResult : public Result { 618 1.1 joerg public: 619 1.1 joerg const ScalarType *IntegerType; 620 1.1 joerg Ptr V; 621 1.1 joerg IntCastResult(const ScalarType *IntegerType, Ptr V) 622 1.1 joerg : IntegerType(IntegerType), V(V) {} 623 1.1 joerg void genCode(raw_ostream &OS, 624 1.1 joerg CodeGenParamAllocator &ParamAlloc) const override { 625 1.1 joerg OS << "Builder.CreateIntCast(" << V->varname() << ", " 626 1.1 joerg << ParamAlloc.allocParam("llvm::Type *", IntegerType->llvmName()) << ", " 627 1.1 joerg << ParamAlloc.allocParam("bool", 628 1.1 joerg IntegerType->kind() == ScalarTypeKind::SignedInt 629 1.1 joerg ? "true" 630 1.1 joerg : "false") 631 1.1 joerg << ")"; 632 1.1 joerg } 633 1.1 joerg void morePrerequisites(std::vector<Ptr> &output) const override { 634 1.1 joerg output.push_back(V); 635 1.1 joerg } 636 1.1 joerg }; 637 1.1 joerg 638 1.1.1.2 joerg // Result subclass representing a cast between different pointer types. 639 1.1.1.2 joerg class PointerCastResult : public Result { 640 1.1.1.2 joerg public: 641 1.1.1.2 joerg const PointerType *PtrType; 642 1.1.1.2 joerg Ptr V; 643 1.1.1.2 joerg PointerCastResult(const PointerType *PtrType, Ptr V) 644 1.1.1.2 joerg : PtrType(PtrType), V(V) {} 645 1.1.1.2 joerg void genCode(raw_ostream &OS, 646 1.1.1.2 joerg CodeGenParamAllocator &ParamAlloc) const override { 647 1.1.1.2 joerg OS << "Builder.CreatePointerCast(" << V->asValue() << ", " 648 1.1.1.2 joerg << ParamAlloc.allocParam("llvm::Type *", PtrType->llvmName()) << ")"; 649 1.1.1.2 joerg } 650 1.1.1.2 joerg void morePrerequisites(std::vector<Ptr> &output) const override { 651 1.1.1.2 joerg output.push_back(V); 652 1.1.1.2 joerg } 653 1.1.1.2 joerg }; 654 1.1.1.2 joerg 655 1.1 joerg // Result subclass representing a call to an IRBuilder method. Each IRBuilder 656 1.1 joerg // method we want to use will have a Tablegen record giving the method name and 657 1.1 joerg // describing any important details of how to call it, such as whether a 658 1.1 joerg // particular argument should be an integer constant instead of an llvm::Value. 659 1.1 joerg class IRBuilderResult : public Result { 660 1.1 joerg public: 661 1.1.1.2 joerg StringRef CallPrefix; 662 1.1 joerg std::vector<Ptr> Args; 663 1.1 joerg std::set<unsigned> AddressArgs; 664 1.1.1.2 joerg std::map<unsigned, std::string> IntegerArgs; 665 1.1.1.2 joerg IRBuilderResult(StringRef CallPrefix, std::vector<Ptr> Args, 666 1.1 joerg std::set<unsigned> AddressArgs, 667 1.1.1.2 joerg std::map<unsigned, std::string> IntegerArgs) 668 1.1.1.2 joerg : CallPrefix(CallPrefix), Args(Args), AddressArgs(AddressArgs), 669 1.1.1.2 joerg IntegerArgs(IntegerArgs) {} 670 1.1 joerg void genCode(raw_ostream &OS, 671 1.1 joerg CodeGenParamAllocator &ParamAlloc) const override { 672 1.1.1.2 joerg OS << CallPrefix; 673 1.1 joerg const char *Sep = ""; 674 1.1 joerg for (unsigned i = 0, e = Args.size(); i < e; ++i) { 675 1.1 joerg Ptr Arg = Args[i]; 676 1.1.1.2 joerg auto it = IntegerArgs.find(i); 677 1.1.1.2 joerg 678 1.1.1.2 joerg OS << Sep; 679 1.1.1.2 joerg Sep = ", "; 680 1.1.1.2 joerg 681 1.1.1.2 joerg if (it != IntegerArgs.end()) { 682 1.1.1.2 joerg if (Arg->hasIntegerConstantValue()) 683 1.1.1.2 joerg OS << "static_cast<" << it->second << ">(" 684 1.1.1.2 joerg << ParamAlloc.allocParam(it->second, 685 1.1.1.2 joerg utostr(Arg->integerConstantValue())) 686 1.1.1.2 joerg << ")"; 687 1.1.1.2 joerg else if (Arg->hasIntegerValue()) 688 1.1.1.2 joerg OS << ParamAlloc.allocParam(it->second, 689 1.1.1.2 joerg Arg->getIntegerValue(it->second)); 690 1.1 joerg } else { 691 1.1.1.2 joerg OS << Arg->varname(); 692 1.1 joerg } 693 1.1 joerg } 694 1.1 joerg OS << ")"; 695 1.1 joerg } 696 1.1 joerg void morePrerequisites(std::vector<Ptr> &output) const override { 697 1.1 joerg for (unsigned i = 0, e = Args.size(); i < e; ++i) { 698 1.1 joerg Ptr Arg = Args[i]; 699 1.1.1.2 joerg if (IntegerArgs.find(i) != IntegerArgs.end()) 700 1.1 joerg continue; 701 1.1 joerg output.push_back(Arg); 702 1.1 joerg } 703 1.1 joerg } 704 1.1 joerg }; 705 1.1 joerg 706 1.1.1.2 joerg // Result subclass representing making an Address out of a Value. 707 1.1.1.2 joerg class AddressResult : public Result { 708 1.1.1.2 joerg public: 709 1.1.1.2 joerg Ptr Arg; 710 1.1.1.2 joerg unsigned Align; 711 1.1.1.2 joerg AddressResult(Ptr Arg, unsigned Align) : Arg(Arg), Align(Align) {} 712 1.1.1.2 joerg void genCode(raw_ostream &OS, 713 1.1.1.2 joerg CodeGenParamAllocator &ParamAlloc) const override { 714 1.1.1.2 joerg OS << "Address(" << Arg->varname() << ", CharUnits::fromQuantity(" 715 1.1.1.2 joerg << Align << "))"; 716 1.1.1.2 joerg } 717 1.1.1.2 joerg std::string typeName() const override { 718 1.1.1.2 joerg return "Address"; 719 1.1.1.2 joerg } 720 1.1.1.2 joerg void morePrerequisites(std::vector<Ptr> &output) const override { 721 1.1.1.2 joerg output.push_back(Arg); 722 1.1.1.2 joerg } 723 1.1.1.2 joerg }; 724 1.1.1.2 joerg 725 1.1 joerg // Result subclass representing a call to an IR intrinsic, which we first have 726 1.1 joerg // to look up using an Intrinsic::ID constant and an array of types. 727 1.1 joerg class IRIntrinsicResult : public Result { 728 1.1 joerg public: 729 1.1 joerg std::string IntrinsicID; 730 1.1 joerg std::vector<const Type *> ParamTypes; 731 1.1 joerg std::vector<Ptr> Args; 732 1.1 joerg IRIntrinsicResult(StringRef IntrinsicID, std::vector<const Type *> ParamTypes, 733 1.1 joerg std::vector<Ptr> Args) 734 1.1.1.2 joerg : IntrinsicID(std::string(IntrinsicID)), ParamTypes(ParamTypes), 735 1.1.1.2 joerg Args(Args) {} 736 1.1 joerg void genCode(raw_ostream &OS, 737 1.1 joerg CodeGenParamAllocator &ParamAlloc) const override { 738 1.1 joerg std::string IntNo = ParamAlloc.allocParam( 739 1.1.1.2 joerg "Intrinsic::ID", "Intrinsic::" + IntrinsicID); 740 1.1 joerg OS << "Builder.CreateCall(CGM.getIntrinsic(" << IntNo; 741 1.1 joerg if (!ParamTypes.empty()) { 742 1.1.1.2 joerg OS << ", {"; 743 1.1 joerg const char *Sep = ""; 744 1.1 joerg for (auto T : ParamTypes) { 745 1.1 joerg OS << Sep << ParamAlloc.allocParam("llvm::Type *", T->llvmName()); 746 1.1 joerg Sep = ", "; 747 1.1 joerg } 748 1.1 joerg OS << "}"; 749 1.1 joerg } 750 1.1.1.2 joerg OS << "), {"; 751 1.1 joerg const char *Sep = ""; 752 1.1 joerg for (auto Arg : Args) { 753 1.1.1.2 joerg OS << Sep << Arg->asValue(); 754 1.1 joerg Sep = ", "; 755 1.1 joerg } 756 1.1 joerg OS << "})"; 757 1.1 joerg } 758 1.1 joerg void morePrerequisites(std::vector<Ptr> &output) const override { 759 1.1 joerg output.insert(output.end(), Args.begin(), Args.end()); 760 1.1 joerg } 761 1.1 joerg }; 762 1.1 joerg 763 1.1.1.2 joerg // Result subclass that specifies a type, for use in IRBuilder operations such 764 1.1.1.2 joerg // as CreateBitCast that take a type argument. 765 1.1.1.2 joerg class TypeResult : public Result { 766 1.1.1.2 joerg public: 767 1.1.1.2 joerg const Type *T; 768 1.1.1.2 joerg TypeResult(const Type *T) : T(T) {} 769 1.1.1.2 joerg void genCode(raw_ostream &OS, CodeGenParamAllocator &) const override { 770 1.1.1.2 joerg OS << T->llvmName(); 771 1.1.1.2 joerg } 772 1.1.1.2 joerg std::string typeName() const override { 773 1.1.1.2 joerg return "llvm::Type *"; 774 1.1.1.2 joerg } 775 1.1.1.2 joerg }; 776 1.1.1.2 joerg 777 1.1 joerg // ----------------------------------------------------------------------------- 778 1.1 joerg // Class that describes a single ACLE intrinsic. 779 1.1 joerg // 780 1.1 joerg // A Tablegen record will typically describe more than one ACLE intrinsic, by 781 1.1 joerg // means of setting the 'list<Type> Params' field to a list of multiple 782 1.1 joerg // parameter types, so as to define vaddq_{s8,u8,...,f16,f32} all in one go. 783 1.1 joerg // We'll end up with one instance of ACLEIntrinsic for *each* parameter type, 784 1.1 joerg // rather than a single one for all of them. Hence, the constructor takes both 785 1.1 joerg // a Tablegen record and the current value of the parameter type. 786 1.1 joerg 787 1.1 joerg class ACLEIntrinsic { 788 1.1 joerg // Structure documenting that one of the intrinsic's arguments is required to 789 1.1 joerg // be a compile-time constant integer, and what constraints there are on its 790 1.1 joerg // value. Used when generating Sema checking code. 791 1.1 joerg struct ImmediateArg { 792 1.1 joerg enum class BoundsType { ExplicitRange, UInt }; 793 1.1 joerg BoundsType boundsType; 794 1.1 joerg int64_t i1, i2; 795 1.1 joerg StringRef ExtraCheckType, ExtraCheckArgs; 796 1.1 joerg const Type *ArgType; 797 1.1 joerg }; 798 1.1 joerg 799 1.1 joerg // For polymorphic intrinsics, FullName is the explicit name that uniquely 800 1.1 joerg // identifies this variant of the intrinsic, and ShortName is the name it 801 1.1 joerg // shares with at least one other intrinsic. 802 1.1 joerg std::string ShortName, FullName; 803 1.1 joerg 804 1.1.1.2 joerg // Name of the architecture extension, used in the Clang builtin name 805 1.1.1.2 joerg StringRef BuiltinExtension; 806 1.1.1.2 joerg 807 1.1.1.2 joerg // A very small number of intrinsics _only_ have a polymorphic 808 1.1.1.2 joerg // variant (vuninitializedq taking an unevaluated argument). 809 1.1.1.2 joerg bool PolymorphicOnly; 810 1.1.1.2 joerg 811 1.1.1.2 joerg // Another rarely-used flag indicating that the builtin doesn't 812 1.1.1.2 joerg // evaluate its argument(s) at all. 813 1.1.1.2 joerg bool NonEvaluating; 814 1.1.1.2 joerg 815 1.1.1.2 joerg // True if the intrinsic needs only the C header part (no codegen, semantic 816 1.1.1.2 joerg // checks, etc). Used for redeclaring MVE intrinsics in the arm_cde.h header. 817 1.1.1.2 joerg bool HeaderOnly; 818 1.1.1.2 joerg 819 1.1 joerg const Type *ReturnType; 820 1.1 joerg std::vector<const Type *> ArgTypes; 821 1.1 joerg std::map<unsigned, ImmediateArg> ImmediateArgs; 822 1.1 joerg Result::Ptr Code; 823 1.1 joerg 824 1.1 joerg std::map<std::string, std::string> CustomCodeGenArgs; 825 1.1 joerg 826 1.1 joerg // Recursive function that does the internals of code generation. 827 1.1 joerg void genCodeDfs(Result::Ptr V, std::list<Result::Ptr> &Used, 828 1.1 joerg unsigned Pass) const { 829 1.1 joerg if (!V->needsVisiting(Pass)) 830 1.1 joerg return; 831 1.1 joerg 832 1.1 joerg for (Result::Ptr W : V->prerequisites()) 833 1.1 joerg genCodeDfs(W, Used, Pass); 834 1.1 joerg 835 1.1 joerg Used.push_back(V); 836 1.1 joerg } 837 1.1 joerg 838 1.1 joerg public: 839 1.1 joerg const std::string &shortName() const { return ShortName; } 840 1.1 joerg const std::string &fullName() const { return FullName; } 841 1.1.1.2 joerg StringRef builtinExtension() const { return BuiltinExtension; } 842 1.1 joerg const Type *returnType() const { return ReturnType; } 843 1.1 joerg const std::vector<const Type *> &argTypes() const { return ArgTypes; } 844 1.1 joerg bool requiresFloat() const { 845 1.1 joerg if (ReturnType->requiresFloat()) 846 1.1 joerg return true; 847 1.1 joerg for (const Type *T : ArgTypes) 848 1.1 joerg if (T->requiresFloat()) 849 1.1 joerg return true; 850 1.1 joerg return false; 851 1.1 joerg } 852 1.1.1.2 joerg bool requiresMVE() const { 853 1.1.1.2 joerg return ReturnType->requiresMVE() || 854 1.1.1.2 joerg any_of(ArgTypes, [](const Type *T) { return T->requiresMVE(); }); 855 1.1.1.2 joerg } 856 1.1 joerg bool polymorphic() const { return ShortName != FullName; } 857 1.1.1.2 joerg bool polymorphicOnly() const { return PolymorphicOnly; } 858 1.1.1.2 joerg bool nonEvaluating() const { return NonEvaluating; } 859 1.1.1.2 joerg bool headerOnly() const { return HeaderOnly; } 860 1.1 joerg 861 1.1.1.2 joerg // External entry point for code generation, called from EmitterBase. 862 1.1 joerg void genCode(raw_ostream &OS, CodeGenParamAllocator &ParamAlloc, 863 1.1 joerg unsigned Pass) const { 864 1.1.1.2 joerg assert(!headerOnly() && "Called genCode for header-only intrinsic"); 865 1.1 joerg if (!hasCode()) { 866 1.1 joerg for (auto kv : CustomCodeGenArgs) 867 1.1 joerg OS << " " << kv.first << " = " << kv.second << ";\n"; 868 1.1 joerg OS << " break; // custom code gen\n"; 869 1.1 joerg return; 870 1.1 joerg } 871 1.1 joerg std::list<Result::Ptr> Used; 872 1.1 joerg genCodeDfs(Code, Used, Pass); 873 1.1 joerg 874 1.1 joerg unsigned varindex = 0; 875 1.1 joerg for (Result::Ptr V : Used) 876 1.1 joerg if (V->varnameUsed()) 877 1.1 joerg V->setVarname("Val" + utostr(varindex++)); 878 1.1 joerg 879 1.1 joerg for (Result::Ptr V : Used) { 880 1.1 joerg OS << " "; 881 1.1 joerg if (V == Used.back()) { 882 1.1 joerg assert(!V->varnameUsed()); 883 1.1 joerg OS << "return "; // FIXME: what if the top-level thing is void? 884 1.1 joerg } else if (V->varnameUsed()) { 885 1.1 joerg std::string Type = V->typeName(); 886 1.1 joerg OS << V->typeName(); 887 1.1 joerg if (!StringRef(Type).endswith("*")) 888 1.1 joerg OS << " "; 889 1.1 joerg OS << V->varname() << " = "; 890 1.1 joerg } 891 1.1 joerg V->genCode(OS, ParamAlloc); 892 1.1 joerg OS << ";\n"; 893 1.1 joerg } 894 1.1 joerg } 895 1.1 joerg bool hasCode() const { return Code != nullptr; } 896 1.1 joerg 897 1.1.1.2 joerg static std::string signedHexLiteral(const llvm::APInt &iOrig) { 898 1.1.1.2 joerg llvm::APInt i = iOrig.trunc(64); 899 1.1.1.2 joerg SmallString<40> s; 900 1.1.1.2 joerg i.toString(s, 16, true, true); 901 1.1.1.2 joerg return std::string(s.str()); 902 1.1.1.2 joerg } 903 1.1.1.2 joerg 904 1.1 joerg std::string genSema() const { 905 1.1.1.2 joerg assert(!headerOnly() && "Called genSema for header-only intrinsic"); 906 1.1 joerg std::vector<std::string> SemaChecks; 907 1.1 joerg 908 1.1 joerg for (const auto &kv : ImmediateArgs) { 909 1.1 joerg const ImmediateArg &IA = kv.second; 910 1.1 joerg 911 1.1 joerg llvm::APInt lo(128, 0), hi(128, 0); 912 1.1 joerg switch (IA.boundsType) { 913 1.1 joerg case ImmediateArg::BoundsType::ExplicitRange: 914 1.1 joerg lo = IA.i1; 915 1.1 joerg hi = IA.i2; 916 1.1 joerg break; 917 1.1 joerg case ImmediateArg::BoundsType::UInt: 918 1.1 joerg lo = 0; 919 1.1.1.2 joerg hi = llvm::APInt::getMaxValue(IA.i1).zext(128); 920 1.1 joerg break; 921 1.1 joerg } 922 1.1 joerg 923 1.1 joerg std::string Index = utostr(kv.first); 924 1.1 joerg 925 1.1.1.2 joerg // Emit a range check if the legal range of values for the 926 1.1.1.2 joerg // immediate is smaller than the _possible_ range of values for 927 1.1.1.2 joerg // its type. 928 1.1.1.2 joerg unsigned ArgTypeBits = IA.ArgType->sizeInBits(); 929 1.1.1.2 joerg llvm::APInt ArgTypeRange = llvm::APInt::getMaxValue(ArgTypeBits).zext(128); 930 1.1.1.2 joerg llvm::APInt ActualRange = (hi-lo).trunc(64).sext(128); 931 1.1.1.2 joerg if (ActualRange.ult(ArgTypeRange)) 932 1.1 joerg SemaChecks.push_back("SemaBuiltinConstantArgRange(TheCall, " + Index + 933 1.1.1.2 joerg ", " + signedHexLiteral(lo) + ", " + 934 1.1.1.2 joerg signedHexLiteral(hi) + ")"); 935 1.1 joerg 936 1.1 joerg if (!IA.ExtraCheckType.empty()) { 937 1.1 joerg std::string Suffix; 938 1.1.1.2 joerg if (!IA.ExtraCheckArgs.empty()) { 939 1.1.1.2 joerg std::string tmp; 940 1.1.1.2 joerg StringRef Arg = IA.ExtraCheckArgs; 941 1.1.1.2 joerg if (Arg == "!lanesize") { 942 1.1.1.2 joerg tmp = utostr(IA.ArgType->sizeInBits()); 943 1.1.1.2 joerg Arg = tmp; 944 1.1.1.2 joerg } 945 1.1.1.2 joerg Suffix = (Twine(", ") + Arg).str(); 946 1.1.1.2 joerg } 947 1.1 joerg SemaChecks.push_back((Twine("SemaBuiltinConstantArg") + 948 1.1 joerg IA.ExtraCheckType + "(TheCall, " + Index + 949 1.1 joerg Suffix + ")") 950 1.1 joerg .str()); 951 1.1 joerg } 952 1.1.1.2 joerg 953 1.1.1.2 joerg assert(!SemaChecks.empty()); 954 1.1 joerg } 955 1.1 joerg if (SemaChecks.empty()) 956 1.1 joerg return ""; 957 1.1.1.2 joerg return join(std::begin(SemaChecks), std::end(SemaChecks), 958 1.1.1.2 joerg " ||\n ") + 959 1.1.1.2 joerg ";\n"; 960 1.1 joerg } 961 1.1 joerg 962 1.1.1.2 joerg ACLEIntrinsic(EmitterBase &ME, Record *R, const Type *Param); 963 1.1 joerg }; 964 1.1 joerg 965 1.1 joerg // ----------------------------------------------------------------------------- 966 1.1 joerg // The top-level class that holds all the state from analyzing the entire 967 1.1 joerg // Tablegen input. 968 1.1 joerg 969 1.1.1.2 joerg class EmitterBase { 970 1.1.1.2 joerg protected: 971 1.1.1.2 joerg // EmitterBase holds a collection of all the types we've instantiated. 972 1.1 joerg VoidType Void; 973 1.1 joerg std::map<std::string, std::unique_ptr<ScalarType>> ScalarTypes; 974 1.1.1.2 joerg std::map<std::tuple<ScalarTypeKind, unsigned, unsigned>, 975 1.1.1.2 joerg std::unique_ptr<VectorType>> 976 1.1 joerg VectorTypes; 977 1.1 joerg std::map<std::pair<std::string, unsigned>, std::unique_ptr<MultiVectorType>> 978 1.1 joerg MultiVectorTypes; 979 1.1 joerg std::map<unsigned, std::unique_ptr<PredicateType>> PredicateTypes; 980 1.1 joerg std::map<std::string, std::unique_ptr<PointerType>> PointerTypes; 981 1.1 joerg 982 1.1 joerg // And all the ACLEIntrinsic instances we've created. 983 1.1 joerg std::map<std::string, std::unique_ptr<ACLEIntrinsic>> ACLEIntrinsics; 984 1.1 joerg 985 1.1 joerg public: 986 1.1 joerg // Methods to create a Type object, or return the right existing one from the 987 1.1 joerg // maps stored in this object. 988 1.1 joerg const VoidType *getVoidType() { return &Void; } 989 1.1 joerg const ScalarType *getScalarType(StringRef Name) { 990 1.1.1.2 joerg return ScalarTypes[std::string(Name)].get(); 991 1.1 joerg } 992 1.1 joerg const ScalarType *getScalarType(Record *R) { 993 1.1 joerg return getScalarType(R->getName()); 994 1.1 joerg } 995 1.1.1.2 joerg const VectorType *getVectorType(const ScalarType *ST, unsigned Lanes) { 996 1.1.1.2 joerg std::tuple<ScalarTypeKind, unsigned, unsigned> key(ST->kind(), 997 1.1.1.2 joerg ST->sizeInBits(), Lanes); 998 1.1 joerg if (VectorTypes.find(key) == VectorTypes.end()) 999 1.1.1.2 joerg VectorTypes[key] = std::make_unique<VectorType>(ST, Lanes); 1000 1.1 joerg return VectorTypes[key].get(); 1001 1.1 joerg } 1002 1.1.1.2 joerg const VectorType *getVectorType(const ScalarType *ST) { 1003 1.1.1.2 joerg return getVectorType(ST, 128 / ST->sizeInBits()); 1004 1.1.1.2 joerg } 1005 1.1 joerg const MultiVectorType *getMultiVectorType(unsigned Registers, 1006 1.1 joerg const VectorType *VT) { 1007 1.1 joerg std::pair<std::string, unsigned> key(VT->cNameBase(), Registers); 1008 1.1 joerg if (MultiVectorTypes.find(key) == MultiVectorTypes.end()) 1009 1.1 joerg MultiVectorTypes[key] = std::make_unique<MultiVectorType>(Registers, VT); 1010 1.1 joerg return MultiVectorTypes[key].get(); 1011 1.1 joerg } 1012 1.1 joerg const PredicateType *getPredicateType(unsigned Lanes) { 1013 1.1 joerg unsigned key = Lanes; 1014 1.1 joerg if (PredicateTypes.find(key) == PredicateTypes.end()) 1015 1.1 joerg PredicateTypes[key] = std::make_unique<PredicateType>(Lanes); 1016 1.1 joerg return PredicateTypes[key].get(); 1017 1.1 joerg } 1018 1.1 joerg const PointerType *getPointerType(const Type *T, bool Const) { 1019 1.1 joerg PointerType PT(T, Const); 1020 1.1 joerg std::string key = PT.cName(); 1021 1.1 joerg if (PointerTypes.find(key) == PointerTypes.end()) 1022 1.1 joerg PointerTypes[key] = std::make_unique<PointerType>(PT); 1023 1.1 joerg return PointerTypes[key].get(); 1024 1.1 joerg } 1025 1.1 joerg 1026 1.1 joerg // Methods to construct a type from various pieces of Tablegen. These are 1027 1.1 joerg // always called in the context of setting up a particular ACLEIntrinsic, so 1028 1.1 joerg // there's always an ambient parameter type (because we're iterating through 1029 1.1 joerg // the Params list in the Tablegen record for the intrinsic), which is used 1030 1.1 joerg // to expand Tablegen classes like 'Vector' which mean something different in 1031 1.1 joerg // each member of a parametric family. 1032 1.1 joerg const Type *getType(Record *R, const Type *Param); 1033 1.1 joerg const Type *getType(DagInit *D, const Type *Param); 1034 1.1 joerg const Type *getType(Init *I, const Type *Param); 1035 1.1 joerg 1036 1.1 joerg // Functions that translate the Tablegen representation of an intrinsic's 1037 1.1 joerg // code generation into a collection of Value objects (which will then be 1038 1.1 joerg // reprocessed to read out the actual C++ code included by CGBuiltin.cpp). 1039 1.1 joerg Result::Ptr getCodeForDag(DagInit *D, const Result::Scope &Scope, 1040 1.1 joerg const Type *Param); 1041 1.1 joerg Result::Ptr getCodeForDagArg(DagInit *D, unsigned ArgNum, 1042 1.1 joerg const Result::Scope &Scope, const Type *Param); 1043 1.1.1.2 joerg Result::Ptr getCodeForArg(unsigned ArgNum, const Type *ArgType, bool Promote, 1044 1.1.1.2 joerg bool Immediate); 1045 1.1.1.2 joerg 1046 1.1.1.2 joerg void GroupSemaChecks(std::map<std::string, std::set<std::string>> &Checks); 1047 1.1 joerg 1048 1.1 joerg // Constructor and top-level functions. 1049 1.1 joerg 1050 1.1.1.2 joerg EmitterBase(RecordKeeper &Records); 1051 1.1.1.2 joerg virtual ~EmitterBase() = default; 1052 1.1 joerg 1053 1.1.1.2 joerg virtual void EmitHeader(raw_ostream &OS) = 0; 1054 1.1.1.2 joerg virtual void EmitBuiltinDef(raw_ostream &OS) = 0; 1055 1.1.1.2 joerg virtual void EmitBuiltinSema(raw_ostream &OS) = 0; 1056 1.1 joerg void EmitBuiltinCG(raw_ostream &OS); 1057 1.1 joerg void EmitBuiltinAliases(raw_ostream &OS); 1058 1.1 joerg }; 1059 1.1 joerg 1060 1.1.1.2 joerg const Type *EmitterBase::getType(Init *I, const Type *Param) { 1061 1.1 joerg if (auto Dag = dyn_cast<DagInit>(I)) 1062 1.1 joerg return getType(Dag, Param); 1063 1.1 joerg if (auto Def = dyn_cast<DefInit>(I)) 1064 1.1 joerg return getType(Def->getDef(), Param); 1065 1.1 joerg 1066 1.1 joerg PrintFatalError("Could not convert this value into a type"); 1067 1.1 joerg } 1068 1.1 joerg 1069 1.1.1.2 joerg const Type *EmitterBase::getType(Record *R, const Type *Param) { 1070 1.1.1.2 joerg // Pass to a subfield of any wrapper records. We don't expect more than one 1071 1.1.1.2 joerg // of these: immediate operands are used as plain numbers rather than as 1072 1.1.1.2 joerg // llvm::Value, so it's meaningless to promote their type anyway. 1073 1.1 joerg if (R->isSubClassOf("Immediate")) 1074 1.1.1.2 joerg R = R->getValueAsDef("type"); 1075 1.1.1.2 joerg else if (R->isSubClassOf("unpromoted")) 1076 1.1.1.2 joerg R = R->getValueAsDef("underlying_type"); 1077 1.1 joerg 1078 1.1 joerg if (R->getName() == "Void") 1079 1.1 joerg return getVoidType(); 1080 1.1 joerg if (R->isSubClassOf("PrimitiveType")) 1081 1.1 joerg return getScalarType(R); 1082 1.1 joerg if (R->isSubClassOf("ComplexType")) 1083 1.1 joerg return getType(R->getValueAsDag("spec"), Param); 1084 1.1 joerg 1085 1.1 joerg PrintFatalError(R->getLoc(), "Could not convert this record into a type"); 1086 1.1 joerg } 1087 1.1 joerg 1088 1.1.1.2 joerg const Type *EmitterBase::getType(DagInit *D, const Type *Param) { 1089 1.1 joerg // The meat of the getType system: types in the Tablegen are represented by a 1090 1.1 joerg // dag whose operators select sub-cases of this function. 1091 1.1 joerg 1092 1.1 joerg Record *Op = cast<DefInit>(D->getOperator())->getDef(); 1093 1.1 joerg if (!Op->isSubClassOf("ComplexTypeOp")) 1094 1.1 joerg PrintFatalError( 1095 1.1 joerg "Expected ComplexTypeOp as dag operator in type expression"); 1096 1.1 joerg 1097 1.1 joerg if (Op->getName() == "CTO_Parameter") { 1098 1.1 joerg if (isa<VoidType>(Param)) 1099 1.1 joerg PrintFatalError("Parametric type in unparametrised context"); 1100 1.1 joerg return Param; 1101 1.1 joerg } 1102 1.1 joerg 1103 1.1 joerg if (Op->getName() == "CTO_Vec") { 1104 1.1 joerg const Type *Element = getType(D->getArg(0), Param); 1105 1.1.1.2 joerg if (D->getNumArgs() == 1) { 1106 1.1.1.2 joerg return getVectorType(cast<ScalarType>(Element)); 1107 1.1.1.2 joerg } else { 1108 1.1.1.2 joerg const Type *ExistingVector = getType(D->getArg(1), Param); 1109 1.1.1.2 joerg return getVectorType(cast<ScalarType>(Element), 1110 1.1.1.2 joerg cast<VectorType>(ExistingVector)->lanes()); 1111 1.1.1.2 joerg } 1112 1.1 joerg } 1113 1.1 joerg 1114 1.1 joerg if (Op->getName() == "CTO_Pred") { 1115 1.1 joerg const Type *Element = getType(D->getArg(0), Param); 1116 1.1 joerg return getPredicateType(128 / Element->sizeInBits()); 1117 1.1 joerg } 1118 1.1 joerg 1119 1.1 joerg if (Op->isSubClassOf("CTO_Tuple")) { 1120 1.1 joerg unsigned Registers = Op->getValueAsInt("n"); 1121 1.1 joerg const Type *Element = getType(D->getArg(0), Param); 1122 1.1 joerg return getMultiVectorType(Registers, cast<VectorType>(Element)); 1123 1.1 joerg } 1124 1.1 joerg 1125 1.1 joerg if (Op->isSubClassOf("CTO_Pointer")) { 1126 1.1 joerg const Type *Pointee = getType(D->getArg(0), Param); 1127 1.1 joerg return getPointerType(Pointee, Op->getValueAsBit("const")); 1128 1.1 joerg } 1129 1.1 joerg 1130 1.1.1.2 joerg if (Op->getName() == "CTO_CopyKind") { 1131 1.1.1.2 joerg const ScalarType *STSize = cast<ScalarType>(getType(D->getArg(0), Param)); 1132 1.1.1.2 joerg const ScalarType *STKind = cast<ScalarType>(getType(D->getArg(1), Param)); 1133 1.1.1.2 joerg for (const auto &kv : ScalarTypes) { 1134 1.1.1.2 joerg const ScalarType *RT = kv.second.get(); 1135 1.1.1.2 joerg if (RT->kind() == STKind->kind() && RT->sizeInBits() == STSize->sizeInBits()) 1136 1.1.1.2 joerg return RT; 1137 1.1.1.2 joerg } 1138 1.1.1.2 joerg PrintFatalError("Cannot find a type to satisfy CopyKind"); 1139 1.1.1.2 joerg } 1140 1.1.1.2 joerg 1141 1.1.1.2 joerg if (Op->isSubClassOf("CTO_ScaleSize")) { 1142 1.1.1.2 joerg const ScalarType *STKind = cast<ScalarType>(getType(D->getArg(0), Param)); 1143 1.1.1.2 joerg int Num = Op->getValueAsInt("num"), Denom = Op->getValueAsInt("denom"); 1144 1.1.1.2 joerg unsigned DesiredSize = STKind->sizeInBits() * Num / Denom; 1145 1.1 joerg for (const auto &kv : ScalarTypes) { 1146 1.1 joerg const ScalarType *RT = kv.second.get(); 1147 1.1.1.2 joerg if (RT->kind() == STKind->kind() && RT->sizeInBits() == DesiredSize) 1148 1.1 joerg return RT; 1149 1.1 joerg } 1150 1.1.1.2 joerg PrintFatalError("Cannot find a type to satisfy ScaleSize"); 1151 1.1 joerg } 1152 1.1 joerg 1153 1.1 joerg PrintFatalError("Bad operator in type dag expression"); 1154 1.1 joerg } 1155 1.1 joerg 1156 1.1.1.2 joerg Result::Ptr EmitterBase::getCodeForDag(DagInit *D, const Result::Scope &Scope, 1157 1.1.1.2 joerg const Type *Param) { 1158 1.1 joerg Record *Op = cast<DefInit>(D->getOperator())->getDef(); 1159 1.1 joerg 1160 1.1 joerg if (Op->getName() == "seq") { 1161 1.1 joerg Result::Scope SubScope = Scope; 1162 1.1 joerg Result::Ptr PrevV = nullptr; 1163 1.1 joerg for (unsigned i = 0, e = D->getNumArgs(); i < e; ++i) { 1164 1.1 joerg // We don't use getCodeForDagArg here, because the argument name 1165 1.1 joerg // has different semantics in a seq 1166 1.1 joerg Result::Ptr V = 1167 1.1 joerg getCodeForDag(cast<DagInit>(D->getArg(i)), SubScope, Param); 1168 1.1 joerg StringRef ArgName = D->getArgNameStr(i); 1169 1.1 joerg if (!ArgName.empty()) 1170 1.1.1.2 joerg SubScope[std::string(ArgName)] = V; 1171 1.1 joerg if (PrevV) 1172 1.1 joerg V->setPredecessor(PrevV); 1173 1.1 joerg PrevV = V; 1174 1.1 joerg } 1175 1.1 joerg return PrevV; 1176 1.1 joerg } else if (Op->isSubClassOf("Type")) { 1177 1.1 joerg if (D->getNumArgs() != 1) 1178 1.1 joerg PrintFatalError("Type casts should have exactly one argument"); 1179 1.1 joerg const Type *CastType = getType(Op, Param); 1180 1.1 joerg Result::Ptr Arg = getCodeForDagArg(D, 0, Scope, Param); 1181 1.1 joerg if (const auto *ST = dyn_cast<ScalarType>(CastType)) { 1182 1.1 joerg if (!ST->requiresFloat()) { 1183 1.1 joerg if (Arg->hasIntegerConstantValue()) 1184 1.1 joerg return std::make_shared<IntLiteralResult>( 1185 1.1 joerg ST, Arg->integerConstantValue()); 1186 1.1 joerg else 1187 1.1 joerg return std::make_shared<IntCastResult>(ST, Arg); 1188 1.1 joerg } 1189 1.1.1.2 joerg } else if (const auto *PT = dyn_cast<PointerType>(CastType)) { 1190 1.1.1.2 joerg return std::make_shared<PointerCastResult>(PT, Arg); 1191 1.1 joerg } 1192 1.1 joerg PrintFatalError("Unsupported type cast"); 1193 1.1.1.2 joerg } else if (Op->getName() == "address") { 1194 1.1.1.2 joerg if (D->getNumArgs() != 2) 1195 1.1.1.2 joerg PrintFatalError("'address' should have two arguments"); 1196 1.1.1.2 joerg Result::Ptr Arg = getCodeForDagArg(D, 0, Scope, Param); 1197 1.1.1.2 joerg unsigned Alignment; 1198 1.1.1.2 joerg if (auto *II = dyn_cast<IntInit>(D->getArg(1))) { 1199 1.1.1.2 joerg Alignment = II->getValue(); 1200 1.1.1.2 joerg } else { 1201 1.1.1.2 joerg PrintFatalError("'address' alignment argument should be an integer"); 1202 1.1.1.2 joerg } 1203 1.1.1.2 joerg return std::make_shared<AddressResult>(Arg, Alignment); 1204 1.1.1.2 joerg } else if (Op->getName() == "unsignedflag") { 1205 1.1.1.2 joerg if (D->getNumArgs() != 1) 1206 1.1.1.2 joerg PrintFatalError("unsignedflag should have exactly one argument"); 1207 1.1.1.2 joerg Record *TypeRec = cast<DefInit>(D->getArg(0))->getDef(); 1208 1.1.1.2 joerg if (!TypeRec->isSubClassOf("Type")) 1209 1.1.1.2 joerg PrintFatalError("unsignedflag's argument should be a type"); 1210 1.1.1.2 joerg if (const auto *ST = dyn_cast<ScalarType>(getType(TypeRec, Param))) { 1211 1.1.1.2 joerg return std::make_shared<IntLiteralResult>( 1212 1.1.1.2 joerg getScalarType("u32"), ST->kind() == ScalarTypeKind::UnsignedInt); 1213 1.1.1.2 joerg } else { 1214 1.1.1.2 joerg PrintFatalError("unsignedflag's argument should be a scalar type"); 1215 1.1.1.2 joerg } 1216 1.1.1.2 joerg } else if (Op->getName() == "bitsize") { 1217 1.1.1.2 joerg if (D->getNumArgs() != 1) 1218 1.1.1.2 joerg PrintFatalError("bitsize should have exactly one argument"); 1219 1.1.1.2 joerg Record *TypeRec = cast<DefInit>(D->getArg(0))->getDef(); 1220 1.1.1.2 joerg if (!TypeRec->isSubClassOf("Type")) 1221 1.1.1.2 joerg PrintFatalError("bitsize's argument should be a type"); 1222 1.1.1.2 joerg if (const auto *ST = dyn_cast<ScalarType>(getType(TypeRec, Param))) { 1223 1.1.1.2 joerg return std::make_shared<IntLiteralResult>(getScalarType("u32"), 1224 1.1.1.2 joerg ST->sizeInBits()); 1225 1.1.1.2 joerg } else { 1226 1.1.1.2 joerg PrintFatalError("bitsize's argument should be a scalar type"); 1227 1.1.1.2 joerg } 1228 1.1 joerg } else { 1229 1.1 joerg std::vector<Result::Ptr> Args; 1230 1.1 joerg for (unsigned i = 0, e = D->getNumArgs(); i < e; ++i) 1231 1.1 joerg Args.push_back(getCodeForDagArg(D, i, Scope, Param)); 1232 1.1.1.2 joerg if (Op->isSubClassOf("IRBuilderBase")) { 1233 1.1 joerg std::set<unsigned> AddressArgs; 1234 1.1.1.2 joerg std::map<unsigned, std::string> IntegerArgs; 1235 1.1.1.2 joerg for (Record *sp : Op->getValueAsListOfDefs("special_params")) { 1236 1.1.1.2 joerg unsigned Index = sp->getValueAsInt("index"); 1237 1.1.1.2 joerg if (sp->isSubClassOf("IRBuilderAddrParam")) { 1238 1.1.1.2 joerg AddressArgs.insert(Index); 1239 1.1.1.2 joerg } else if (sp->isSubClassOf("IRBuilderIntParam")) { 1240 1.1.1.2 joerg IntegerArgs[Index] = std::string(sp->getValueAsString("type")); 1241 1.1.1.2 joerg } 1242 1.1.1.2 joerg } 1243 1.1.1.2 joerg return std::make_shared<IRBuilderResult>(Op->getValueAsString("prefix"), 1244 1.1.1.2 joerg Args, AddressArgs, IntegerArgs); 1245 1.1.1.2 joerg } else if (Op->isSubClassOf("IRIntBase")) { 1246 1.1 joerg std::vector<const Type *> ParamTypes; 1247 1.1 joerg for (Record *RParam : Op->getValueAsListOfDefs("params")) 1248 1.1 joerg ParamTypes.push_back(getType(RParam, Param)); 1249 1.1.1.2 joerg std::string IntName = std::string(Op->getValueAsString("intname")); 1250 1.1 joerg if (Op->getValueAsBit("appendKind")) 1251 1.1 joerg IntName += "_" + toLetter(cast<ScalarType>(Param)->kind()); 1252 1.1 joerg return std::make_shared<IRIntrinsicResult>(IntName, ParamTypes, Args); 1253 1.1 joerg } else { 1254 1.1 joerg PrintFatalError("Unsupported dag node " + Op->getName()); 1255 1.1 joerg } 1256 1.1 joerg } 1257 1.1 joerg } 1258 1.1 joerg 1259 1.1.1.2 joerg Result::Ptr EmitterBase::getCodeForDagArg(DagInit *D, unsigned ArgNum, 1260 1.1.1.2 joerg const Result::Scope &Scope, 1261 1.1.1.2 joerg const Type *Param) { 1262 1.1 joerg Init *Arg = D->getArg(ArgNum); 1263 1.1 joerg StringRef Name = D->getArgNameStr(ArgNum); 1264 1.1 joerg 1265 1.1 joerg if (!Name.empty()) { 1266 1.1 joerg if (!isa<UnsetInit>(Arg)) 1267 1.1 joerg PrintFatalError( 1268 1.1 joerg "dag operator argument should not have both a value and a name"); 1269 1.1.1.2 joerg auto it = Scope.find(std::string(Name)); 1270 1.1 joerg if (it == Scope.end()) 1271 1.1 joerg PrintFatalError("unrecognized variable name '" + Name + "'"); 1272 1.1 joerg return it->second; 1273 1.1 joerg } 1274 1.1 joerg 1275 1.1.1.2 joerg // Sometimes the Arg is a bit. Prior to multiclass template argument 1276 1.1.1.2 joerg // checking, integers would sneak through the bit declaration, 1277 1.1.1.2 joerg // but now they really are bits. 1278 1.1.1.2 joerg if (auto *BI = dyn_cast<BitInit>(Arg)) 1279 1.1.1.2 joerg return std::make_shared<IntLiteralResult>(getScalarType("u32"), 1280 1.1.1.2 joerg BI->getValue()); 1281 1.1.1.2 joerg 1282 1.1 joerg if (auto *II = dyn_cast<IntInit>(Arg)) 1283 1.1 joerg return std::make_shared<IntLiteralResult>(getScalarType("u32"), 1284 1.1 joerg II->getValue()); 1285 1.1 joerg 1286 1.1 joerg if (auto *DI = dyn_cast<DagInit>(Arg)) 1287 1.1 joerg return getCodeForDag(DI, Scope, Param); 1288 1.1 joerg 1289 1.1.1.2 joerg if (auto *DI = dyn_cast<DefInit>(Arg)) { 1290 1.1.1.2 joerg Record *Rec = DI->getDef(); 1291 1.1.1.2 joerg if (Rec->isSubClassOf("Type")) { 1292 1.1.1.2 joerg const Type *T = getType(Rec, Param); 1293 1.1.1.2 joerg return std::make_shared<TypeResult>(T); 1294 1.1.1.2 joerg } 1295 1.1.1.2 joerg } 1296 1.1 joerg 1297 1.1.1.2 joerg PrintError("bad DAG argument type for code generation"); 1298 1.1.1.2 joerg PrintNote("DAG: " + D->getAsString()); 1299 1.1.1.2 joerg if (TypedInit *Typed = dyn_cast<TypedInit>(Arg)) 1300 1.1.1.2 joerg PrintNote("argument type: " + Typed->getType()->getAsString()); 1301 1.1.1.2 joerg PrintFatalNote("argument number " + Twine(ArgNum) + ": " + Arg->getAsString()); 1302 1.1.1.2 joerg } 1303 1.1 joerg 1304 1.1.1.2 joerg Result::Ptr EmitterBase::getCodeForArg(unsigned ArgNum, const Type *ArgType, 1305 1.1.1.2 joerg bool Promote, bool Immediate) { 1306 1.1.1.2 joerg Result::Ptr V = std::make_shared<BuiltinArgResult>( 1307 1.1.1.2 joerg ArgNum, isa<PointerType>(ArgType), Immediate); 1308 1.1.1.2 joerg 1309 1.1.1.2 joerg if (Promote) { 1310 1.1.1.2 joerg if (const auto *ST = dyn_cast<ScalarType>(ArgType)) { 1311 1.1.1.2 joerg if (ST->isInteger() && ST->sizeInBits() < 32) 1312 1.1.1.2 joerg V = std::make_shared<IntCastResult>(getScalarType("u32"), V); 1313 1.1.1.2 joerg } else if (const auto *PT = dyn_cast<PredicateType>(ArgType)) { 1314 1.1 joerg V = std::make_shared<IntCastResult>(getScalarType("u32"), V); 1315 1.1.1.2 joerg V = std::make_shared<IRIntrinsicResult>("arm_mve_pred_i2v", 1316 1.1.1.2 joerg std::vector<const Type *>{PT}, 1317 1.1.1.2 joerg std::vector<Result::Ptr>{V}); 1318 1.1.1.2 joerg } 1319 1.1 joerg } 1320 1.1 joerg 1321 1.1 joerg return V; 1322 1.1 joerg } 1323 1.1 joerg 1324 1.1.1.2 joerg ACLEIntrinsic::ACLEIntrinsic(EmitterBase &ME, Record *R, const Type *Param) 1325 1.1 joerg : ReturnType(ME.getType(R->getValueAsDef("ret"), Param)) { 1326 1.1 joerg // Derive the intrinsic's full name, by taking the name of the 1327 1.1 joerg // Tablegen record (or override) and appending the suffix from its 1328 1.1 joerg // parameter type. (If the intrinsic is unparametrised, its 1329 1.1 joerg // parameter type will be given as Void, which returns the empty 1330 1.1 joerg // string for acleSuffix.) 1331 1.1 joerg StringRef BaseName = 1332 1.1 joerg (R->isSubClassOf("NameOverride") ? R->getValueAsString("basename") 1333 1.1 joerg : R->getName()); 1334 1.1.1.2 joerg StringRef overrideLetter = R->getValueAsString("overrideKindLetter"); 1335 1.1.1.2 joerg FullName = 1336 1.1.1.2 joerg (Twine(BaseName) + Param->acleSuffix(std::string(overrideLetter))).str(); 1337 1.1 joerg 1338 1.1 joerg // Derive the intrinsic's polymorphic name, by removing components from the 1339 1.1 joerg // full name as specified by its 'pnt' member ('polymorphic name type'), 1340 1.1 joerg // which indicates how many type suffixes to remove, and any other piece of 1341 1.1 joerg // the name that should be removed. 1342 1.1 joerg Record *PolymorphicNameType = R->getValueAsDef("pnt"); 1343 1.1 joerg SmallVector<StringRef, 8> NameParts; 1344 1.1 joerg StringRef(FullName).split(NameParts, '_'); 1345 1.1 joerg for (unsigned i = 0, e = PolymorphicNameType->getValueAsInt( 1346 1.1 joerg "NumTypeSuffixesToDiscard"); 1347 1.1 joerg i < e; ++i) 1348 1.1 joerg NameParts.pop_back(); 1349 1.1 joerg if (!PolymorphicNameType->isValueUnset("ExtraSuffixToDiscard")) { 1350 1.1 joerg StringRef ExtraSuffix = 1351 1.1 joerg PolymorphicNameType->getValueAsString("ExtraSuffixToDiscard"); 1352 1.1 joerg auto it = NameParts.end(); 1353 1.1 joerg while (it != NameParts.begin()) { 1354 1.1 joerg --it; 1355 1.1 joerg if (*it == ExtraSuffix) { 1356 1.1 joerg NameParts.erase(it); 1357 1.1 joerg break; 1358 1.1 joerg } 1359 1.1 joerg } 1360 1.1 joerg } 1361 1.1 joerg ShortName = join(std::begin(NameParts), std::end(NameParts), "_"); 1362 1.1 joerg 1363 1.1.1.2 joerg BuiltinExtension = R->getValueAsString("builtinExtension"); 1364 1.1.1.2 joerg 1365 1.1.1.2 joerg PolymorphicOnly = R->getValueAsBit("polymorphicOnly"); 1366 1.1.1.2 joerg NonEvaluating = R->getValueAsBit("nonEvaluating"); 1367 1.1.1.2 joerg HeaderOnly = R->getValueAsBit("headerOnly"); 1368 1.1.1.2 joerg 1369 1.1 joerg // Process the intrinsic's argument list. 1370 1.1 joerg DagInit *ArgsDag = R->getValueAsDag("args"); 1371 1.1 joerg Result::Scope Scope; 1372 1.1 joerg for (unsigned i = 0, e = ArgsDag->getNumArgs(); i < e; ++i) { 1373 1.1 joerg Init *TypeInit = ArgsDag->getArg(i); 1374 1.1 joerg 1375 1.1.1.2 joerg bool Promote = true; 1376 1.1.1.2 joerg if (auto TypeDI = dyn_cast<DefInit>(TypeInit)) 1377 1.1.1.2 joerg if (TypeDI->getDef()->isSubClassOf("unpromoted")) 1378 1.1.1.2 joerg Promote = false; 1379 1.1.1.2 joerg 1380 1.1 joerg // Work out the type of the argument, for use in the function prototype in 1381 1.1 joerg // the header file. 1382 1.1 joerg const Type *ArgType = ME.getType(TypeInit, Param); 1383 1.1 joerg ArgTypes.push_back(ArgType); 1384 1.1 joerg 1385 1.1 joerg // If the argument is a subclass of Immediate, record the details about 1386 1.1 joerg // what values it can take, for Sema checking. 1387 1.1.1.2 joerg bool Immediate = false; 1388 1.1 joerg if (auto TypeDI = dyn_cast<DefInit>(TypeInit)) { 1389 1.1 joerg Record *TypeRec = TypeDI->getDef(); 1390 1.1 joerg if (TypeRec->isSubClassOf("Immediate")) { 1391 1.1.1.2 joerg Immediate = true; 1392 1.1.1.2 joerg 1393 1.1 joerg Record *Bounds = TypeRec->getValueAsDef("bounds"); 1394 1.1 joerg ImmediateArg &IA = ImmediateArgs[i]; 1395 1.1 joerg if (Bounds->isSubClassOf("IB_ConstRange")) { 1396 1.1 joerg IA.boundsType = ImmediateArg::BoundsType::ExplicitRange; 1397 1.1 joerg IA.i1 = Bounds->getValueAsInt("lo"); 1398 1.1 joerg IA.i2 = Bounds->getValueAsInt("hi"); 1399 1.1 joerg } else if (Bounds->getName() == "IB_UEltValue") { 1400 1.1 joerg IA.boundsType = ImmediateArg::BoundsType::UInt; 1401 1.1 joerg IA.i1 = Param->sizeInBits(); 1402 1.1 joerg } else if (Bounds->getName() == "IB_LaneIndex") { 1403 1.1 joerg IA.boundsType = ImmediateArg::BoundsType::ExplicitRange; 1404 1.1 joerg IA.i1 = 0; 1405 1.1.1.2 joerg IA.i2 = 128 / Param->sizeInBits() - 1; 1406 1.1.1.2 joerg } else if (Bounds->isSubClassOf("IB_EltBit")) { 1407 1.1 joerg IA.boundsType = ImmediateArg::BoundsType::ExplicitRange; 1408 1.1 joerg IA.i1 = Bounds->getValueAsInt("base"); 1409 1.1.1.2 joerg const Type *T = ME.getType(Bounds->getValueAsDef("type"), Param); 1410 1.1.1.2 joerg IA.i2 = IA.i1 + T->sizeInBits() - 1; 1411 1.1 joerg } else { 1412 1.1 joerg PrintFatalError("unrecognised ImmediateBounds subclass"); 1413 1.1 joerg } 1414 1.1 joerg 1415 1.1 joerg IA.ArgType = ArgType; 1416 1.1 joerg 1417 1.1 joerg if (!TypeRec->isValueUnset("extra")) { 1418 1.1 joerg IA.ExtraCheckType = TypeRec->getValueAsString("extra"); 1419 1.1 joerg if (!TypeRec->isValueUnset("extraarg")) 1420 1.1 joerg IA.ExtraCheckArgs = TypeRec->getValueAsString("extraarg"); 1421 1.1 joerg } 1422 1.1 joerg } 1423 1.1 joerg } 1424 1.1.1.2 joerg 1425 1.1.1.2 joerg // The argument will usually have a name in the arguments dag, which goes 1426 1.1.1.2 joerg // into the variable-name scope that the code gen will refer to. 1427 1.1.1.2 joerg StringRef ArgName = ArgsDag->getArgNameStr(i); 1428 1.1.1.2 joerg if (!ArgName.empty()) 1429 1.1.1.2 joerg Scope[std::string(ArgName)] = 1430 1.1.1.2 joerg ME.getCodeForArg(i, ArgType, Promote, Immediate); 1431 1.1 joerg } 1432 1.1 joerg 1433 1.1 joerg // Finally, go through the codegen dag and translate it into a Result object 1434 1.1 joerg // (with an arbitrary DAG of depended-on Results hanging off it). 1435 1.1 joerg DagInit *CodeDag = R->getValueAsDag("codegen"); 1436 1.1 joerg Record *MainOp = cast<DefInit>(CodeDag->getOperator())->getDef(); 1437 1.1 joerg if (MainOp->isSubClassOf("CustomCodegen")) { 1438 1.1 joerg // Or, if it's the special case of CustomCodegen, just accumulate 1439 1.1 joerg // a list of parameters we're going to assign to variables before 1440 1.1 joerg // breaking from the loop. 1441 1.1 joerg CustomCodeGenArgs["CustomCodeGenType"] = 1442 1.1 joerg (Twine("CustomCodeGen::") + MainOp->getValueAsString("type")).str(); 1443 1.1 joerg for (unsigned i = 0, e = CodeDag->getNumArgs(); i < e; ++i) { 1444 1.1 joerg StringRef Name = CodeDag->getArgNameStr(i); 1445 1.1 joerg if (Name.empty()) { 1446 1.1 joerg PrintFatalError("Operands to CustomCodegen should have names"); 1447 1.1 joerg } else if (auto *II = dyn_cast<IntInit>(CodeDag->getArg(i))) { 1448 1.1.1.2 joerg CustomCodeGenArgs[std::string(Name)] = itostr(II->getValue()); 1449 1.1 joerg } else if (auto *SI = dyn_cast<StringInit>(CodeDag->getArg(i))) { 1450 1.1.1.2 joerg CustomCodeGenArgs[std::string(Name)] = std::string(SI->getValue()); 1451 1.1 joerg } else { 1452 1.1 joerg PrintFatalError("Operands to CustomCodegen should be integers"); 1453 1.1 joerg } 1454 1.1 joerg } 1455 1.1 joerg } else { 1456 1.1 joerg Code = ME.getCodeForDag(CodeDag, Scope, Param); 1457 1.1 joerg } 1458 1.1 joerg } 1459 1.1 joerg 1460 1.1.1.2 joerg EmitterBase::EmitterBase(RecordKeeper &Records) { 1461 1.1.1.2 joerg // Construct the whole EmitterBase. 1462 1.1 joerg 1463 1.1 joerg // First, look up all the instances of PrimitiveType. This gives us the list 1464 1.1 joerg // of vector typedefs we have to put in arm_mve.h, and also allows us to 1465 1.1 joerg // collect all the useful ScalarType instances into a big list so that we can 1466 1.1 joerg // use it for operations such as 'find the unsigned version of this signed 1467 1.1 joerg // integer type'. 1468 1.1 joerg for (Record *R : Records.getAllDerivedDefinitions("PrimitiveType")) 1469 1.1.1.2 joerg ScalarTypes[std::string(R->getName())] = std::make_unique<ScalarType>(R); 1470 1.1 joerg 1471 1.1 joerg // Now go through the instances of Intrinsic, and for each one, iterate 1472 1.1 joerg // through its list of type parameters making an ACLEIntrinsic for each one. 1473 1.1 joerg for (Record *R : Records.getAllDerivedDefinitions("Intrinsic")) { 1474 1.1 joerg for (Record *RParam : R->getValueAsListOfDefs("params")) { 1475 1.1 joerg const Type *Param = getType(RParam, getVoidType()); 1476 1.1 joerg auto Intrinsic = std::make_unique<ACLEIntrinsic>(*this, R, Param); 1477 1.1 joerg ACLEIntrinsics[Intrinsic->fullName()] = std::move(Intrinsic); 1478 1.1 joerg } 1479 1.1 joerg } 1480 1.1 joerg } 1481 1.1 joerg 1482 1.1 joerg /// A wrapper on raw_string_ostream that contains its own buffer rather than 1483 1.1 joerg /// having to point it at one elsewhere. (In other words, it works just like 1484 1.1 joerg /// std::ostringstream; also, this makes it convenient to declare a whole array 1485 1.1 joerg /// of them at once.) 1486 1.1 joerg /// 1487 1.1 joerg /// We have to set this up using multiple inheritance, to ensure that the 1488 1.1 joerg /// string member has been constructed before raw_string_ostream's constructor 1489 1.1 joerg /// is given a pointer to it. 1490 1.1 joerg class string_holder { 1491 1.1 joerg protected: 1492 1.1 joerg std::string S; 1493 1.1 joerg }; 1494 1.1 joerg class raw_self_contained_string_ostream : private string_holder, 1495 1.1 joerg public raw_string_ostream { 1496 1.1 joerg public: 1497 1.1 joerg raw_self_contained_string_ostream() 1498 1.1 joerg : string_holder(), raw_string_ostream(S) {} 1499 1.1 joerg }; 1500 1.1 joerg 1501 1.1.1.2 joerg const char LLVMLicenseHeader[] = 1502 1.1.1.2 joerg " *\n" 1503 1.1.1.2 joerg " *\n" 1504 1.1.1.2 joerg " * Part of the LLVM Project, under the Apache License v2.0 with LLVM" 1505 1.1.1.2 joerg " Exceptions.\n" 1506 1.1.1.2 joerg " * See https://llvm.org/LICENSE.txt for license information.\n" 1507 1.1.1.2 joerg " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n" 1508 1.1.1.2 joerg " *\n" 1509 1.1.1.2 joerg " *===-----------------------------------------------------------------" 1510 1.1.1.2 joerg "------===\n" 1511 1.1.1.2 joerg " */\n" 1512 1.1.1.2 joerg "\n"; 1513 1.1 joerg 1514 1.1.1.2 joerg // Machinery for the grouping of intrinsics by similar codegen. 1515 1.1.1.2 joerg // 1516 1.1.1.2 joerg // The general setup is that 'MergeableGroup' stores the things that a set of 1517 1.1.1.2 joerg // similarly shaped intrinsics have in common: the text of their code 1518 1.1.1.2 joerg // generation, and the number and type of their parameter variables. 1519 1.1.1.2 joerg // MergeableGroup is the key in a std::map whose value is a set of 1520 1.1.1.2 joerg // OutputIntrinsic, which stores the ways in which a particular intrinsic 1521 1.1.1.2 joerg // specializes the MergeableGroup's generic description: the function name and 1522 1.1.1.2 joerg // the _values_ of the parameter variables. 1523 1.1 joerg 1524 1.1.1.2 joerg struct ComparableStringVector : std::vector<std::string> { 1525 1.1.1.2 joerg // Infrastructure: a derived class of vector<string> which comes with an 1526 1.1.1.2 joerg // ordering, so that it can be used as a key in maps and an element in sets. 1527 1.1.1.2 joerg // There's no requirement on the ordering beyond being deterministic. 1528 1.1.1.2 joerg bool operator<(const ComparableStringVector &rhs) const { 1529 1.1.1.2 joerg if (size() != rhs.size()) 1530 1.1.1.2 joerg return size() < rhs.size(); 1531 1.1.1.2 joerg for (size_t i = 0, e = size(); i < e; ++i) 1532 1.1.1.2 joerg if ((*this)[i] != rhs[i]) 1533 1.1.1.2 joerg return (*this)[i] < rhs[i]; 1534 1.1.1.2 joerg return false; 1535 1.1.1.2 joerg } 1536 1.1.1.2 joerg }; 1537 1.1 joerg 1538 1.1.1.2 joerg struct OutputIntrinsic { 1539 1.1.1.2 joerg const ACLEIntrinsic *Int; 1540 1.1.1.2 joerg std::string Name; 1541 1.1.1.2 joerg ComparableStringVector ParamValues; 1542 1.1.1.2 joerg bool operator<(const OutputIntrinsic &rhs) const { 1543 1.1.1.2 joerg if (Name != rhs.Name) 1544 1.1.1.2 joerg return Name < rhs.Name; 1545 1.1.1.2 joerg return ParamValues < rhs.ParamValues; 1546 1.1 joerg } 1547 1.1.1.2 joerg }; 1548 1.1.1.2 joerg struct MergeableGroup { 1549 1.1.1.2 joerg std::string Code; 1550 1.1.1.2 joerg ComparableStringVector ParamTypes; 1551 1.1.1.2 joerg bool operator<(const MergeableGroup &rhs) const { 1552 1.1.1.2 joerg if (Code != rhs.Code) 1553 1.1.1.2 joerg return Code < rhs.Code; 1554 1.1.1.2 joerg return ParamTypes < rhs.ParamTypes; 1555 1.1.1.2 joerg } 1556 1.1.1.2 joerg }; 1557 1.1 joerg 1558 1.1.1.2 joerg void EmitterBase::EmitBuiltinCG(raw_ostream &OS) { 1559 1.1.1.2 joerg // Pass 1: generate code for all the intrinsics as if every type or constant 1560 1.1.1.2 joerg // that can possibly be abstracted out into a parameter variable will be. 1561 1.1.1.2 joerg // This identifies the sets of intrinsics we'll group together into a single 1562 1.1.1.2 joerg // piece of code generation. 1563 1.1.1.2 joerg 1564 1.1.1.2 joerg std::map<MergeableGroup, std::set<OutputIntrinsic>> MergeableGroupsPrelim; 1565 1.1 joerg 1566 1.1 joerg for (const auto &kv : ACLEIntrinsics) { 1567 1.1 joerg const ACLEIntrinsic &Int = *kv.second; 1568 1.1.1.2 joerg if (Int.headerOnly()) 1569 1.1.1.2 joerg continue; 1570 1.1 joerg 1571 1.1.1.2 joerg MergeableGroup MG; 1572 1.1.1.2 joerg OutputIntrinsic OI; 1573 1.1 joerg 1574 1.1.1.2 joerg OI.Int = ∬ 1575 1.1.1.2 joerg OI.Name = Int.fullName(); 1576 1.1.1.2 joerg CodeGenParamAllocator ParamAllocPrelim{&MG.ParamTypes, &OI.ParamValues}; 1577 1.1.1.2 joerg raw_string_ostream OS(MG.Code); 1578 1.1.1.2 joerg Int.genCode(OS, ParamAllocPrelim, 1); 1579 1.1.1.2 joerg OS.flush(); 1580 1.1 joerg 1581 1.1.1.2 joerg MergeableGroupsPrelim[MG].insert(OI); 1582 1.1.1.2 joerg } 1583 1.1 joerg 1584 1.1.1.2 joerg // Pass 2: for each of those groups, optimize the parameter variable set by 1585 1.1.1.2 joerg // eliminating 'parameters' that are the same for all intrinsics in the 1586 1.1.1.2 joerg // group, and merging together pairs of parameter variables that take the 1587 1.1.1.2 joerg // same values as each other for all intrinsics in the group. 1588 1.1 joerg 1589 1.1.1.2 joerg std::map<MergeableGroup, std::set<OutputIntrinsic>> MergeableGroups; 1590 1.1 joerg 1591 1.1.1.2 joerg for (const auto &kv : MergeableGroupsPrelim) { 1592 1.1.1.2 joerg const MergeableGroup &MG = kv.first; 1593 1.1.1.2 joerg std::vector<int> ParamNumbers; 1594 1.1.1.2 joerg std::map<ComparableStringVector, int> ParamNumberMap; 1595 1.1 joerg 1596 1.1.1.2 joerg // Loop over the parameters for this group. 1597 1.1.1.2 joerg for (size_t i = 0, e = MG.ParamTypes.size(); i < e; ++i) { 1598 1.1.1.2 joerg // Is this parameter the same for all intrinsics in the group? 1599 1.1.1.2 joerg const OutputIntrinsic &OI_first = *kv.second.begin(); 1600 1.1.1.2 joerg bool Constant = all_of(kv.second, [&](const OutputIntrinsic &OI) { 1601 1.1.1.2 joerg return OI.ParamValues[i] == OI_first.ParamValues[i]; 1602 1.1.1.2 joerg }); 1603 1.1 joerg 1604 1.1.1.2 joerg // If so, record it as -1, meaning 'no parameter variable needed'. Then 1605 1.1.1.2 joerg // the corresponding call to allocParam in pass 2 will not generate a 1606 1.1.1.2 joerg // variable at all, and just use the value inline. 1607 1.1.1.2 joerg if (Constant) { 1608 1.1.1.2 joerg ParamNumbers.push_back(-1); 1609 1.1.1.2 joerg continue; 1610 1.1.1.2 joerg } 1611 1.1 joerg 1612 1.1.1.2 joerg // Otherwise, make a list of the values this parameter takes for each 1613 1.1.1.2 joerg // intrinsic, and see if that value vector matches anything we already 1614 1.1.1.2 joerg // have. We also record the parameter type, so that we don't accidentally 1615 1.1.1.2 joerg // match up two parameter variables with different types. (Not that 1616 1.1.1.2 joerg // there's much chance of them having textually equivalent values, but in 1617 1.1.1.2 joerg // _principle_ it could happen.) 1618 1.1.1.2 joerg ComparableStringVector key; 1619 1.1.1.2 joerg key.push_back(MG.ParamTypes[i]); 1620 1.1.1.2 joerg for (const auto &OI : kv.second) 1621 1.1.1.2 joerg key.push_back(OI.ParamValues[i]); 1622 1.1.1.2 joerg 1623 1.1.1.2 joerg auto Found = ParamNumberMap.find(key); 1624 1.1.1.2 joerg if (Found != ParamNumberMap.end()) { 1625 1.1.1.2 joerg // Yes, an existing parameter variable can be reused for this. 1626 1.1.1.2 joerg ParamNumbers.push_back(Found->second); 1627 1.1.1.2 joerg continue; 1628 1.1.1.2 joerg } 1629 1.1.1.2 joerg 1630 1.1.1.2 joerg // No, we need a new parameter variable. 1631 1.1.1.2 joerg int ExistingIndex = ParamNumberMap.size(); 1632 1.1.1.2 joerg ParamNumberMap[key] = ExistingIndex; 1633 1.1.1.2 joerg ParamNumbers.push_back(ExistingIndex); 1634 1.1.1.2 joerg } 1635 1.1.1.2 joerg 1636 1.1.1.2 joerg // Now we're ready to do the pass 2 code generation, which will emit the 1637 1.1.1.2 joerg // reduced set of parameter variables we've just worked out. 1638 1.1.1.2 joerg 1639 1.1.1.2 joerg for (const auto &OI_prelim : kv.second) { 1640 1.1.1.2 joerg const ACLEIntrinsic *Int = OI_prelim.Int; 1641 1.1.1.2 joerg 1642 1.1.1.2 joerg MergeableGroup MG; 1643 1.1.1.2 joerg OutputIntrinsic OI; 1644 1.1.1.2 joerg 1645 1.1.1.2 joerg OI.Int = OI_prelim.Int; 1646 1.1.1.2 joerg OI.Name = OI_prelim.Name; 1647 1.1.1.2 joerg CodeGenParamAllocator ParamAlloc{&MG.ParamTypes, &OI.ParamValues, 1648 1.1.1.2 joerg &ParamNumbers}; 1649 1.1.1.2 joerg raw_string_ostream OS(MG.Code); 1650 1.1.1.2 joerg Int->genCode(OS, ParamAlloc, 2); 1651 1.1.1.2 joerg OS.flush(); 1652 1.1.1.2 joerg 1653 1.1.1.2 joerg MergeableGroups[MG].insert(OI); 1654 1.1.1.2 joerg } 1655 1.1.1.2 joerg } 1656 1.1.1.2 joerg 1657 1.1.1.2 joerg // Output the actual C++ code. 1658 1.1.1.2 joerg 1659 1.1.1.2 joerg for (const auto &kv : MergeableGroups) { 1660 1.1.1.2 joerg const MergeableGroup &MG = kv.first; 1661 1.1.1.2 joerg 1662 1.1.1.2 joerg // List of case statements in the main switch on BuiltinID, and an open 1663 1.1.1.2 joerg // brace. 1664 1.1.1.2 joerg const char *prefix = ""; 1665 1.1.1.2 joerg for (const auto &OI : kv.second) { 1666 1.1.1.2 joerg OS << prefix << "case ARM::BI__builtin_arm_" << OI.Int->builtinExtension() 1667 1.1.1.2 joerg << "_" << OI.Name << ":"; 1668 1.1.1.2 joerg 1669 1.1.1.2 joerg prefix = "\n"; 1670 1.1.1.2 joerg } 1671 1.1.1.2 joerg OS << " {\n"; 1672 1.1.1.2 joerg 1673 1.1.1.2 joerg if (!MG.ParamTypes.empty()) { 1674 1.1.1.2 joerg // If we've got some parameter variables, then emit their declarations... 1675 1.1.1.2 joerg for (size_t i = 0, e = MG.ParamTypes.size(); i < e; ++i) { 1676 1.1.1.2 joerg StringRef Type = MG.ParamTypes[i]; 1677 1.1.1.2 joerg OS << " " << Type; 1678 1.1.1.2 joerg if (!Type.endswith("*")) 1679 1.1.1.2 joerg OS << " "; 1680 1.1.1.2 joerg OS << " Param" << utostr(i) << ";\n"; 1681 1.1.1.2 joerg } 1682 1.1.1.2 joerg 1683 1.1.1.2 joerg // ... and an inner switch on BuiltinID that will fill them in with each 1684 1.1.1.2 joerg // individual intrinsic's values. 1685 1.1.1.2 joerg OS << " switch (BuiltinID) {\n"; 1686 1.1.1.2 joerg for (const auto &OI : kv.second) { 1687 1.1.1.2 joerg OS << " case ARM::BI__builtin_arm_" << OI.Int->builtinExtension() 1688 1.1.1.2 joerg << "_" << OI.Name << ":\n"; 1689 1.1.1.2 joerg for (size_t i = 0, e = MG.ParamTypes.size(); i < e; ++i) 1690 1.1.1.2 joerg OS << " Param" << utostr(i) << " = " << OI.ParamValues[i] << ";\n"; 1691 1.1.1.2 joerg OS << " break;\n"; 1692 1.1.1.2 joerg } 1693 1.1.1.2 joerg OS << " }\n"; 1694 1.1.1.2 joerg } 1695 1.1.1.2 joerg 1696 1.1.1.2 joerg // And finally, output the code, and close the outer pair of braces. (The 1697 1.1.1.2 joerg // code will always end with a 'return' statement, so we need not insert a 1698 1.1.1.2 joerg // 'break' here.) 1699 1.1.1.2 joerg OS << MG.Code << "}\n"; 1700 1.1.1.2 joerg } 1701 1.1.1.2 joerg } 1702 1.1.1.2 joerg 1703 1.1.1.2 joerg void EmitterBase::EmitBuiltinAliases(raw_ostream &OS) { 1704 1.1.1.2 joerg // Build a sorted table of: 1705 1.1.1.2 joerg // - intrinsic id number 1706 1.1.1.2 joerg // - full name 1707 1.1.1.2 joerg // - polymorphic name or -1 1708 1.1.1.2 joerg StringToOffsetTable StringTable; 1709 1.1.1.2 joerg OS << "static const IntrinToName MapData[] = {\n"; 1710 1.1.1.2 joerg for (const auto &kv : ACLEIntrinsics) { 1711 1.1.1.2 joerg const ACLEIntrinsic &Int = *kv.second; 1712 1.1.1.2 joerg if (Int.headerOnly()) 1713 1.1.1.2 joerg continue; 1714 1.1.1.2 joerg int32_t ShortNameOffset = 1715 1.1.1.2 joerg Int.polymorphic() ? StringTable.GetOrAddStringOffset(Int.shortName()) 1716 1.1.1.2 joerg : -1; 1717 1.1.1.2 joerg OS << " { ARM::BI__builtin_arm_" << Int.builtinExtension() << "_" 1718 1.1.1.2 joerg << Int.fullName() << ", " 1719 1.1.1.2 joerg << StringTable.GetOrAddStringOffset(Int.fullName()) << ", " 1720 1.1.1.2 joerg << ShortNameOffset << "},\n"; 1721 1.1.1.2 joerg } 1722 1.1.1.2 joerg OS << "};\n\n"; 1723 1.1.1.2 joerg 1724 1.1.1.2 joerg OS << "ArrayRef<IntrinToName> Map(MapData);\n\n"; 1725 1.1.1.2 joerg 1726 1.1.1.2 joerg OS << "static const char IntrinNames[] = {\n"; 1727 1.1.1.2 joerg StringTable.EmitString(OS); 1728 1.1.1.2 joerg OS << "};\n\n"; 1729 1.1.1.2 joerg } 1730 1.1.1.2 joerg 1731 1.1.1.2 joerg void EmitterBase::GroupSemaChecks( 1732 1.1.1.2 joerg std::map<std::string, std::set<std::string>> &Checks) { 1733 1.1.1.2 joerg for (const auto &kv : ACLEIntrinsics) { 1734 1.1.1.2 joerg const ACLEIntrinsic &Int = *kv.second; 1735 1.1.1.2 joerg if (Int.headerOnly()) 1736 1.1.1.2 joerg continue; 1737 1.1.1.2 joerg std::string Check = Int.genSema(); 1738 1.1.1.2 joerg if (!Check.empty()) 1739 1.1.1.2 joerg Checks[Check].insert(Int.fullName()); 1740 1.1.1.2 joerg } 1741 1.1.1.2 joerg } 1742 1.1.1.2 joerg 1743 1.1.1.2 joerg // ----------------------------------------------------------------------------- 1744 1.1.1.2 joerg // The class used for generating arm_mve.h and related Clang bits 1745 1.1.1.2 joerg // 1746 1.1.1.2 joerg 1747 1.1.1.2 joerg class MveEmitter : public EmitterBase { 1748 1.1.1.2 joerg public: 1749 1.1.1.2 joerg MveEmitter(RecordKeeper &Records) : EmitterBase(Records){}; 1750 1.1.1.2 joerg void EmitHeader(raw_ostream &OS) override; 1751 1.1.1.2 joerg void EmitBuiltinDef(raw_ostream &OS) override; 1752 1.1.1.2 joerg void EmitBuiltinSema(raw_ostream &OS) override; 1753 1.1.1.2 joerg }; 1754 1.1.1.2 joerg 1755 1.1.1.2 joerg void MveEmitter::EmitHeader(raw_ostream &OS) { 1756 1.1.1.2 joerg // Accumulate pieces of the header file that will be enabled under various 1757 1.1.1.2 joerg // different combinations of #ifdef. The index into parts[] is made up of 1758 1.1.1.2 joerg // the following bit flags. 1759 1.1.1.2 joerg constexpr unsigned Float = 1; 1760 1.1.1.2 joerg constexpr unsigned UseUserNamespace = 2; 1761 1.1.1.2 joerg 1762 1.1.1.2 joerg constexpr unsigned NumParts = 4; 1763 1.1.1.2 joerg raw_self_contained_string_ostream parts[NumParts]; 1764 1.1.1.2 joerg 1765 1.1.1.2 joerg // Write typedefs for all the required vector types, and a few scalar 1766 1.1.1.2 joerg // types that don't already have the name we want them to have. 1767 1.1.1.2 joerg 1768 1.1.1.2 joerg parts[0] << "typedef uint16_t mve_pred16_t;\n"; 1769 1.1.1.2 joerg parts[Float] << "typedef __fp16 float16_t;\n" 1770 1.1.1.2 joerg "typedef float float32_t;\n"; 1771 1.1.1.2 joerg for (const auto &kv : ScalarTypes) { 1772 1.1.1.2 joerg const ScalarType *ST = kv.second.get(); 1773 1.1.1.2 joerg if (ST->hasNonstandardName()) 1774 1.1.1.2 joerg continue; 1775 1.1.1.2 joerg raw_ostream &OS = parts[ST->requiresFloat() ? Float : 0]; 1776 1.1.1.2 joerg const VectorType *VT = getVectorType(ST); 1777 1.1.1.2 joerg 1778 1.1.1.2 joerg OS << "typedef __attribute__((__neon_vector_type__(" << VT->lanes() 1779 1.1.1.2 joerg << "), __clang_arm_mve_strict_polymorphism)) " << ST->cName() << " " 1780 1.1.1.2 joerg << VT->cName() << ";\n"; 1781 1.1.1.2 joerg 1782 1.1.1.2 joerg // Every vector type also comes with a pair of multi-vector types for 1783 1.1.1.2 joerg // the VLD2 and VLD4 instructions. 1784 1.1.1.2 joerg for (unsigned n = 2; n <= 4; n += 2) { 1785 1.1.1.2 joerg const MultiVectorType *MT = getMultiVectorType(n, VT); 1786 1.1.1.2 joerg OS << "typedef struct { " << VT->cName() << " val[" << n << "]; } " 1787 1.1.1.2 joerg << MT->cName() << ";\n"; 1788 1.1.1.2 joerg } 1789 1.1.1.2 joerg } 1790 1.1.1.2 joerg parts[0] << "\n"; 1791 1.1.1.2 joerg parts[Float] << "\n"; 1792 1.1.1.2 joerg 1793 1.1.1.2 joerg // Write declarations for all the intrinsics. 1794 1.1.1.2 joerg 1795 1.1.1.2 joerg for (const auto &kv : ACLEIntrinsics) { 1796 1.1.1.2 joerg const ACLEIntrinsic &Int = *kv.second; 1797 1.1.1.2 joerg 1798 1.1.1.2 joerg // We generate each intrinsic twice, under its full unambiguous 1799 1.1.1.2 joerg // name and its shorter polymorphic name (if the latter exists). 1800 1.1.1.2 joerg for (bool Polymorphic : {false, true}) { 1801 1.1.1.2 joerg if (Polymorphic && !Int.polymorphic()) 1802 1.1.1.2 joerg continue; 1803 1.1.1.2 joerg if (!Polymorphic && Int.polymorphicOnly()) 1804 1.1.1.2 joerg continue; 1805 1.1.1.2 joerg 1806 1.1.1.2 joerg // We also generate each intrinsic under a name like __arm_vfooq 1807 1.1.1.2 joerg // (which is in C language implementation namespace, so it's 1808 1.1.1.2 joerg // safe to define in any conforming user program) and a shorter 1809 1.1.1.2 joerg // one like vfooq (which is in user namespace, so a user might 1810 1.1.1.2 joerg // reasonably have used it for something already). If so, they 1811 1.1.1.2 joerg // can #define __ARM_MVE_PRESERVE_USER_NAMESPACE before 1812 1.1.1.2 joerg // including the header, which will suppress the shorter names 1813 1.1.1.2 joerg // and leave only the implementation-namespace ones. Then they 1814 1.1.1.2 joerg // have to write __arm_vfooq everywhere, of course. 1815 1.1.1.2 joerg 1816 1.1.1.2 joerg for (bool UserNamespace : {false, true}) { 1817 1.1.1.2 joerg raw_ostream &OS = parts[(Int.requiresFloat() ? Float : 0) | 1818 1.1.1.2 joerg (UserNamespace ? UseUserNamespace : 0)]; 1819 1.1.1.2 joerg 1820 1.1.1.2 joerg // Make the name of the function in this declaration. 1821 1.1.1.2 joerg 1822 1.1.1.2 joerg std::string FunctionName = 1823 1.1.1.2 joerg Polymorphic ? Int.shortName() : Int.fullName(); 1824 1.1.1.2 joerg if (!UserNamespace) 1825 1.1.1.2 joerg FunctionName = "__arm_" + FunctionName; 1826 1.1.1.2 joerg 1827 1.1.1.2 joerg // Make strings for the types involved in the function's 1828 1.1.1.2 joerg // prototype. 1829 1.1.1.2 joerg 1830 1.1.1.2 joerg std::string RetTypeName = Int.returnType()->cName(); 1831 1.1.1.2 joerg if (!StringRef(RetTypeName).endswith("*")) 1832 1.1.1.2 joerg RetTypeName += " "; 1833 1.1.1.2 joerg 1834 1.1.1.2 joerg std::vector<std::string> ArgTypeNames; 1835 1.1.1.2 joerg for (const Type *ArgTypePtr : Int.argTypes()) 1836 1.1.1.2 joerg ArgTypeNames.push_back(ArgTypePtr->cName()); 1837 1.1.1.2 joerg std::string ArgTypesString = 1838 1.1.1.2 joerg join(std::begin(ArgTypeNames), std::end(ArgTypeNames), ", "); 1839 1.1.1.2 joerg 1840 1.1.1.2 joerg // Emit the actual declaration. All these functions are 1841 1.1.1.2 joerg // declared 'static inline' without a body, which is fine 1842 1.1.1.2 joerg // provided clang recognizes them as builtins, and has the 1843 1.1.1.2 joerg // effect that this type signature is used in place of the one 1844 1.1.1.2 joerg // that Builtins.def didn't provide. That's how we can get 1845 1.1.1.2 joerg // structure types that weren't defined until this header was 1846 1.1.1.2 joerg // included to be part of the type signature of a builtin that 1847 1.1.1.2 joerg // was known to clang already. 1848 1.1.1.2 joerg // 1849 1.1.1.2 joerg // The declarations use __attribute__(__clang_arm_builtin_alias), 1850 1.1.1.2 joerg // so that each function declared will be recognized as the 1851 1.1.1.2 joerg // appropriate MVE builtin in spite of its user-facing name. 1852 1.1.1.2 joerg // 1853 1.1.1.2 joerg // (That's better than making them all wrapper functions, 1854 1.1.1.2 joerg // partly because it avoids any compiler error message citing 1855 1.1.1.2 joerg // the wrapper function definition instead of the user's code, 1856 1.1.1.2 joerg // and mostly because some MVE intrinsics have arguments 1857 1.1.1.2 joerg // required to be compile-time constants, and that property 1858 1.1.1.2 joerg // can't be propagated through a wrapper function. It can be 1859 1.1.1.2 joerg // propagated through a macro, but macros can't be overloaded 1860 1.1.1.2 joerg // on argument types very easily - you have to use _Generic, 1861 1.1 joerg // which makes error messages very confusing when the user 1862 1.1 joerg // gets it wrong.) 1863 1.1 joerg // 1864 1.1 joerg // Finally, the polymorphic versions of the intrinsics are 1865 1.1 joerg // also defined with __attribute__(overloadable), so that when 1866 1.1 joerg // the same name is defined with several type signatures, the 1867 1.1 joerg // right thing happens. Each one of the overloaded 1868 1.1 joerg // declarations is given a different builtin id, which 1869 1.1 joerg // has exactly the effect we want: first clang resolves the 1870 1.1 joerg // overload to the right function, then it knows which builtin 1871 1.1 joerg // it's referring to, and then the Sema checking for that 1872 1.1 joerg // builtin can check further things like the constant 1873 1.1 joerg // arguments. 1874 1.1 joerg // 1875 1.1 joerg // One more subtlety is the newline just before the return 1876 1.1 joerg // type name. That's a cosmetic tweak to make the error 1877 1.1 joerg // messages legible if the user gets the types wrong in a call 1878 1.1 joerg // to a polymorphic function: this way, clang will print just 1879 1.1 joerg // the _final_ line of each declaration in the header, to show 1880 1.1 joerg // the type signatures that would have been legal. So all the 1881 1.1 joerg // confusing machinery with __attribute__ is left out of the 1882 1.1 joerg // error message, and the user sees something that's more or 1883 1.1 joerg // less self-documenting: "here's a list of actually readable 1884 1.1 joerg // type signatures for vfooq(), and here's why each one didn't 1885 1.1 joerg // match your call". 1886 1.1 joerg 1887 1.1 joerg OS << "static __inline__ __attribute__((" 1888 1.1.1.2 joerg << (Polymorphic ? "__overloadable__, " : "") 1889 1.1.1.2 joerg << "__clang_arm_builtin_alias(__builtin_arm_mve_" << Int.fullName() 1890 1.1 joerg << ")))\n" 1891 1.1 joerg << RetTypeName << FunctionName << "(" << ArgTypesString << ");\n"; 1892 1.1 joerg } 1893 1.1 joerg } 1894 1.1 joerg } 1895 1.1 joerg for (auto &part : parts) 1896 1.1 joerg part << "\n"; 1897 1.1 joerg 1898 1.1 joerg // Now we've finished accumulating bits and pieces into the parts[] array. 1899 1.1 joerg // Put it all together to write the final output file. 1900 1.1 joerg 1901 1.1 joerg OS << "/*===---- arm_mve.h - ARM MVE intrinsics " 1902 1.1 joerg "-----------------------------------===\n" 1903 1.1.1.2 joerg << LLVMLicenseHeader 1904 1.1.1.2 joerg << "#ifndef __ARM_MVE_H\n" 1905 1.1 joerg "#define __ARM_MVE_H\n" 1906 1.1 joerg "\n" 1907 1.1 joerg "#if !__ARM_FEATURE_MVE\n" 1908 1.1 joerg "#error \"MVE support not enabled\"\n" 1909 1.1 joerg "#endif\n" 1910 1.1 joerg "\n" 1911 1.1 joerg "#include <stdint.h>\n" 1912 1.1.1.2 joerg "\n" 1913 1.1.1.2 joerg "#ifdef __cplusplus\n" 1914 1.1.1.2 joerg "extern \"C\" {\n" 1915 1.1.1.2 joerg "#endif\n" 1916 1.1 joerg "\n"; 1917 1.1 joerg 1918 1.1 joerg for (size_t i = 0; i < NumParts; ++i) { 1919 1.1 joerg std::vector<std::string> conditions; 1920 1.1 joerg if (i & Float) 1921 1.1 joerg conditions.push_back("(__ARM_FEATURE_MVE & 2)"); 1922 1.1 joerg if (i & UseUserNamespace) 1923 1.1 joerg conditions.push_back("(!defined __ARM_MVE_PRESERVE_USER_NAMESPACE)"); 1924 1.1 joerg 1925 1.1 joerg std::string condition = 1926 1.1 joerg join(std::begin(conditions), std::end(conditions), " && "); 1927 1.1 joerg if (!condition.empty()) 1928 1.1 joerg OS << "#if " << condition << "\n\n"; 1929 1.1 joerg OS << parts[i].str(); 1930 1.1 joerg if (!condition.empty()) 1931 1.1 joerg OS << "#endif /* " << condition << " */\n\n"; 1932 1.1 joerg } 1933 1.1 joerg 1934 1.1.1.2 joerg OS << "#ifdef __cplusplus\n" 1935 1.1.1.2 joerg "} /* extern \"C\" */\n" 1936 1.1.1.2 joerg "#endif\n" 1937 1.1.1.2 joerg "\n" 1938 1.1.1.2 joerg "#endif /* __ARM_MVE_H */\n"; 1939 1.1 joerg } 1940 1.1 joerg 1941 1.1 joerg void MveEmitter::EmitBuiltinDef(raw_ostream &OS) { 1942 1.1 joerg for (const auto &kv : ACLEIntrinsics) { 1943 1.1 joerg const ACLEIntrinsic &Int = *kv.second; 1944 1.1 joerg OS << "TARGET_HEADER_BUILTIN(__builtin_arm_mve_" << Int.fullName() 1945 1.1 joerg << ", \"\", \"n\", \"arm_mve.h\", ALL_LANGUAGES, \"\")\n"; 1946 1.1 joerg } 1947 1.1 joerg 1948 1.1 joerg std::set<std::string> ShortNamesSeen; 1949 1.1 joerg 1950 1.1 joerg for (const auto &kv : ACLEIntrinsics) { 1951 1.1 joerg const ACLEIntrinsic &Int = *kv.second; 1952 1.1 joerg if (Int.polymorphic()) { 1953 1.1 joerg StringRef Name = Int.shortName(); 1954 1.1.1.2 joerg if (ShortNamesSeen.find(std::string(Name)) == ShortNamesSeen.end()) { 1955 1.1.1.2 joerg OS << "BUILTIN(__builtin_arm_mve_" << Name << ", \"vi.\", \"nt"; 1956 1.1.1.2 joerg if (Int.nonEvaluating()) 1957 1.1.1.2 joerg OS << "u"; // indicate that this builtin doesn't evaluate its args 1958 1.1.1.2 joerg OS << "\")\n"; 1959 1.1.1.2 joerg ShortNamesSeen.insert(std::string(Name)); 1960 1.1 joerg } 1961 1.1 joerg } 1962 1.1 joerg } 1963 1.1 joerg } 1964 1.1 joerg 1965 1.1 joerg void MveEmitter::EmitBuiltinSema(raw_ostream &OS) { 1966 1.1 joerg std::map<std::string, std::set<std::string>> Checks; 1967 1.1.1.2 joerg GroupSemaChecks(Checks); 1968 1.1 joerg 1969 1.1 joerg for (const auto &kv : Checks) { 1970 1.1 joerg for (StringRef Name : kv.second) 1971 1.1 joerg OS << "case ARM::BI__builtin_arm_mve_" << Name << ":\n"; 1972 1.1.1.2 joerg OS << " return " << kv.first; 1973 1.1 joerg } 1974 1.1 joerg } 1975 1.1 joerg 1976 1.1.1.2 joerg // ----------------------------------------------------------------------------- 1977 1.1.1.2 joerg // Class that describes an ACLE intrinsic implemented as a macro. 1978 1.1 joerg // 1979 1.1.1.2 joerg // This class is used when the intrinsic is polymorphic in 2 or 3 types, but we 1980 1.1.1.2 joerg // want to avoid a combinatorial explosion by reinterpreting the arguments to 1981 1.1.1.2 joerg // fixed types. 1982 1.1.1.2 joerg 1983 1.1.1.2 joerg class FunctionMacro { 1984 1.1.1.2 joerg std::vector<StringRef> Params; 1985 1.1.1.2 joerg StringRef Definition; 1986 1.1 joerg 1987 1.1.1.2 joerg public: 1988 1.1.1.2 joerg FunctionMacro(const Record &R); 1989 1.1 joerg 1990 1.1.1.2 joerg const std::vector<StringRef> &getParams() const { return Params; } 1991 1.1.1.2 joerg StringRef getDefinition() const { return Definition; } 1992 1.1 joerg }; 1993 1.1 joerg 1994 1.1.1.2 joerg FunctionMacro::FunctionMacro(const Record &R) { 1995 1.1.1.2 joerg Params = R.getValueAsListOfStrings("params"); 1996 1.1.1.2 joerg Definition = R.getValueAsString("definition"); 1997 1.1.1.2 joerg } 1998 1.1 joerg 1999 1.1.1.2 joerg // ----------------------------------------------------------------------------- 2000 1.1.1.2 joerg // The class used for generating arm_cde.h and related Clang bits 2001 1.1.1.2 joerg // 2002 1.1 joerg 2003 1.1.1.2 joerg class CdeEmitter : public EmitterBase { 2004 1.1.1.2 joerg std::map<StringRef, FunctionMacro> FunctionMacros; 2005 1.1 joerg 2006 1.1.1.2 joerg public: 2007 1.1.1.2 joerg CdeEmitter(RecordKeeper &Records); 2008 1.1.1.2 joerg void EmitHeader(raw_ostream &OS) override; 2009 1.1.1.2 joerg void EmitBuiltinDef(raw_ostream &OS) override; 2010 1.1.1.2 joerg void EmitBuiltinSema(raw_ostream &OS) override; 2011 1.1.1.2 joerg }; 2012 1.1 joerg 2013 1.1.1.2 joerg CdeEmitter::CdeEmitter(RecordKeeper &Records) : EmitterBase(Records) { 2014 1.1.1.2 joerg for (Record *R : Records.getAllDerivedDefinitions("FunctionMacro")) 2015 1.1.1.2 joerg FunctionMacros.emplace(R->getName(), FunctionMacro(*R)); 2016 1.1.1.2 joerg } 2017 1.1 joerg 2018 1.1.1.2 joerg void CdeEmitter::EmitHeader(raw_ostream &OS) { 2019 1.1.1.2 joerg // Accumulate pieces of the header file that will be enabled under various 2020 1.1.1.2 joerg // different combinations of #ifdef. The index into parts[] is one of the 2021 1.1.1.2 joerg // following: 2022 1.1.1.2 joerg constexpr unsigned None = 0; 2023 1.1.1.2 joerg constexpr unsigned MVE = 1; 2024 1.1.1.2 joerg constexpr unsigned MVEFloat = 2; 2025 1.1 joerg 2026 1.1.1.2 joerg constexpr unsigned NumParts = 3; 2027 1.1.1.2 joerg raw_self_contained_string_ostream parts[NumParts]; 2028 1.1 joerg 2029 1.1.1.2 joerg // Write typedefs for all the required vector types, and a few scalar 2030 1.1.1.2 joerg // types that don't already have the name we want them to have. 2031 1.1 joerg 2032 1.1.1.2 joerg parts[MVE] << "typedef uint16_t mve_pred16_t;\n"; 2033 1.1.1.2 joerg parts[MVEFloat] << "typedef __fp16 float16_t;\n" 2034 1.1.1.2 joerg "typedef float float32_t;\n"; 2035 1.1.1.2 joerg for (const auto &kv : ScalarTypes) { 2036 1.1.1.2 joerg const ScalarType *ST = kv.second.get(); 2037 1.1.1.2 joerg if (ST->hasNonstandardName()) 2038 1.1.1.2 joerg continue; 2039 1.1.1.2 joerg // We don't have float64x2_t 2040 1.1.1.2 joerg if (ST->kind() == ScalarTypeKind::Float && ST->sizeInBits() == 64) 2041 1.1.1.2 joerg continue; 2042 1.1.1.2 joerg raw_ostream &OS = parts[ST->requiresFloat() ? MVEFloat : MVE]; 2043 1.1.1.2 joerg const VectorType *VT = getVectorType(ST); 2044 1.1 joerg 2045 1.1.1.2 joerg OS << "typedef __attribute__((__neon_vector_type__(" << VT->lanes() 2046 1.1.1.2 joerg << "), __clang_arm_mve_strict_polymorphism)) " << ST->cName() << " " 2047 1.1.1.2 joerg << VT->cName() << ";\n"; 2048 1.1.1.2 joerg } 2049 1.1.1.2 joerg parts[MVE] << "\n"; 2050 1.1.1.2 joerg parts[MVEFloat] << "\n"; 2051 1.1 joerg 2052 1.1.1.2 joerg // Write declarations for all the intrinsics. 2053 1.1 joerg 2054 1.1.1.2 joerg for (const auto &kv : ACLEIntrinsics) { 2055 1.1.1.2 joerg const ACLEIntrinsic &Int = *kv.second; 2056 1.1 joerg 2057 1.1.1.2 joerg // We generate each intrinsic twice, under its full unambiguous 2058 1.1.1.2 joerg // name and its shorter polymorphic name (if the latter exists). 2059 1.1.1.2 joerg for (bool Polymorphic : {false, true}) { 2060 1.1.1.2 joerg if (Polymorphic && !Int.polymorphic()) 2061 1.1.1.2 joerg continue; 2062 1.1.1.2 joerg if (!Polymorphic && Int.polymorphicOnly()) 2063 1.1 joerg continue; 2064 1.1 joerg 2065 1.1.1.2 joerg raw_ostream &OS = 2066 1.1.1.2 joerg parts[Int.requiresFloat() ? MVEFloat 2067 1.1.1.2 joerg : Int.requiresMVE() ? MVE : None]; 2068 1.1.1.2 joerg 2069 1.1.1.2 joerg // Make the name of the function in this declaration. 2070 1.1.1.2 joerg std::string FunctionName = 2071 1.1.1.2 joerg "__arm_" + (Polymorphic ? Int.shortName() : Int.fullName()); 2072 1.1.1.2 joerg 2073 1.1.1.2 joerg // Make strings for the types involved in the function's 2074 1.1.1.2 joerg // prototype. 2075 1.1.1.2 joerg std::string RetTypeName = Int.returnType()->cName(); 2076 1.1.1.2 joerg if (!StringRef(RetTypeName).endswith("*")) 2077 1.1.1.2 joerg RetTypeName += " "; 2078 1.1.1.2 joerg 2079 1.1.1.2 joerg std::vector<std::string> ArgTypeNames; 2080 1.1.1.2 joerg for (const Type *ArgTypePtr : Int.argTypes()) 2081 1.1.1.2 joerg ArgTypeNames.push_back(ArgTypePtr->cName()); 2082 1.1.1.2 joerg std::string ArgTypesString = 2083 1.1.1.2 joerg join(std::begin(ArgTypeNames), std::end(ArgTypeNames), ", "); 2084 1.1.1.2 joerg 2085 1.1.1.2 joerg // Emit the actual declaration. See MveEmitter::EmitHeader for detailed 2086 1.1.1.2 joerg // comments 2087 1.1.1.2 joerg OS << "static __inline__ __attribute__((" 2088 1.1.1.2 joerg << (Polymorphic ? "__overloadable__, " : "") 2089 1.1.1.2 joerg << "__clang_arm_builtin_alias(__builtin_arm_" << Int.builtinExtension() 2090 1.1.1.2 joerg << "_" << Int.fullName() << ")))\n" 2091 1.1.1.2 joerg << RetTypeName << FunctionName << "(" << ArgTypesString << ");\n"; 2092 1.1 joerg } 2093 1.1 joerg } 2094 1.1 joerg 2095 1.1.1.2 joerg for (const auto &kv : FunctionMacros) { 2096 1.1.1.2 joerg StringRef Name = kv.first; 2097 1.1.1.2 joerg const FunctionMacro &FM = kv.second; 2098 1.1.1.2 joerg 2099 1.1.1.2 joerg raw_ostream &OS = parts[MVE]; 2100 1.1.1.2 joerg OS << "#define " 2101 1.1.1.2 joerg << "__arm_" << Name << "(" << join(FM.getParams(), ", ") << ") " 2102 1.1.1.2 joerg << FM.getDefinition() << "\n"; 2103 1.1.1.2 joerg } 2104 1.1 joerg 2105 1.1.1.2 joerg for (auto &part : parts) 2106 1.1.1.2 joerg part << "\n"; 2107 1.1 joerg 2108 1.1.1.2 joerg // Now we've finished accumulating bits and pieces into the parts[] array. 2109 1.1.1.2 joerg // Put it all together to write the final output file. 2110 1.1 joerg 2111 1.1.1.2 joerg OS << "/*===---- arm_cde.h - ARM CDE intrinsics " 2112 1.1.1.2 joerg "-----------------------------------===\n" 2113 1.1.1.2 joerg << LLVMLicenseHeader 2114 1.1.1.2 joerg << "#ifndef __ARM_CDE_H\n" 2115 1.1.1.2 joerg "#define __ARM_CDE_H\n" 2116 1.1.1.2 joerg "\n" 2117 1.1.1.2 joerg "#if !__ARM_FEATURE_CDE\n" 2118 1.1.1.2 joerg "#error \"CDE support not enabled\"\n" 2119 1.1.1.2 joerg "#endif\n" 2120 1.1.1.2 joerg "\n" 2121 1.1.1.2 joerg "#include <stdint.h>\n" 2122 1.1.1.2 joerg "\n" 2123 1.1.1.2 joerg "#ifdef __cplusplus\n" 2124 1.1.1.2 joerg "extern \"C\" {\n" 2125 1.1.1.2 joerg "#endif\n" 2126 1.1.1.2 joerg "\n"; 2127 1.1 joerg 2128 1.1.1.2 joerg for (size_t i = 0; i < NumParts; ++i) { 2129 1.1.1.2 joerg std::string condition; 2130 1.1.1.2 joerg if (i == MVEFloat) 2131 1.1.1.2 joerg condition = "__ARM_FEATURE_MVE & 2"; 2132 1.1.1.2 joerg else if (i == MVE) 2133 1.1.1.2 joerg condition = "__ARM_FEATURE_MVE"; 2134 1.1 joerg 2135 1.1.1.2 joerg if (!condition.empty()) 2136 1.1.1.2 joerg OS << "#if " << condition << "\n\n"; 2137 1.1.1.2 joerg OS << parts[i].str(); 2138 1.1.1.2 joerg if (!condition.empty()) 2139 1.1.1.2 joerg OS << "#endif /* " << condition << " */\n\n"; 2140 1.1 joerg } 2141 1.1.1.2 joerg 2142 1.1.1.2 joerg OS << "#ifdef __cplusplus\n" 2143 1.1.1.2 joerg "} /* extern \"C\" */\n" 2144 1.1.1.2 joerg "#endif\n" 2145 1.1.1.2 joerg "\n" 2146 1.1.1.2 joerg "#endif /* __ARM_CDE_H */\n"; 2147 1.1 joerg } 2148 1.1 joerg 2149 1.1.1.2 joerg void CdeEmitter::EmitBuiltinDef(raw_ostream &OS) { 2150 1.1 joerg for (const auto &kv : ACLEIntrinsics) { 2151 1.1.1.2 joerg if (kv.second->headerOnly()) 2152 1.1.1.2 joerg continue; 2153 1.1 joerg const ACLEIntrinsic &Int = *kv.second; 2154 1.1.1.2 joerg OS << "TARGET_HEADER_BUILTIN(__builtin_arm_cde_" << Int.fullName() 2155 1.1.1.2 joerg << ", \"\", \"ncU\", \"arm_cde.h\", ALL_LANGUAGES, \"\")\n"; 2156 1.1.1.2 joerg } 2157 1.1.1.2 joerg } 2158 1.1.1.2 joerg 2159 1.1.1.2 joerg void CdeEmitter::EmitBuiltinSema(raw_ostream &OS) { 2160 1.1.1.2 joerg std::map<std::string, std::set<std::string>> Checks; 2161 1.1.1.2 joerg GroupSemaChecks(Checks); 2162 1.1.1.2 joerg 2163 1.1.1.2 joerg for (const auto &kv : Checks) { 2164 1.1.1.2 joerg for (StringRef Name : kv.second) 2165 1.1.1.2 joerg OS << "case ARM::BI__builtin_arm_cde_" << Name << ":\n"; 2166 1.1.1.2 joerg OS << " Err = " << kv.first << " break;\n"; 2167 1.1 joerg } 2168 1.1 joerg } 2169 1.1 joerg 2170 1.1 joerg } // namespace 2171 1.1 joerg 2172 1.1 joerg namespace clang { 2173 1.1 joerg 2174 1.1.1.2 joerg // MVE 2175 1.1.1.2 joerg 2176 1.1 joerg void EmitMveHeader(RecordKeeper &Records, raw_ostream &OS) { 2177 1.1 joerg MveEmitter(Records).EmitHeader(OS); 2178 1.1 joerg } 2179 1.1 joerg 2180 1.1 joerg void EmitMveBuiltinDef(RecordKeeper &Records, raw_ostream &OS) { 2181 1.1 joerg MveEmitter(Records).EmitBuiltinDef(OS); 2182 1.1 joerg } 2183 1.1 joerg 2184 1.1 joerg void EmitMveBuiltinSema(RecordKeeper &Records, raw_ostream &OS) { 2185 1.1 joerg MveEmitter(Records).EmitBuiltinSema(OS); 2186 1.1 joerg } 2187 1.1 joerg 2188 1.1 joerg void EmitMveBuiltinCG(RecordKeeper &Records, raw_ostream &OS) { 2189 1.1 joerg MveEmitter(Records).EmitBuiltinCG(OS); 2190 1.1 joerg } 2191 1.1 joerg 2192 1.1 joerg void EmitMveBuiltinAliases(RecordKeeper &Records, raw_ostream &OS) { 2193 1.1 joerg MveEmitter(Records).EmitBuiltinAliases(OS); 2194 1.1 joerg } 2195 1.1 joerg 2196 1.1.1.2 joerg // CDE 2197 1.1.1.2 joerg 2198 1.1.1.2 joerg void EmitCdeHeader(RecordKeeper &Records, raw_ostream &OS) { 2199 1.1.1.2 joerg CdeEmitter(Records).EmitHeader(OS); 2200 1.1.1.2 joerg } 2201 1.1.1.2 joerg 2202 1.1.1.2 joerg void EmitCdeBuiltinDef(RecordKeeper &Records, raw_ostream &OS) { 2203 1.1.1.2 joerg CdeEmitter(Records).EmitBuiltinDef(OS); 2204 1.1.1.2 joerg } 2205 1.1.1.2 joerg 2206 1.1.1.2 joerg void EmitCdeBuiltinSema(RecordKeeper &Records, raw_ostream &OS) { 2207 1.1.1.2 joerg CdeEmitter(Records).EmitBuiltinSema(OS); 2208 1.1.1.2 joerg } 2209 1.1.1.2 joerg 2210 1.1.1.2 joerg void EmitCdeBuiltinCG(RecordKeeper &Records, raw_ostream &OS) { 2211 1.1.1.2 joerg CdeEmitter(Records).EmitBuiltinCG(OS); 2212 1.1.1.2 joerg } 2213 1.1.1.2 joerg 2214 1.1.1.2 joerg void EmitCdeBuiltinAliases(RecordKeeper &Records, raw_ostream &OS) { 2215 1.1.1.2 joerg CdeEmitter(Records).EmitBuiltinAliases(OS); 2216 1.1.1.2 joerg } 2217 1.1.1.2 joerg 2218 1.1 joerg } // end namespace clang 2219