Skip to content

Commit

Permalink
[IR] Add support for empty tokens
Browse files Browse the repository at this point in the history
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

llvm-svn: 252811
  • Loading branch information
majnemer committed Nov 11, 2015
1 parent 77f211c commit f0f224d
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 14 deletions.
3 changes: 3 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(ConstantInt) \
macro(ConstantPointerNull) \
macro(ConstantStruct) \
macro(ConstantTokenNone) \
macro(ConstantVector) \
macro(GlobalValue) \
macro(GlobalAlias) \
Expand Down
25 changes: 25 additions & 0 deletions llvm/include/llvm/IR/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,32 @@ class ConstantDataVector : public ConstantDataSequential {
}
};

//===----------------------------------------------------------------------===//
/// 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.
///
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/IR/Value.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(zeroinitializer);
KEYWORD(undef);
KEYWORD(null);
KEYWORD(none);
KEYWORD(to);
KEYWORD(caller);
KEYWORD(tail);
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 '}'
Expand Down Expand Up @@ -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");
Expand Down
18 changes: 9 additions & 9 deletions llvm/lib/AsmParser/LLParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
24 changes: 22 additions & 2 deletions llvm/lib/IR/Constants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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!");
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()!");
}
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/LLVMContextImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/IR/LLVMContextImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,8 @@ class LLVMContextImpl {
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;
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Transforms/IPO/MergeFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions llvm/test/Assembler/token.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit f0f224d

Please sign in to comment.