Path: blob/main/contrib/llvm-project/llvm/lib/IR/Intrinsics.cpp
213766 views
//===-- Intrinsics.cpp - Intrinsic Function Handling ------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements functions required for supporting intrinsic functions.9//10//===----------------------------------------------------------------------===//1112#include "llvm/IR/Intrinsics.h"13#include "llvm/ADT/StringExtras.h"14#include "llvm/ADT/StringTable.h"15#include "llvm/IR/ConstantRange.h"16#include "llvm/IR/Function.h"17#include "llvm/IR/IntrinsicsAArch64.h"18#include "llvm/IR/IntrinsicsAMDGPU.h"19#include "llvm/IR/IntrinsicsARM.h"20#include "llvm/IR/IntrinsicsBPF.h"21#include "llvm/IR/IntrinsicsHexagon.h"22#include "llvm/IR/IntrinsicsLoongArch.h"23#include "llvm/IR/IntrinsicsMips.h"24#include "llvm/IR/IntrinsicsNVPTX.h"25#include "llvm/IR/IntrinsicsPowerPC.h"26#include "llvm/IR/IntrinsicsR600.h"27#include "llvm/IR/IntrinsicsRISCV.h"28#include "llvm/IR/IntrinsicsS390.h"29#include "llvm/IR/IntrinsicsSPIRV.h"30#include "llvm/IR/IntrinsicsVE.h"31#include "llvm/IR/IntrinsicsX86.h"32#include "llvm/IR/IntrinsicsXCore.h"33#include "llvm/IR/Module.h"34#include "llvm/IR/Type.h"3536using namespace llvm;3738/// Table of string intrinsic names indexed by enum value.39#define GET_INTRINSIC_NAME_TABLE40#include "llvm/IR/IntrinsicImpl.inc"41#undef GET_INTRINSIC_NAME_TABLE4243StringRef Intrinsic::getBaseName(ID id) {44assert(id < num_intrinsics && "Invalid intrinsic ID!");45return IntrinsicNameTable[IntrinsicNameOffsetTable[id]];46}4748StringRef Intrinsic::getName(ID id) {49assert(id < num_intrinsics && "Invalid intrinsic ID!");50assert(!Intrinsic::isOverloaded(id) &&51"This version of getName does not support overloading");52return getBaseName(id);53}5455/// Returns a stable mangling for the type specified for use in the name56/// mangling scheme used by 'any' types in intrinsic signatures. The mangling57/// of named types is simply their name. Manglings for unnamed types consist58/// of a prefix ('p' for pointers, 'a' for arrays, 'f_' for functions)59/// combined with the mangling of their component types. A vararg function60/// type will have a suffix of 'vararg'. Since function types can contain61/// other function types, we close a function type mangling with suffix 'f'62/// which can't be confused with it's prefix. This ensures we don't have63/// collisions between two unrelated function types. Otherwise, you might64/// parse ffXX as f(fXX) or f(fX)X. (X is a placeholder for any other type.)65/// The HasUnnamedType boolean is set if an unnamed type was encountered,66/// indicating that extra care must be taken to ensure a unique name.67static std::string getMangledTypeStr(Type *Ty, bool &HasUnnamedType) {68std::string Result;69if (PointerType *PTyp = dyn_cast<PointerType>(Ty)) {70Result += "p" + utostr(PTyp->getAddressSpace());71} else if (ArrayType *ATyp = dyn_cast<ArrayType>(Ty)) {72Result += "a" + utostr(ATyp->getNumElements()) +73getMangledTypeStr(ATyp->getElementType(), HasUnnamedType);74} else if (StructType *STyp = dyn_cast<StructType>(Ty)) {75if (!STyp->isLiteral()) {76Result += "s_";77if (STyp->hasName())78Result += STyp->getName();79else80HasUnnamedType = true;81} else {82Result += "sl_";83for (auto *Elem : STyp->elements())84Result += getMangledTypeStr(Elem, HasUnnamedType);85}86// Ensure nested structs are distinguishable.87Result += "s";88} else if (FunctionType *FT = dyn_cast<FunctionType>(Ty)) {89Result += "f_" + getMangledTypeStr(FT->getReturnType(), HasUnnamedType);90for (size_t i = 0; i < FT->getNumParams(); i++)91Result += getMangledTypeStr(FT->getParamType(i), HasUnnamedType);92if (FT->isVarArg())93Result += "vararg";94// Ensure nested function types are distinguishable.95Result += "f";96} else if (VectorType *VTy = dyn_cast<VectorType>(Ty)) {97ElementCount EC = VTy->getElementCount();98if (EC.isScalable())99Result += "nx";100Result += "v" + utostr(EC.getKnownMinValue()) +101getMangledTypeStr(VTy->getElementType(), HasUnnamedType);102} else if (TargetExtType *TETy = dyn_cast<TargetExtType>(Ty)) {103Result += "t";104Result += TETy->getName();105for (Type *ParamTy : TETy->type_params())106Result += "_" + getMangledTypeStr(ParamTy, HasUnnamedType);107for (unsigned IntParam : TETy->int_params())108Result += "_" + utostr(IntParam);109// Ensure nested target extension types are distinguishable.110Result += "t";111} else if (Ty) {112switch (Ty->getTypeID()) {113default:114llvm_unreachable("Unhandled type");115case Type::VoidTyID:116Result += "isVoid";117break;118case Type::MetadataTyID:119Result += "Metadata";120break;121case Type::HalfTyID:122Result += "f16";123break;124case Type::BFloatTyID:125Result += "bf16";126break;127case Type::FloatTyID:128Result += "f32";129break;130case Type::DoubleTyID:131Result += "f64";132break;133case Type::X86_FP80TyID:134Result += "f80";135break;136case Type::FP128TyID:137Result += "f128";138break;139case Type::PPC_FP128TyID:140Result += "ppcf128";141break;142case Type::X86_AMXTyID:143Result += "x86amx";144break;145case Type::IntegerTyID:146Result += "i" + utostr(cast<IntegerType>(Ty)->getBitWidth());147break;148}149}150return Result;151}152153static std::string getIntrinsicNameImpl(Intrinsic::ID Id, ArrayRef<Type *> Tys,154Module *M, FunctionType *FT,155bool EarlyModuleCheck) {156157assert(Id < Intrinsic::num_intrinsics && "Invalid intrinsic ID!");158assert((Tys.empty() || Intrinsic::isOverloaded(Id)) &&159"This version of getName is for overloaded intrinsics only");160(void)EarlyModuleCheck;161assert((!EarlyModuleCheck || M ||162!any_of(Tys, [](Type *T) { return isa<PointerType>(T); })) &&163"Intrinsic overloading on pointer types need to provide a Module");164bool HasUnnamedType = false;165std::string Result(Intrinsic::getBaseName(Id));166for (Type *Ty : Tys)167Result += "." + getMangledTypeStr(Ty, HasUnnamedType);168if (HasUnnamedType) {169assert(M && "unnamed types need a module");170if (!FT)171FT = Intrinsic::getType(M->getContext(), Id, Tys);172else173assert((FT == Intrinsic::getType(M->getContext(), Id, Tys)) &&174"Provided FunctionType must match arguments");175return M->getUniqueIntrinsicName(Result, Id, FT);176}177return Result;178}179180std::string Intrinsic::getName(ID Id, ArrayRef<Type *> Tys, Module *M,181FunctionType *FT) {182assert(M && "We need to have a Module");183return getIntrinsicNameImpl(Id, Tys, M, FT, true);184}185186std::string Intrinsic::getNameNoUnnamedTypes(ID Id, ArrayRef<Type *> Tys) {187return getIntrinsicNameImpl(Id, Tys, nullptr, nullptr, false);188}189190/// IIT_Info - These are enumerators that describe the entries returned by the191/// getIntrinsicInfoTableEntries function.192///193/// Defined in Intrinsics.td.194enum IIT_Info {195#define GET_INTRINSIC_IITINFO196#include "llvm/IR/IntrinsicImpl.inc"197#undef GET_INTRINSIC_IITINFO198};199200static void201DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,202IIT_Info LastInfo,203SmallVectorImpl<Intrinsic::IITDescriptor> &OutputTable) {204using namespace Intrinsic;205206bool IsScalableVector = (LastInfo == IIT_SCALABLE_VEC);207208IIT_Info Info = IIT_Info(Infos[NextElt++]);209unsigned StructElts = 2;210211switch (Info) {212case IIT_Done:213OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0));214return;215case IIT_VARARG:216OutputTable.push_back(IITDescriptor::get(IITDescriptor::VarArg, 0));217return;218case IIT_MMX:219OutputTable.push_back(IITDescriptor::get(IITDescriptor::MMX, 0));220return;221case IIT_AMX:222OutputTable.push_back(IITDescriptor::get(IITDescriptor::AMX, 0));223return;224case IIT_TOKEN:225OutputTable.push_back(IITDescriptor::get(IITDescriptor::Token, 0));226return;227case IIT_METADATA:228OutputTable.push_back(IITDescriptor::get(IITDescriptor::Metadata, 0));229return;230case IIT_F16:231OutputTable.push_back(IITDescriptor::get(IITDescriptor::Half, 0));232return;233case IIT_BF16:234OutputTable.push_back(IITDescriptor::get(IITDescriptor::BFloat, 0));235return;236case IIT_F32:237OutputTable.push_back(IITDescriptor::get(IITDescriptor::Float, 0));238return;239case IIT_F64:240OutputTable.push_back(IITDescriptor::get(IITDescriptor::Double, 0));241return;242case IIT_F128:243OutputTable.push_back(IITDescriptor::get(IITDescriptor::Quad, 0));244return;245case IIT_PPCF128:246OutputTable.push_back(IITDescriptor::get(IITDescriptor::PPCQuad, 0));247return;248case IIT_I1:249OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1));250return;251case IIT_I2:252OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 2));253return;254case IIT_I4:255OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 4));256return;257case IIT_AARCH64_SVCOUNT:258OutputTable.push_back(IITDescriptor::get(IITDescriptor::AArch64Svcount, 0));259return;260case IIT_I8:261OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 8));262return;263case IIT_I16:264OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 16));265return;266case IIT_I32:267OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 32));268return;269case IIT_I64:270OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 64));271return;272case IIT_I128:273OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 128));274return;275case IIT_V1:276OutputTable.push_back(IITDescriptor::getVector(1, IsScalableVector));277DecodeIITType(NextElt, Infos, Info, OutputTable);278return;279case IIT_V2:280OutputTable.push_back(IITDescriptor::getVector(2, IsScalableVector));281DecodeIITType(NextElt, Infos, Info, OutputTable);282return;283case IIT_V3:284OutputTable.push_back(IITDescriptor::getVector(3, IsScalableVector));285DecodeIITType(NextElt, Infos, Info, OutputTable);286return;287case IIT_V4:288OutputTable.push_back(IITDescriptor::getVector(4, IsScalableVector));289DecodeIITType(NextElt, Infos, Info, OutputTable);290return;291case IIT_V6:292OutputTable.push_back(IITDescriptor::getVector(6, IsScalableVector));293DecodeIITType(NextElt, Infos, Info, OutputTable);294return;295case IIT_V8:296OutputTable.push_back(IITDescriptor::getVector(8, IsScalableVector));297DecodeIITType(NextElt, Infos, Info, OutputTable);298return;299case IIT_V10:300OutputTable.push_back(IITDescriptor::getVector(10, IsScalableVector));301DecodeIITType(NextElt, Infos, Info, OutputTable);302return;303case IIT_V16:304OutputTable.push_back(IITDescriptor::getVector(16, IsScalableVector));305DecodeIITType(NextElt, Infos, Info, OutputTable);306return;307case IIT_V32:308OutputTable.push_back(IITDescriptor::getVector(32, IsScalableVector));309DecodeIITType(NextElt, Infos, Info, OutputTable);310return;311case IIT_V64:312OutputTable.push_back(IITDescriptor::getVector(64, IsScalableVector));313DecodeIITType(NextElt, Infos, Info, OutputTable);314return;315case IIT_V128:316OutputTable.push_back(IITDescriptor::getVector(128, IsScalableVector));317DecodeIITType(NextElt, Infos, Info, OutputTable);318return;319case IIT_V256:320OutputTable.push_back(IITDescriptor::getVector(256, IsScalableVector));321DecodeIITType(NextElt, Infos, Info, OutputTable);322return;323case IIT_V512:324OutputTable.push_back(IITDescriptor::getVector(512, IsScalableVector));325DecodeIITType(NextElt, Infos, Info, OutputTable);326return;327case IIT_V1024:328OutputTable.push_back(IITDescriptor::getVector(1024, IsScalableVector));329DecodeIITType(NextElt, Infos, Info, OutputTable);330return;331case IIT_V2048:332OutputTable.push_back(IITDescriptor::getVector(2048, IsScalableVector));333DecodeIITType(NextElt, Infos, Info, OutputTable);334return;335case IIT_V4096:336OutputTable.push_back(IITDescriptor::getVector(4096, IsScalableVector));337DecodeIITType(NextElt, Infos, Info, OutputTable);338return;339case IIT_EXTERNREF:340OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 10));341return;342case IIT_FUNCREF:343OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 20));344return;345case IIT_PTR:346OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0));347return;348case IIT_ANYPTR: // [ANYPTR addrspace]349OutputTable.push_back(350IITDescriptor::get(IITDescriptor::Pointer, Infos[NextElt++]));351return;352case IIT_ARG: {353unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);354OutputTable.push_back(IITDescriptor::get(IITDescriptor::Argument, ArgInfo));355return;356}357case IIT_EXTEND_ARG: {358unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);359OutputTable.push_back(360IITDescriptor::get(IITDescriptor::ExtendArgument, ArgInfo));361return;362}363case IIT_TRUNC_ARG: {364unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);365OutputTable.push_back(366IITDescriptor::get(IITDescriptor::TruncArgument, ArgInfo));367return;368}369case IIT_ONE_NTH_ELTS_VEC_ARG: {370unsigned short ArgNo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);371unsigned short N = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);372OutputTable.push_back(373IITDescriptor::get(IITDescriptor::OneNthEltsVecArgument, N, ArgNo));374return;375}376case IIT_SAME_VEC_WIDTH_ARG: {377unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);378OutputTable.push_back(379IITDescriptor::get(IITDescriptor::SameVecWidthArgument, ArgInfo));380return;381}382case IIT_VEC_OF_ANYPTRS_TO_ELT: {383unsigned short ArgNo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);384unsigned short RefNo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);385OutputTable.push_back(386IITDescriptor::get(IITDescriptor::VecOfAnyPtrsToElt, ArgNo, RefNo));387return;388}389case IIT_EMPTYSTRUCT:390OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0));391return;392case IIT_STRUCT9:393++StructElts;394[[fallthrough]];395case IIT_STRUCT8:396++StructElts;397[[fallthrough]];398case IIT_STRUCT7:399++StructElts;400[[fallthrough]];401case IIT_STRUCT6:402++StructElts;403[[fallthrough]];404case IIT_STRUCT5:405++StructElts;406[[fallthrough]];407case IIT_STRUCT4:408++StructElts;409[[fallthrough]];410case IIT_STRUCT3:411++StructElts;412[[fallthrough]];413case IIT_STRUCT2: {414OutputTable.push_back(415IITDescriptor::get(IITDescriptor::Struct, StructElts));416417for (unsigned i = 0; i != StructElts; ++i)418DecodeIITType(NextElt, Infos, Info, OutputTable);419return;420}421case IIT_SUBDIVIDE2_ARG: {422unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);423OutputTable.push_back(424IITDescriptor::get(IITDescriptor::Subdivide2Argument, ArgInfo));425return;426}427case IIT_SUBDIVIDE4_ARG: {428unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);429OutputTable.push_back(430IITDescriptor::get(IITDescriptor::Subdivide4Argument, ArgInfo));431return;432}433case IIT_VEC_ELEMENT: {434unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);435OutputTable.push_back(436IITDescriptor::get(IITDescriptor::VecElementArgument, ArgInfo));437return;438}439case IIT_SCALABLE_VEC: {440DecodeIITType(NextElt, Infos, Info, OutputTable);441return;442}443case IIT_VEC_OF_BITCASTS_TO_INT: {444unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);445OutputTable.push_back(446IITDescriptor::get(IITDescriptor::VecOfBitcastsToInt, ArgInfo));447return;448}449}450llvm_unreachable("unhandled");451}452453#define GET_INTRINSIC_GENERATOR_GLOBAL454#include "llvm/IR/IntrinsicImpl.inc"455#undef GET_INTRINSIC_GENERATOR_GLOBAL456457void Intrinsic::getIntrinsicInfoTableEntries(458ID id, SmallVectorImpl<IITDescriptor> &T) {459static_assert(sizeof(IIT_Table[0]) == 2,460"Expect 16-bit entries in IIT_Table");461// Check to see if the intrinsic's type was expressible by the table.462uint16_t TableVal = IIT_Table[id - 1];463464// Decode the TableVal into an array of IITValues.465SmallVector<unsigned char> IITValues;466ArrayRef<unsigned char> IITEntries;467unsigned NextElt = 0;468if (TableVal >> 15) {469// This is an offset into the IIT_LongEncodingTable.470IITEntries = IIT_LongEncodingTable;471472// Strip sentinel bit.473NextElt = TableVal & 0x7fff;474} else {475// If the entry was encoded into a single word in the table itself, decode476// it from an array of nibbles to an array of bytes.477do {478IITValues.push_back(TableVal & 0xF);479TableVal >>= 4;480} while (TableVal);481482IITEntries = IITValues;483NextElt = 0;484}485486// Okay, decode the table into the output vector of IITDescriptors.487DecodeIITType(NextElt, IITEntries, IIT_Done, T);488while (NextElt != IITEntries.size() && IITEntries[NextElt] != 0)489DecodeIITType(NextElt, IITEntries, IIT_Done, T);490}491492static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,493ArrayRef<Type *> Tys, LLVMContext &Context) {494using namespace Intrinsic;495496IITDescriptor D = Infos.front();497Infos = Infos.slice(1);498499switch (D.Kind) {500case IITDescriptor::Void:501return Type::getVoidTy(Context);502case IITDescriptor::VarArg:503return Type::getVoidTy(Context);504case IITDescriptor::MMX:505return llvm::FixedVectorType::get(llvm::IntegerType::get(Context, 64), 1);506case IITDescriptor::AMX:507return Type::getX86_AMXTy(Context);508case IITDescriptor::Token:509return Type::getTokenTy(Context);510case IITDescriptor::Metadata:511return Type::getMetadataTy(Context);512case IITDescriptor::Half:513return Type::getHalfTy(Context);514case IITDescriptor::BFloat:515return Type::getBFloatTy(Context);516case IITDescriptor::Float:517return Type::getFloatTy(Context);518case IITDescriptor::Double:519return Type::getDoubleTy(Context);520case IITDescriptor::Quad:521return Type::getFP128Ty(Context);522case IITDescriptor::PPCQuad:523return Type::getPPC_FP128Ty(Context);524case IITDescriptor::AArch64Svcount:525return TargetExtType::get(Context, "aarch64.svcount");526527case IITDescriptor::Integer:528return IntegerType::get(Context, D.Integer_Width);529case IITDescriptor::Vector:530return VectorType::get(DecodeFixedType(Infos, Tys, Context),531D.Vector_Width);532case IITDescriptor::Pointer:533return PointerType::get(Context, D.Pointer_AddressSpace);534case IITDescriptor::Struct: {535SmallVector<Type *, 8> Elts;536for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i)537Elts.push_back(DecodeFixedType(Infos, Tys, Context));538return StructType::get(Context, Elts);539}540case IITDescriptor::Argument:541return Tys[D.getArgumentNumber()];542case IITDescriptor::ExtendArgument: {543Type *Ty = Tys[D.getArgumentNumber()];544if (VectorType *VTy = dyn_cast<VectorType>(Ty))545return VectorType::getExtendedElementVectorType(VTy);546547return IntegerType::get(Context, 2 * cast<IntegerType>(Ty)->getBitWidth());548}549case IITDescriptor::TruncArgument: {550Type *Ty = Tys[D.getArgumentNumber()];551if (VectorType *VTy = dyn_cast<VectorType>(Ty))552return VectorType::getTruncatedElementVectorType(VTy);553554IntegerType *ITy = cast<IntegerType>(Ty);555assert(ITy->getBitWidth() % 2 == 0);556return IntegerType::get(Context, ITy->getBitWidth() / 2);557}558case IITDescriptor::Subdivide2Argument:559case IITDescriptor::Subdivide4Argument: {560Type *Ty = Tys[D.getArgumentNumber()];561VectorType *VTy = dyn_cast<VectorType>(Ty);562assert(VTy && "Expected an argument of Vector Type");563int SubDivs = D.Kind == IITDescriptor::Subdivide2Argument ? 1 : 2;564return VectorType::getSubdividedVectorType(VTy, SubDivs);565}566case IITDescriptor::OneNthEltsVecArgument:567return VectorType::getOneNthElementsVectorType(568cast<VectorType>(Tys[D.getRefArgNumber()]), D.getVectorDivisor());569case IITDescriptor::SameVecWidthArgument: {570Type *EltTy = DecodeFixedType(Infos, Tys, Context);571Type *Ty = Tys[D.getArgumentNumber()];572if (auto *VTy = dyn_cast<VectorType>(Ty))573return VectorType::get(EltTy, VTy->getElementCount());574return EltTy;575}576case IITDescriptor::VecElementArgument: {577Type *Ty = Tys[D.getArgumentNumber()];578if (VectorType *VTy = dyn_cast<VectorType>(Ty))579return VTy->getElementType();580llvm_unreachable("Expected an argument of Vector Type");581}582case IITDescriptor::VecOfBitcastsToInt: {583Type *Ty = Tys[D.getArgumentNumber()];584VectorType *VTy = dyn_cast<VectorType>(Ty);585assert(VTy && "Expected an argument of Vector Type");586return VectorType::getInteger(VTy);587}588case IITDescriptor::VecOfAnyPtrsToElt:589// Return the overloaded type (which determines the pointers address space)590return Tys[D.getOverloadArgNumber()];591}592llvm_unreachable("unhandled");593}594595FunctionType *Intrinsic::getType(LLVMContext &Context, ID id,596ArrayRef<Type *> Tys) {597SmallVector<IITDescriptor, 8> Table;598getIntrinsicInfoTableEntries(id, Table);599600ArrayRef<IITDescriptor> TableRef = Table;601Type *ResultTy = DecodeFixedType(TableRef, Tys, Context);602603SmallVector<Type *, 8> ArgTys;604while (!TableRef.empty())605ArgTys.push_back(DecodeFixedType(TableRef, Tys, Context));606607// DecodeFixedType returns Void for IITDescriptor::Void and608// IITDescriptor::VarArg If we see void type as the type of the last argument,609// it is vararg intrinsic610if (!ArgTys.empty() && ArgTys.back()->isVoidTy()) {611ArgTys.pop_back();612return FunctionType::get(ResultTy, ArgTys, true);613}614return FunctionType::get(ResultTy, ArgTys, false);615}616617bool Intrinsic::isOverloaded(ID id) {618#define GET_INTRINSIC_OVERLOAD_TABLE619#include "llvm/IR/IntrinsicImpl.inc"620#undef GET_INTRINSIC_OVERLOAD_TABLE621}622623/// Table of per-target intrinsic name tables.624#define GET_INTRINSIC_TARGET_DATA625#include "llvm/IR/IntrinsicImpl.inc"626#undef GET_INTRINSIC_TARGET_DATA627628bool Intrinsic::isTargetIntrinsic(Intrinsic::ID IID) {629return IID > TargetInfos[0].Count;630}631632/// Looks up Name in NameTable via binary search. NameTable must be sorted633/// and all entries must start with "llvm.". If NameTable contains an exact634/// match for Name or a prefix of Name followed by a dot, its index in635/// NameTable is returned. Otherwise, -1 is returned.636static int lookupLLVMIntrinsicByName(ArrayRef<unsigned> NameOffsetTable,637StringRef Name, StringRef Target = "") {638assert(Name.starts_with("llvm.") && "Unexpected intrinsic prefix");639assert(Name.drop_front(5).starts_with(Target) && "Unexpected target");640641// Do successive binary searches of the dotted name components. For642// "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of643// intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then644// "llvm.gc.experimental.statepoint", and then we will stop as the range is645// size 1. During the search, we can skip the prefix that we already know is646// identical. By using strncmp we consider names with differing suffixes to647// be part of the equal range.648size_t CmpEnd = 4; // Skip the "llvm" component.649if (!Target.empty())650CmpEnd += 1 + Target.size(); // skip the .target component.651652const unsigned *Low = NameOffsetTable.begin();653const unsigned *High = NameOffsetTable.end();654const unsigned *LastLow = Low;655while (CmpEnd < Name.size() && High - Low > 0) {656size_t CmpStart = CmpEnd;657CmpEnd = Name.find('.', CmpStart + 1);658CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd;659auto Cmp = [CmpStart, CmpEnd](auto LHS, auto RHS) {660// `equal_range` requires the comparison to work with either side being an661// offset or the value. Detect which kind each side is to set up the662// compared strings.663StringRef LHSStr;664if constexpr (std::is_integral_v<decltype(LHS)>) {665LHSStr = IntrinsicNameTable[LHS];666} else {667LHSStr = LHS;668}669StringRef RHSStr;670if constexpr (std::is_integral_v<decltype(RHS)>) {671RHSStr = IntrinsicNameTable[RHS];672} else {673RHSStr = RHS;674}675return strncmp(LHSStr.data() + CmpStart, RHSStr.data() + CmpStart,676CmpEnd - CmpStart) < 0;677};678LastLow = Low;679std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);680}681if (High - Low > 0)682LastLow = Low;683684if (LastLow == NameOffsetTable.end())685return -1;686StringRef NameFound = IntrinsicNameTable[*LastLow];687if (Name == NameFound ||688(Name.starts_with(NameFound) && Name[NameFound.size()] == '.'))689return LastLow - NameOffsetTable.begin();690return -1;691}692693/// Find the segment of \c IntrinsicNameOffsetTable for intrinsics with the same694/// target as \c Name, or the generic table if \c Name is not target specific.695///696/// Returns the relevant slice of \c IntrinsicNameOffsetTable and the target697/// name.698static std::pair<ArrayRef<unsigned>, StringRef>699findTargetSubtable(StringRef Name) {700assert(Name.starts_with("llvm."));701702ArrayRef<IntrinsicTargetInfo> Targets(TargetInfos);703// Drop "llvm." and take the first dotted component. That will be the target704// if this is target specific.705StringRef Target = Name.drop_front(5).split('.').first;706auto It = partition_point(707Targets, [=](const IntrinsicTargetInfo &TI) { return TI.Name < Target; });708// We've either found the target or just fall back to the generic set, which709// is always first.710const auto &TI = It != Targets.end() && It->Name == Target ? *It : Targets[0];711return {ArrayRef(&IntrinsicNameOffsetTable[1] + TI.Offset, TI.Count),712TI.Name};713}714715/// This does the actual lookup of an intrinsic ID which matches the given716/// function name.717Intrinsic::ID Intrinsic::lookupIntrinsicID(StringRef Name) {718auto [NameOffsetTable, Target] = findTargetSubtable(Name);719int Idx = lookupLLVMIntrinsicByName(NameOffsetTable, Name, Target);720if (Idx == -1)721return Intrinsic::not_intrinsic;722723// Intrinsic IDs correspond to the location in IntrinsicNameTable, but we have724// an index into a sub-table.725int Adjust = NameOffsetTable.data() - IntrinsicNameOffsetTable;726Intrinsic::ID ID = static_cast<Intrinsic::ID>(Idx + Adjust);727728// If the intrinsic is not overloaded, require an exact match. If it is729// overloaded, require either exact or prefix match.730const auto MatchSize = IntrinsicNameTable[NameOffsetTable[Idx]].size();731assert(Name.size() >= MatchSize && "Expected either exact or prefix match");732bool IsExactMatch = Name.size() == MatchSize;733return IsExactMatch || Intrinsic::isOverloaded(ID) ? ID734: Intrinsic::not_intrinsic;735}736737/// This defines the "Intrinsic::getAttributes(ID id)" method.738#define GET_INTRINSIC_ATTRIBUTES739#include "llvm/IR/IntrinsicImpl.inc"740#undef GET_INTRINSIC_ATTRIBUTES741742AttributeSet Intrinsic::getFnAttributes(LLVMContext &C, ID id) {743if (id == 0)744return AttributeSet();745uint16_t PackedID = IntrinsicsToAttributesMap[id - 1];746uint8_t FnAttrID = PackedID >> 8;747return getIntrinsicFnAttributeSet(C, FnAttrID);748}749750Function *Intrinsic::getOrInsertDeclaration(Module *M, ID id,751ArrayRef<Type *> Tys) {752// There can never be multiple globals with the same name of different types,753// because intrinsics must be a specific type.754auto *FT = getType(M->getContext(), id, Tys);755return cast<Function>(756M->getOrInsertFunction(757Tys.empty() ? getName(id) : getName(id, Tys, M, FT), FT)758.getCallee());759}760761Function *Intrinsic::getDeclarationIfExists(const Module *M, ID id) {762return M->getFunction(getName(id));763}764765Function *Intrinsic::getDeclarationIfExists(Module *M, ID id,766ArrayRef<Type *> Tys,767FunctionType *FT) {768return M->getFunction(getName(id, Tys, M, FT));769}770771// This defines the "Intrinsic::getIntrinsicForClangBuiltin()" method.772#define GET_LLVM_INTRINSIC_FOR_CLANG_BUILTIN773#include "llvm/IR/IntrinsicImpl.inc"774#undef GET_LLVM_INTRINSIC_FOR_CLANG_BUILTIN775776// This defines the "Intrinsic::getIntrinsicForMSBuiltin()" method.777#define GET_LLVM_INTRINSIC_FOR_MS_BUILTIN778#include "llvm/IR/IntrinsicImpl.inc"779#undef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN780781bool Intrinsic::isConstrainedFPIntrinsic(ID QID) {782switch (QID) {783#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \784case Intrinsic::INTRINSIC:785#include "llvm/IR/ConstrainedOps.def"786#undef INSTRUCTION787return true;788default:789return false;790}791}792793bool Intrinsic::hasConstrainedFPRoundingModeOperand(Intrinsic::ID QID) {794switch (QID) {795#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \796case Intrinsic::INTRINSIC: \797return ROUND_MODE == 1;798#include "llvm/IR/ConstrainedOps.def"799#undef INSTRUCTION800default:801return false;802}803}804805using DeferredIntrinsicMatchPair =806std::pair<Type *, ArrayRef<Intrinsic::IITDescriptor>>;807808static bool809matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,810SmallVectorImpl<Type *> &ArgTys,811SmallVectorImpl<DeferredIntrinsicMatchPair> &DeferredChecks,812bool IsDeferredCheck) {813using namespace Intrinsic;814815// If we ran out of descriptors, there are too many arguments.816if (Infos.empty())817return true;818819// Do this before slicing off the 'front' part820auto InfosRef = Infos;821auto DeferCheck = [&DeferredChecks, &InfosRef](Type *T) {822DeferredChecks.emplace_back(T, InfosRef);823return false;824};825826IITDescriptor D = Infos.front();827Infos = Infos.slice(1);828829switch (D.Kind) {830case IITDescriptor::Void:831return !Ty->isVoidTy();832case IITDescriptor::VarArg:833return true;834case IITDescriptor::MMX: {835FixedVectorType *VT = dyn_cast<FixedVectorType>(Ty);836return !VT || VT->getNumElements() != 1 ||837!VT->getElementType()->isIntegerTy(64);838}839case IITDescriptor::AMX:840return !Ty->isX86_AMXTy();841case IITDescriptor::Token:842return !Ty->isTokenTy();843case IITDescriptor::Metadata:844return !Ty->isMetadataTy();845case IITDescriptor::Half:846return !Ty->isHalfTy();847case IITDescriptor::BFloat:848return !Ty->isBFloatTy();849case IITDescriptor::Float:850return !Ty->isFloatTy();851case IITDescriptor::Double:852return !Ty->isDoubleTy();853case IITDescriptor::Quad:854return !Ty->isFP128Ty();855case IITDescriptor::PPCQuad:856return !Ty->isPPC_FP128Ty();857case IITDescriptor::Integer:858return !Ty->isIntegerTy(D.Integer_Width);859case IITDescriptor::AArch64Svcount:860return !isa<TargetExtType>(Ty) ||861cast<TargetExtType>(Ty)->getName() != "aarch64.svcount";862case IITDescriptor::Vector: {863VectorType *VT = dyn_cast<VectorType>(Ty);864return !VT || VT->getElementCount() != D.Vector_Width ||865matchIntrinsicType(VT->getElementType(), Infos, ArgTys,866DeferredChecks, IsDeferredCheck);867}868case IITDescriptor::Pointer: {869PointerType *PT = dyn_cast<PointerType>(Ty);870return !PT || PT->getAddressSpace() != D.Pointer_AddressSpace;871}872873case IITDescriptor::Struct: {874StructType *ST = dyn_cast<StructType>(Ty);875if (!ST || !ST->isLiteral() || ST->isPacked() ||876ST->getNumElements() != D.Struct_NumElements)877return true;878879for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i)880if (matchIntrinsicType(ST->getElementType(i), Infos, ArgTys,881DeferredChecks, IsDeferredCheck))882return true;883return false;884}885886case IITDescriptor::Argument:887// If this is the second occurrence of an argument,888// verify that the later instance matches the previous instance.889if (D.getArgumentNumber() < ArgTys.size())890return Ty != ArgTys[D.getArgumentNumber()];891892if (D.getArgumentNumber() > ArgTys.size() ||893D.getArgumentKind() == IITDescriptor::AK_MatchType)894return IsDeferredCheck || DeferCheck(Ty);895896assert(D.getArgumentNumber() == ArgTys.size() && !IsDeferredCheck &&897"Table consistency error");898ArgTys.push_back(Ty);899900switch (D.getArgumentKind()) {901case IITDescriptor::AK_Any:902return false; // Success903case IITDescriptor::AK_AnyInteger:904return !Ty->isIntOrIntVectorTy();905case IITDescriptor::AK_AnyFloat:906return !Ty->isFPOrFPVectorTy();907case IITDescriptor::AK_AnyVector:908return !isa<VectorType>(Ty);909case IITDescriptor::AK_AnyPointer:910return !isa<PointerType>(Ty);911default:912break;913}914llvm_unreachable("all argument kinds not covered");915916case IITDescriptor::ExtendArgument: {917// If this is a forward reference, defer the check for later.918if (D.getArgumentNumber() >= ArgTys.size())919return IsDeferredCheck || DeferCheck(Ty);920921Type *NewTy = ArgTys[D.getArgumentNumber()];922if (VectorType *VTy = dyn_cast<VectorType>(NewTy))923NewTy = VectorType::getExtendedElementVectorType(VTy);924else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy))925NewTy = IntegerType::get(ITy->getContext(), 2 * ITy->getBitWidth());926else927return true;928929return Ty != NewTy;930}931case IITDescriptor::TruncArgument: {932// If this is a forward reference, defer the check for later.933if (D.getArgumentNumber() >= ArgTys.size())934return IsDeferredCheck || DeferCheck(Ty);935936Type *NewTy = ArgTys[D.getArgumentNumber()];937if (VectorType *VTy = dyn_cast<VectorType>(NewTy))938NewTy = VectorType::getTruncatedElementVectorType(VTy);939else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy))940NewTy = IntegerType::get(ITy->getContext(), ITy->getBitWidth() / 2);941else942return true;943944return Ty != NewTy;945}946case IITDescriptor::OneNthEltsVecArgument:947// If this is a forward reference, defer the check for later.948if (D.getRefArgNumber() >= ArgTys.size())949return IsDeferredCheck || DeferCheck(Ty);950return !isa<VectorType>(ArgTys[D.getRefArgNumber()]) ||951VectorType::getOneNthElementsVectorType(952cast<VectorType>(ArgTys[D.getRefArgNumber()]),953D.getVectorDivisor()) != Ty;954case IITDescriptor::SameVecWidthArgument: {955if (D.getArgumentNumber() >= ArgTys.size()) {956// Defer check and subsequent check for the vector element type.957Infos = Infos.slice(1);958return IsDeferredCheck || DeferCheck(Ty);959}960auto *ReferenceType = dyn_cast<VectorType>(ArgTys[D.getArgumentNumber()]);961auto *ThisArgType = dyn_cast<VectorType>(Ty);962// Both must be vectors of the same number of elements or neither.963if ((ReferenceType != nullptr) != (ThisArgType != nullptr))964return true;965Type *EltTy = Ty;966if (ThisArgType) {967if (ReferenceType->getElementCount() != ThisArgType->getElementCount())968return true;969EltTy = ThisArgType->getElementType();970}971return matchIntrinsicType(EltTy, Infos, ArgTys, DeferredChecks,972IsDeferredCheck);973}974case IITDescriptor::VecOfAnyPtrsToElt: {975unsigned RefArgNumber = D.getRefArgNumber();976if (RefArgNumber >= ArgTys.size()) {977if (IsDeferredCheck)978return true;979// If forward referencing, already add the pointer-vector type and980// defer the checks for later.981ArgTys.push_back(Ty);982return DeferCheck(Ty);983}984985if (!IsDeferredCheck) {986assert(D.getOverloadArgNumber() == ArgTys.size() &&987"Table consistency error");988ArgTys.push_back(Ty);989}990991// Verify the overloaded type "matches" the Ref type.992// i.e. Ty is a vector with the same width as Ref.993// Composed of pointers to the same element type as Ref.994auto *ReferenceType = dyn_cast<VectorType>(ArgTys[RefArgNumber]);995auto *ThisArgVecTy = dyn_cast<VectorType>(Ty);996if (!ThisArgVecTy || !ReferenceType ||997(ReferenceType->getElementCount() != ThisArgVecTy->getElementCount()))998return true;999return !ThisArgVecTy->getElementType()->isPointerTy();1000}1001case IITDescriptor::VecElementArgument: {1002if (D.getArgumentNumber() >= ArgTys.size())1003return IsDeferredCheck ? true : DeferCheck(Ty);1004auto *ReferenceType = dyn_cast<VectorType>(ArgTys[D.getArgumentNumber()]);1005return !ReferenceType || Ty != ReferenceType->getElementType();1006}1007case IITDescriptor::Subdivide2Argument:1008case IITDescriptor::Subdivide4Argument: {1009// If this is a forward reference, defer the check for later.1010if (D.getArgumentNumber() >= ArgTys.size())1011return IsDeferredCheck || DeferCheck(Ty);10121013Type *NewTy = ArgTys[D.getArgumentNumber()];1014if (auto *VTy = dyn_cast<VectorType>(NewTy)) {1015int SubDivs = D.Kind == IITDescriptor::Subdivide2Argument ? 1 : 2;1016NewTy = VectorType::getSubdividedVectorType(VTy, SubDivs);1017return Ty != NewTy;1018}1019return true;1020}1021case IITDescriptor::VecOfBitcastsToInt: {1022if (D.getArgumentNumber() >= ArgTys.size())1023return IsDeferredCheck || DeferCheck(Ty);1024auto *ReferenceType = dyn_cast<VectorType>(ArgTys[D.getArgumentNumber()]);1025auto *ThisArgVecTy = dyn_cast<VectorType>(Ty);1026if (!ThisArgVecTy || !ReferenceType)1027return true;1028return ThisArgVecTy != VectorType::getInteger(ReferenceType);1029}1030}1031llvm_unreachable("unhandled");1032}10331034Intrinsic::MatchIntrinsicTypesResult1035Intrinsic::matchIntrinsicSignature(FunctionType *FTy,1036ArrayRef<Intrinsic::IITDescriptor> &Infos,1037SmallVectorImpl<Type *> &ArgTys) {1038SmallVector<DeferredIntrinsicMatchPair, 2> DeferredChecks;1039if (matchIntrinsicType(FTy->getReturnType(), Infos, ArgTys, DeferredChecks,1040false))1041return MatchIntrinsicTypes_NoMatchRet;10421043unsigned NumDeferredReturnChecks = DeferredChecks.size();10441045for (auto *Ty : FTy->params())1046if (matchIntrinsicType(Ty, Infos, ArgTys, DeferredChecks, false))1047return MatchIntrinsicTypes_NoMatchArg;10481049for (unsigned I = 0, E = DeferredChecks.size(); I != E; ++I) {1050DeferredIntrinsicMatchPair &Check = DeferredChecks[I];1051if (matchIntrinsicType(Check.first, Check.second, ArgTys, DeferredChecks,1052true))1053return I < NumDeferredReturnChecks ? MatchIntrinsicTypes_NoMatchRet1054: MatchIntrinsicTypes_NoMatchArg;1055}10561057return MatchIntrinsicTypes_Match;1058}10591060bool Intrinsic::matchIntrinsicVarArg(1061bool isVarArg, ArrayRef<Intrinsic::IITDescriptor> &Infos) {1062// If there are no descriptors left, then it can't be a vararg.1063if (Infos.empty())1064return isVarArg;10651066// There should be only one descriptor remaining at this point.1067if (Infos.size() != 1)1068return true;10691070// Check and verify the descriptor.1071IITDescriptor D = Infos.front();1072Infos = Infos.slice(1);1073if (D.Kind == IITDescriptor::VarArg)1074return !isVarArg;10751076return true;1077}10781079bool Intrinsic::getIntrinsicSignature(Intrinsic::ID ID, FunctionType *FT,1080SmallVectorImpl<Type *> &ArgTys) {1081if (!ID)1082return false;10831084SmallVector<Intrinsic::IITDescriptor, 8> Table;1085getIntrinsicInfoTableEntries(ID, Table);1086ArrayRef<Intrinsic::IITDescriptor> TableRef = Table;10871088if (Intrinsic::matchIntrinsicSignature(FT, TableRef, ArgTys) !=1089Intrinsic::MatchIntrinsicTypesResult::MatchIntrinsicTypes_Match) {1090return false;1091}1092if (Intrinsic::matchIntrinsicVarArg(FT->isVarArg(), TableRef))1093return false;1094return true;1095}10961097bool Intrinsic::getIntrinsicSignature(Function *F,1098SmallVectorImpl<Type *> &ArgTys) {1099return getIntrinsicSignature(F->getIntrinsicID(), F->getFunctionType(),1100ArgTys);1101}11021103std::optional<Function *> Intrinsic::remangleIntrinsicFunction(Function *F) {1104SmallVector<Type *, 4> ArgTys;1105if (!getIntrinsicSignature(F, ArgTys))1106return std::nullopt;11071108Intrinsic::ID ID = F->getIntrinsicID();1109StringRef Name = F->getName();1110std::string WantedName =1111Intrinsic::getName(ID, ArgTys, F->getParent(), F->getFunctionType());1112if (Name == WantedName)1113return std::nullopt;11141115Function *NewDecl = [&] {1116if (auto *ExistingGV = F->getParent()->getNamedValue(WantedName)) {1117if (auto *ExistingF = dyn_cast<Function>(ExistingGV))1118if (ExistingF->getFunctionType() == F->getFunctionType())1119return ExistingF;11201121// The name already exists, but is not a function or has the wrong1122// prototype. Make place for the new one by renaming the old version.1123// Either this old version will be removed later on or the module is1124// invalid and we'll get an error.1125ExistingGV->setName(WantedName + ".renamed");1126}1127return Intrinsic::getOrInsertDeclaration(F->getParent(), ID, ArgTys);1128}();11291130NewDecl->setCallingConv(F->getCallingConv());1131assert(NewDecl->getFunctionType() == F->getFunctionType() &&1132"Shouldn't change the signature");1133return NewDecl;1134}113511361137