[IR] Add support for empty tokens
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 11 Nov 2015 21:57:16 +0000 (21:57 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 11 Nov 2015 21:57:16 +0000 (21:57 +0000)
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

14 files changed:
docs/LangRef.rst
include/llvm-c/Core.h
include/llvm/IR/Constants.h
include/llvm/IR/Value.def
lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/AsmParser/LLToken.h
lib/IR/AsmWriter.cpp
lib/IR/Constants.cpp
lib/IR/LLVMContextImpl.cpp
lib/IR/LLVMContextImpl.h
lib/Transforms/IPO/MergeFunctions.cpp
test/Assembler/token.ll

index c66df4ef6e92c9c555b1e37766d0a525cd11bcda..0e4eae0df804cae975170c38ebcd5955b4a1bbca 100644 (file)
@@ -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>`.
 **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
 
 The one non-intuitive notation for constants is the hexadecimal form of
 floating point constants. For example, the form
index 519363271ad57029c082fdfcda268aaaa759ef50..8157e9cf8695c6de812b7894fbcee8d6fe24070a 100644 (file)
@@ -1185,6 +1185,7 @@ LLVMTypeRef LLVMX86MMXType(void);
       macro(ConstantInt)                    \
       macro(ConstantPointerNull)            \
       macro(ConstantStruct)                 \
       macro(ConstantInt)                    \
       macro(ConstantPointerNull)            \
       macro(ConstantStruct)                 \
+      macro(ConstantTokenNone)              \
       macro(ConstantVector)                 \
       macro(GlobalValue)                    \
         macro(GlobalAlias)                  \
       macro(ConstantVector)                 \
       macro(GlobalValue)                    \
         macro(GlobalAlias)                  \
index 11ca8008f2953bdf2d916e6e8248e038c31d773c..a5a20c9c5701c1c917c508b7cbf3490f67970267 100644 (file)
@@ -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.
 ///
 
 /// BlockAddress - The address of a basic block.
 ///
index c2a0639603ed0907e91b5f5c366ff31593a86360..4c5d452fc3c344d37fa7237817be2a3a4888595e 100644 (file)
@@ -70,6 +70,7 @@ HANDLE_CONSTANT(ConstantArray)
 HANDLE_CONSTANT(ConstantStruct)
 HANDLE_CONSTANT(ConstantVector)
 HANDLE_CONSTANT(ConstantPointerNull)
 HANDLE_CONSTANT(ConstantStruct)
 HANDLE_CONSTANT(ConstantVector)
 HANDLE_CONSTANT(ConstantPointerNull)
+HANDLE_CONSTANT(ConstantTokenNone)
 
 HANDLE_METADATA_VALUE(MetadataAsValue)
 HANDLE_INLINE_ASM_VALUE(InlineAsm)
 
 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)
 // 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
 
 #undef HANDLE_GLOBAL_VALUE
 #undef HANDLE_CONSTANT
index 91ce1fd7669dfebba2dc27b9c0048f70b1002c8f..372c565888647bc0e29e6051cc7bddb2ebf1eb89 100644 (file)
@@ -523,6 +523,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(zeroinitializer);
   KEYWORD(undef);
   KEYWORD(null);
   KEYWORD(zeroinitializer);
   KEYWORD(undef);
   KEYWORD(null);
+  KEYWORD(none);
   KEYWORD(to);
   KEYWORD(caller);
   KEYWORD(tail);
   KEYWORD(to);
   KEYWORD(caller);
   KEYWORD(tail);
index aabd9716118fd32124f6e78d7152b7e3cbd62020..2c6e8081c13646d412e981b333f1025c16ee9de0 100644 (file)
@@ -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_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 '}'
 
   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;
       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");
   case ValID::t_Constant:
     if (ID.ConstantVal->getType() != Ty)
       return Error(ID.Loc, "constant expression type mismatch");
index 24ff8e750237a86e768fd070676cc46259c25a21..d4384db9bf034e08d9e9ff34efec48aca6fa71fa 100644 (file)
@@ -46,15 +46,15 @@ namespace llvm {
   /// or a symbolic (%var) reference.  This is just a discriminated union.
   struct ValID {
     enum {
   /// 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;
     } Kind = t_LocalID;
 
     LLLexer::LocTy Loc;
index 6980790c098dcf47b932de2c5e2cab8061083b14..6a9a1de0b85092813d55b3108da4c9f7fa2e2692 100644 (file)
@@ -49,7 +49,7 @@ namespace lltok {
     kw_external, kw_thread_local,
     kw_localdynamic, kw_initialexec, kw_localexec,
     kw_zeroinitializer,
     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,
     kw_to,
     kw_caller,
     kw_tail,
index aaa719eda7e11c2dd780b8e8ab625413c86b4be4..759c5a8001c00158947e1b701e787f7b95812c4b 100644 (file)
@@ -1328,6 +1328,11 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
     return;
   }
 
     return;
   }
 
+  if (isa<ConstantTokenNone>(CV)) {
+    Out << "none";
+    return;
+  }
+
   if (isa<UndefValue>(CV)) {
     Out << "undef";
     return;
   if (isa<UndefValue>(CV)) {
     Out << "undef";
     return;
index 798ea2470fadc4f16e554b3279834abdd3b58861..74d42c71de843918b96c59c1687b184ac488cd2b 100644 (file)
@@ -81,8 +81,10 @@ bool Constant::isNullValue() const {
   if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
     return CFP->isZero() && !CFP->isNegative();
 
   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 {
 }
 
 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::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!");
   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);
 }
 
   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
 
 // 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()!");
 }
 
   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()!");
 }
 Value *UndefValue::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
   llvm_unreachable("Unsupported class for handleOperandChange()!");
 }
index 5239b4f7d84a6099b7a445f44f9963c1005c1fc9..48df5ba62f049f6b8d21aea42e9d33fb20bba8e5 100644 (file)
@@ -21,6 +21,7 @@ using namespace llvm;
 
 LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
   : TheTrueVal(nullptr), TheFalseVal(nullptr),
 
 LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
   : TheTrueVal(nullptr), TheFalseVal(nullptr),
+    TheNoneToken(nullptr),
     VoidTy(C, Type::VoidTyID),
     LabelTy(C, Type::LabelTyID),
     HalfTy(C, Type::HalfTyID),
     VoidTy(C, Type::VoidTyID),
     LabelTy(C, Type::LabelTyID),
     HalfTy(C, Type::HalfTyID),
index 24f22b43fc074c7f6f8783f36a9eefa58f2d4899..3403cd4acfbb7a35bc7630689e6437b7cc249678 100644 (file)
@@ -924,6 +924,8 @@ public:
   ConstantInt *TheTrueVal;
   ConstantInt *TheFalseVal;
 
   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;
   // Basic type instances.
   Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy, TokenTy;
   Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy;
index 762741b72bff1eccb1d77d17ae31655f02c76564..bb75ab6ece16aa0b3c3e94025dc8e0d949a65b61 100644 (file)
@@ -656,7 +656,9 @@ int FunctionComparator::cmpConstants(const Constant *L, const Constant *R) {
   }
 
   switch (L->getValueID()) {
   }
 
   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();
   case Value::ConstantIntVal: {
     const APInt &LInt = cast<ConstantInt>(L)->getValue();
     const APInt &RInt = cast<ConstantInt>(R)->getValue();
index 22d71b0b730b22ffffbf38120f74c654b6be286c..c4d68b4b3ffb0d31f912e8e27e5baee53df85311 100644 (file)
@@ -4,3 +4,8 @@
 
 ; CHECK: declare void @llvm.token.foobar(token)
 declare void @llvm.token.foobar(token)
 
 ; 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
+}