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