mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
13605b24cd
This patch adds support for intrinsic overloading on unnamed types. This fixes PR38117 and PR48340 and will also be needed for the Full Restrict Patches (D68484). The main problem is that the intrinsic overloading name mangling is using 's_s' for unnamed types. This can result in identical intrinsic mangled names for different function prototypes. This patch changes this by adding a '.XXXXX' to the intrinsic mangled name when at least one of the types is based on an unnamed type, ensuring that we get a unique name. Implementation details: - The mapping is created on demand and kept in Module. - It also checks for existing clashes and recycles potentially existing prototypes and declarations. - Because of extra data in Module, Intrinsic::getName needs an extra Module* argument and, for speed, an optional FunctionType* argument. - I still kept the original two-argument 'Intrinsic::getName' around which keeps the original behavior (providing the base name). -- Main reason is that I did not want to change the LLVMIntrinsicGetName version, as I don't know how acceptable such a change is -- The current situation already has a limitation. So that should not get worse with this patch. - Intrinsic::getDeclaration and the verifier are now using the new version. Other notes: - As far as I see, this should not suffer from stability issues. The count is only added for prototypes depending on at least one anonymous struct - The initial count starts from 0 for each intrinsic mangled name. - In case of name clashes, existing prototypes are remembered and reused when that makes sense. Reviewed By: fhahn Differential Revision: https://reviews.llvm.org/D91250
252 lines
8.9 KiB
C++
252 lines
8.9 KiB
C++
//===- Intrinsics.h - LLVM Intrinsic Function Handling ----------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines a set of enums which allow processing of intrinsic
|
|
// functions. Values of these enum types are returned by
|
|
// Function::getIntrinsicID.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_IR_INTRINSICS_H
|
|
#define LLVM_IR_INTRINSICS_H
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/None.h"
|
|
#include "llvm/ADT/Optional.h"
|
|
#include "llvm/Support/TypeSize.h"
|
|
#include <string>
|
|
|
|
namespace llvm {
|
|
|
|
class Type;
|
|
class FunctionType;
|
|
class Function;
|
|
class LLVMContext;
|
|
class Module;
|
|
class AttributeList;
|
|
|
|
/// This namespace contains an enum with a value for every intrinsic/builtin
|
|
/// function known by LLVM. The enum values are returned by
|
|
/// Function::getIntrinsicID().
|
|
namespace Intrinsic {
|
|
// Abstraction for the arguments of the noalias intrinsics
|
|
static const int NoAliasScopeDeclScopeArg = 0;
|
|
|
|
// Intrinsic ID type. This is an opaque typedef to facilitate splitting up
|
|
// the enum into target-specific enums.
|
|
typedef unsigned ID;
|
|
|
|
enum IndependentIntrinsics : unsigned {
|
|
not_intrinsic = 0, // Must be zero
|
|
|
|
// Get the intrinsic enums generated from Intrinsics.td
|
|
#define GET_INTRINSIC_ENUM_VALUES
|
|
#include "llvm/IR/IntrinsicEnums.inc"
|
|
#undef GET_INTRINSIC_ENUM_VALUES
|
|
};
|
|
|
|
/// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
|
|
/// Note, this version is for intrinsics with no overloads. Use the other
|
|
/// version of getName if overloads are required.
|
|
StringRef getName(ID id);
|
|
|
|
/// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
|
|
/// Note, this version of getName supports overloads, but not unnamed types.
|
|
/// It is less efficient than the StringRef version of this function. If no
|
|
/// overloads are required, it is safe to use this version, but better to use
|
|
/// the StringRef version.
|
|
std::string getName(ID Id, ArrayRef<Type *> Tys);
|
|
|
|
/// Return the LLVM name for an intrinsic, such as "llvm.ssa.copy.p0s_s.1".
|
|
/// Note, this version of getName supports overloads and unnamed types, but is
|
|
/// less efficient than the StringRef version of this function. If no
|
|
/// overloads are required, it is safe to use this version, but better to use
|
|
/// the StringRef version. A function type FT can be provided to avoid
|
|
/// computing it. It is used (or computed) if one of the types is based on an
|
|
/// unnamed type.
|
|
std::string getName(ID Id, ArrayRef<Type *> Tys, Module *M, FunctionType *FT);
|
|
|
|
/// Return the function type for an intrinsic.
|
|
FunctionType *getType(LLVMContext &Context, ID id,
|
|
ArrayRef<Type*> Tys = None);
|
|
|
|
/// Returns true if the intrinsic can be overloaded.
|
|
bool isOverloaded(ID id);
|
|
|
|
/// Returns true if the intrinsic is a leaf, i.e. it does not make any calls
|
|
/// itself. Most intrinsics are leafs, the exceptions being the patchpoint
|
|
/// and statepoint intrinsics. These call (or invoke) their "target" argument.
|
|
bool isLeaf(ID id);
|
|
|
|
/// Return the attributes for an intrinsic.
|
|
AttributeList getAttributes(LLVMContext &C, ID id);
|
|
|
|
/// Create or insert an LLVM Function declaration for an intrinsic, and return
|
|
/// it.
|
|
///
|
|
/// The Tys parameter is for intrinsics with overloaded types (e.g., those
|
|
/// using iAny, fAny, vAny, or iPTRAny). For a declaration of an overloaded
|
|
/// intrinsic, Tys must provide exactly one type for each overloaded type in
|
|
/// the intrinsic.
|
|
Function *getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys = None);
|
|
|
|
/// Looks up Name in NameTable via binary search. NameTable must be sorted
|
|
/// and all entries must start with "llvm.". If NameTable contains an exact
|
|
/// match for Name or a prefix of Name followed by a dot, its index in
|
|
/// NameTable is returned. Otherwise, -1 is returned.
|
|
int lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
|
|
StringRef Name);
|
|
|
|
/// Map a GCC builtin name to an intrinsic ID.
|
|
ID getIntrinsicForGCCBuiltin(const char *Prefix, StringRef BuiltinName);
|
|
|
|
/// Map a MS builtin name to an intrinsic ID.
|
|
ID getIntrinsicForMSBuiltin(const char *Prefix, StringRef BuiltinName);
|
|
|
|
/// This is a type descriptor which explains the type requirements of an
|
|
/// intrinsic. This is returned by getIntrinsicInfoTableEntries.
|
|
struct IITDescriptor {
|
|
enum IITDescriptorKind {
|
|
Void,
|
|
VarArg,
|
|
MMX,
|
|
Token,
|
|
Metadata,
|
|
Half,
|
|
BFloat,
|
|
Float,
|
|
Double,
|
|
Quad,
|
|
Integer,
|
|
Vector,
|
|
Pointer,
|
|
Struct,
|
|
Argument,
|
|
ExtendArgument,
|
|
TruncArgument,
|
|
HalfVecArgument,
|
|
SameVecWidthArgument,
|
|
PtrToArgument,
|
|
PtrToElt,
|
|
VecOfAnyPtrsToElt,
|
|
VecElementArgument,
|
|
Subdivide2Argument,
|
|
Subdivide4Argument,
|
|
VecOfBitcastsToInt,
|
|
AMX
|
|
} Kind;
|
|
|
|
union {
|
|
unsigned Integer_Width;
|
|
unsigned Float_Width;
|
|
unsigned Pointer_AddressSpace;
|
|
unsigned Struct_NumElements;
|
|
unsigned Argument_Info;
|
|
ElementCount Vector_Width;
|
|
};
|
|
|
|
enum ArgKind {
|
|
AK_Any,
|
|
AK_AnyInteger,
|
|
AK_AnyFloat,
|
|
AK_AnyVector,
|
|
AK_AnyPointer,
|
|
AK_MatchType = 7
|
|
};
|
|
|
|
unsigned getArgumentNumber() const {
|
|
assert(Kind == Argument || Kind == ExtendArgument ||
|
|
Kind == TruncArgument || Kind == HalfVecArgument ||
|
|
Kind == SameVecWidthArgument || Kind == PtrToArgument ||
|
|
Kind == PtrToElt || Kind == VecElementArgument ||
|
|
Kind == Subdivide2Argument || Kind == Subdivide4Argument ||
|
|
Kind == VecOfBitcastsToInt);
|
|
return Argument_Info >> 3;
|
|
}
|
|
ArgKind getArgumentKind() const {
|
|
assert(Kind == Argument || Kind == ExtendArgument ||
|
|
Kind == TruncArgument || Kind == HalfVecArgument ||
|
|
Kind == SameVecWidthArgument || Kind == PtrToArgument ||
|
|
Kind == VecElementArgument || Kind == Subdivide2Argument ||
|
|
Kind == Subdivide4Argument || Kind == VecOfBitcastsToInt);
|
|
return (ArgKind)(Argument_Info & 7);
|
|
}
|
|
|
|
// VecOfAnyPtrsToElt uses both an overloaded argument (for address space)
|
|
// and a reference argument (for matching vector width and element types)
|
|
unsigned getOverloadArgNumber() const {
|
|
assert(Kind == VecOfAnyPtrsToElt);
|
|
return Argument_Info >> 16;
|
|
}
|
|
unsigned getRefArgNumber() const {
|
|
assert(Kind == VecOfAnyPtrsToElt);
|
|
return Argument_Info & 0xFFFF;
|
|
}
|
|
|
|
static IITDescriptor get(IITDescriptorKind K, unsigned Field) {
|
|
IITDescriptor Result = { K, { Field } };
|
|
return Result;
|
|
}
|
|
|
|
static IITDescriptor get(IITDescriptorKind K, unsigned short Hi,
|
|
unsigned short Lo) {
|
|
unsigned Field = Hi << 16 | Lo;
|
|
IITDescriptor Result = {K, {Field}};
|
|
return Result;
|
|
}
|
|
|
|
static IITDescriptor getVector(unsigned Width, bool IsScalable) {
|
|
IITDescriptor Result = {Vector, {0}};
|
|
Result.Vector_Width = ElementCount::get(Width, IsScalable);
|
|
return Result;
|
|
}
|
|
};
|
|
|
|
/// Return the IIT table descriptor for the specified intrinsic into an array
|
|
/// of IITDescriptors.
|
|
void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
|
|
|
|
enum MatchIntrinsicTypesResult {
|
|
MatchIntrinsicTypes_Match = 0,
|
|
MatchIntrinsicTypes_NoMatchRet = 1,
|
|
MatchIntrinsicTypes_NoMatchArg = 2,
|
|
};
|
|
|
|
/// Match the specified function type with the type constraints specified by
|
|
/// the .td file. If the given type is an overloaded type it is pushed to the
|
|
/// ArgTys vector.
|
|
///
|
|
/// Returns false if the given type matches with the constraints, true
|
|
/// otherwise.
|
|
MatchIntrinsicTypesResult
|
|
matchIntrinsicSignature(FunctionType *FTy, ArrayRef<IITDescriptor> &Infos,
|
|
SmallVectorImpl<Type *> &ArgTys);
|
|
|
|
/// Verify if the intrinsic has variable arguments. This method is intended to
|
|
/// be called after all the fixed arguments have been matched first.
|
|
///
|
|
/// This method returns true on error.
|
|
bool matchIntrinsicVarArg(bool isVarArg, ArrayRef<IITDescriptor> &Infos);
|
|
|
|
/// Gets the type arguments of an intrinsic call by matching type contraints
|
|
/// specified by the .td file. The overloaded types are pushed into the
|
|
/// AgTys vector.
|
|
///
|
|
/// Returns false if the given function is not a valid intrinsic call.
|
|
bool getIntrinsicSignature(Function *F, SmallVectorImpl<Type *> &ArgTys);
|
|
|
|
// Checks if the intrinsic name matches with its signature and if not
|
|
// returns the declaration with the same signature and remangled name.
|
|
llvm::Optional<Function*> remangleIntrinsicFunction(Function *F);
|
|
|
|
} // End Intrinsic namespace
|
|
|
|
} // End llvm namespace
|
|
|
|
#endif
|