From: David Majnemer Date: Wed, 11 Nov 2015 21:57:16 +0000 (+0000) Subject: [IR] Add support for empty tokens X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=83fc12aeed03b6423fdf973ad4ae351202fe0982 [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 --- diff --git a/docs/LangRef.rst b/docs/LangRef.rst index c66df4ef6e9..0e4eae0df80 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -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 `. +**Token constants** + The identifier '``none``' is recognized as an empty token constant + and must be of :ref:`token type `. The one non-intuitive notation for constants is the hexadecimal form of floating point constants. For example, the form diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 519363271ad..8157e9cf869 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -1185,6 +1185,7 @@ LLVMTypeRef LLVMX86MMXType(void); macro(ConstantInt) \ macro(ConstantPointerNull) \ macro(ConstantStruct) \ + macro(ConstantTokenNone) \ macro(ConstantVector) \ macro(GlobalValue) \ macro(GlobalAlias) \ diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 11ca8008f29..a5a20c9c570 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -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. /// diff --git a/include/llvm/IR/Value.def b/include/llvm/IR/Value.def index c2a0639603e..4c5d452fc3c 100644 --- a/include/llvm/IR/Value.def +++ b/include/llvm/IR/Value.def @@ -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 diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 91ce1fd7669..372c5658886 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -523,6 +523,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(zeroinitializer); KEYWORD(undef); KEYWORD(null); + KEYWORD(none); KEYWORD(to); KEYWORD(caller); KEYWORD(tail); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index aabd9716118..2c6e8081c13 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -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"); diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 24ff8e75023..d4384db9bf0 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -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; diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 6980790c098..6a9a1de0b85 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -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, diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index aaa719eda7e..759c5a8001c 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1328,6 +1328,11 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, return; } + if (isa(CV)) { + Out << "none"; + return; + } + if (isa(CV)) { Out << "undef"; return; diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index 798ea2470fa..74d42c71de8 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -81,8 +81,10 @@ bool Constant::isNullValue() const { if (const ConstantFP *CFP = dyn_cast(this)) return CFP->isZero() && !CFP->isNegative(); - // constant zero is zero for aggregates and cpnull is null for pointers. - return isa(this) || isa(this); + // constant zero is zero for aggregates, cpnull is null for pointers, none for + // tokens. + return isa(this) || isa(this) || + isa(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()!"); } diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 5239b4f7d84..48df5ba62f0 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -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), diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 24f22b43fc0..3403cd4acfb 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -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; diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index 762741b72bf..bb75ab6ece1 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -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(L)->getValue(); const APInt &RInt = cast(R)->getValue(); diff --git a/test/Assembler/token.ll b/test/Assembler/token.ll index 22d71b0b730..c4d68b4b3ff 100644 --- a/test/Assembler/token.ll +++ b/test/Assembler/token.ll @@ -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 +}