mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-23 11:49:50 +00:00
[IR] Add support for empty tokens
When working with tokens, it is often the case that one has instructions which consume a token and produce a new token. Currently, we have no mechanism to represent an initial token state. Instead, we can create a notional "empty token" by inventing a new constant which captures the semantics we would like. This new constant is called ConstantTokenNone and is written textually as "token none". Differential Revision: http://reviews.llvm.org/D14581 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252811 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ab31dd0add
commit
83fc12aeed
@ -2434,6 +2434,9 @@ Simple Constants
|
||||
**Null pointer constants**
|
||||
The identifier '``null``' is recognized as a null pointer constant
|
||||
and must be of :ref:`pointer type <t_pointer>`.
|
||||
**Token constants**
|
||||
The identifier '``none``' is recognized as an empty token constant
|
||||
and must be of :ref:`token type <t_token>`.
|
||||
|
||||
The one non-intuitive notation for constants is the hexadecimal form of
|
||||
floating point constants. For example, the form
|
||||
|
@ -1185,6 +1185,7 @@ LLVMTypeRef LLVMX86MMXType(void);
|
||||
macro(ConstantInt) \
|
||||
macro(ConstantPointerNull) \
|
||||
macro(ConstantStruct) \
|
||||
macro(ConstantTokenNone) \
|
||||
macro(ConstantVector) \
|
||||
macro(GlobalValue) \
|
||||
macro(GlobalAlias) \
|
||||
|
@ -795,7 +795,32 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// ConstantTokenNone - a constant token which is empty
|
||||
///
|
||||
class ConstantTokenNone : public Constant {
|
||||
void *operator new(size_t, unsigned) = delete;
|
||||
ConstantTokenNone(const ConstantTokenNone &) = delete;
|
||||
|
||||
friend class Constant;
|
||||
void destroyConstantImpl();
|
||||
Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
|
||||
|
||||
protected:
|
||||
explicit ConstantTokenNone(LLVMContext &Context)
|
||||
: Constant(Type::getTokenTy(Context), ConstantTokenNoneVal, nullptr, 0) {}
|
||||
// allocate space for exactly zero operands
|
||||
void *operator new(size_t s) { return User::operator new(s, 0); }
|
||||
|
||||
public:
|
||||
/// Return the ConstantTokenNone.
|
||||
static ConstantTokenNone *get(LLVMContext &Context);
|
||||
|
||||
/// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
|
||||
static bool classof(const Value *V) {
|
||||
return V->getValueID() == ConstantTokenNoneVal;
|
||||
}
|
||||
};
|
||||
|
||||
/// BlockAddress - The address of a basic block.
|
||||
///
|
||||
|
@ -70,6 +70,7 @@ HANDLE_CONSTANT(ConstantArray)
|
||||
HANDLE_CONSTANT(ConstantStruct)
|
||||
HANDLE_CONSTANT(ConstantVector)
|
||||
HANDLE_CONSTANT(ConstantPointerNull)
|
||||
HANDLE_CONSTANT(ConstantTokenNone)
|
||||
|
||||
HANDLE_METADATA_VALUE(MetadataAsValue)
|
||||
HANDLE_INLINE_ASM_VALUE(InlineAsm)
|
||||
@ -79,7 +80,7 @@ HANDLE_INSTRUCTION(Instruction)
|
||||
// don't add new values here!
|
||||
|
||||
HANDLE_CONSTANT_MARKER(ConstantFirstVal, Function)
|
||||
HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantPointerNull)
|
||||
HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantTokenNone)
|
||||
|
||||
#undef HANDLE_GLOBAL_VALUE
|
||||
#undef HANDLE_CONSTANT
|
||||
|
@ -523,6 +523,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(zeroinitializer);
|
||||
KEYWORD(undef);
|
||||
KEYWORD(null);
|
||||
KEYWORD(none);
|
||||
KEYWORD(to);
|
||||
KEYWORD(caller);
|
||||
KEYWORD(tail);
|
||||
|
@ -2622,6 +2622,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
|
||||
case lltok::kw_null: ID.Kind = ValID::t_Null; break;
|
||||
case lltok::kw_undef: ID.Kind = ValID::t_Undef; break;
|
||||
case lltok::kw_zeroinitializer: ID.Kind = ValID::t_Zero; break;
|
||||
case lltok::kw_none: ID.Kind = ValID::t_None; break;
|
||||
|
||||
case lltok::lbrace: {
|
||||
// ValID ::= '{' ConstVector '}'
|
||||
@ -4255,6 +4256,11 @@ bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
|
||||
return Error(ID.Loc, "invalid type for null constant");
|
||||
V = Constant::getNullValue(Ty);
|
||||
return false;
|
||||
case ValID::t_None:
|
||||
if (!Ty->isTokenTy())
|
||||
return Error(ID.Loc, "invalid type for none constant");
|
||||
V = Constant::getNullValue(Ty);
|
||||
return false;
|
||||
case ValID::t_Constant:
|
||||
if (ID.ConstantVal->getType() != Ty)
|
||||
return Error(ID.Loc, "constant expression type mismatch");
|
||||
|
@ -46,15 +46,15 @@ namespace llvm {
|
||||
/// or a symbolic (%var) reference. This is just a discriminated union.
|
||||
struct ValID {
|
||||
enum {
|
||||
t_LocalID, t_GlobalID, // ID in UIntVal.
|
||||
t_LocalName, t_GlobalName, // Name in StrVal.
|
||||
t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal.
|
||||
t_Null, t_Undef, t_Zero, // No value.
|
||||
t_EmptyArray, // No value: []
|
||||
t_Constant, // Value in ConstantVal.
|
||||
t_InlineAsm, // Value in FTy/StrVal/StrVal2/UIntVal.
|
||||
t_ConstantStruct, // Value in ConstantStructElts.
|
||||
t_PackedConstantStruct // Value in ConstantStructElts.
|
||||
t_LocalID, t_GlobalID, // ID in UIntVal.
|
||||
t_LocalName, t_GlobalName, // Name in StrVal.
|
||||
t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal.
|
||||
t_Null, t_Undef, t_Zero, t_None, // No value.
|
||||
t_EmptyArray, // No value: []
|
||||
t_Constant, // Value in ConstantVal.
|
||||
t_InlineAsm, // Value in FTy/StrVal/StrVal2/UIntVal.
|
||||
t_ConstantStruct, // Value in ConstantStructElts.
|
||||
t_PackedConstantStruct // Value in ConstantStructElts.
|
||||
} Kind = t_LocalID;
|
||||
|
||||
LLLexer::LocTy Loc;
|
||||
|
@ -49,7 +49,7 @@ namespace lltok {
|
||||
kw_external, kw_thread_local,
|
||||
kw_localdynamic, kw_initialexec, kw_localexec,
|
||||
kw_zeroinitializer,
|
||||
kw_undef, kw_null,
|
||||
kw_undef, kw_null, kw_none,
|
||||
kw_to,
|
||||
kw_caller,
|
||||
kw_tail,
|
||||
|
@ -1328,6 +1328,11 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
|
||||
return;
|
||||
}
|
||||
|
||||
if (isa<ConstantTokenNone>(CV)) {
|
||||
Out << "none";
|
||||
return;
|
||||
}
|
||||
|
||||
if (isa<UndefValue>(CV)) {
|
||||
Out << "undef";
|
||||
return;
|
||||
|
@ -81,8 +81,10 @@ bool Constant::isNullValue() const {
|
||||
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
|
||||
return CFP->isZero() && !CFP->isNegative();
|
||||
|
||||
// constant zero is zero for aggregates and cpnull is null for pointers.
|
||||
return isa<ConstantAggregateZero>(this) || isa<ConstantPointerNull>(this);
|
||||
// constant zero is zero for aggregates, cpnull is null for pointers, none for
|
||||
// tokens.
|
||||
return isa<ConstantAggregateZero>(this) || isa<ConstantPointerNull>(this) ||
|
||||
isa<ConstantTokenNone>(this);
|
||||
}
|
||||
|
||||
bool Constant::isAllOnesValue() const {
|
||||
@ -204,6 +206,8 @@ Constant *Constant::getNullValue(Type *Ty) {
|
||||
case Type::ArrayTyID:
|
||||
case Type::VectorTyID:
|
||||
return ConstantAggregateZero::get(Ty);
|
||||
case Type::TokenTyID:
|
||||
return ConstantTokenNone::get(Ty->getContext());
|
||||
default:
|
||||
// Function, Label, or Opaque type?
|
||||
llvm_unreachable("Cannot create a null constant of that type!");
|
||||
@ -1170,6 +1174,17 @@ Constant *ConstantVector::getSplat(unsigned NumElts, Constant *V) {
|
||||
return get(Elts);
|
||||
}
|
||||
|
||||
ConstantTokenNone *ConstantTokenNone::get(LLVMContext &Context) {
|
||||
LLVMContextImpl *pImpl = Context.pImpl;
|
||||
if (!pImpl->TheNoneToken)
|
||||
pImpl->TheNoneToken = new ConstantTokenNone(Context);
|
||||
return pImpl->TheNoneToken;
|
||||
}
|
||||
|
||||
/// Remove the constant from the constant table.
|
||||
void ConstantTokenNone::destroyConstantImpl() {
|
||||
llvm_unreachable("You can't ConstantTokenNone->destroyConstantImpl()!");
|
||||
}
|
||||
|
||||
// Utility function for determining if a ConstantExpr is a CastOp or not. This
|
||||
// can't be inline because we don't want to #include Instruction.h into
|
||||
@ -2875,6 +2890,11 @@ Value *ConstantFP::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
|
||||
llvm_unreachable("Unsupported class for handleOperandChange()!");
|
||||
}
|
||||
|
||||
Value *ConstantTokenNone::handleOperandChangeImpl(Value *From, Value *To,
|
||||
Use *U) {
|
||||
llvm_unreachable("Unsupported class for handleOperandChange()!");
|
||||
}
|
||||
|
||||
Value *UndefValue::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
|
||||
llvm_unreachable("Unsupported class for handleOperandChange()!");
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ using namespace llvm;
|
||||
|
||||
LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
|
||||
: TheTrueVal(nullptr), TheFalseVal(nullptr),
|
||||
TheNoneToken(nullptr),
|
||||
VoidTy(C, Type::VoidTyID),
|
||||
LabelTy(C, Type::LabelTyID),
|
||||
HalfTy(C, Type::HalfTyID),
|
||||
|
@ -924,6 +924,8 @@ public:
|
||||
ConstantInt *TheTrueVal;
|
||||
ConstantInt *TheFalseVal;
|
||||
|
||||
ConstantTokenNone *TheNoneToken;
|
||||
|
||||
// Basic type instances.
|
||||
Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy, TokenTy;
|
||||
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy;
|
||||
|
@ -656,7 +656,9 @@ int FunctionComparator::cmpConstants(const Constant *L, const Constant *R) {
|
||||
}
|
||||
|
||||
switch (L->getValueID()) {
|
||||
case Value::UndefValueVal: return TypesRes;
|
||||
case Value::UndefValueVal:
|
||||
case Value::ConstantTokenNoneVal:
|
||||
return TypesRes;
|
||||
case Value::ConstantIntVal: {
|
||||
const APInt &LInt = cast<ConstantInt>(L)->getValue();
|
||||
const APInt &RInt = cast<ConstantInt>(R)->getValue();
|
||||
|
@ -4,3 +4,8 @@
|
||||
|
||||
; CHECK: declare void @llvm.token.foobar(token)
|
||||
declare void @llvm.token.foobar(token)
|
||||
|
||||
define void @f() {
|
||||
call void @llvm.token.foobar(token none)
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user