in lib/AsmParser/LLParser.cpp [2385:2939]
bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
ID.Loc = Lex.getLoc();
switch (Lex.getKind()) {
default: return TokError("expected value token");
case lltok::GlobalID: // @42
ID.UIntVal = Lex.getUIntVal();
ID.Kind = ValID::t_GlobalID;
break;
case lltok::GlobalVar: // @foo
ID.StrVal = Lex.getStrVal();
ID.Kind = ValID::t_GlobalName;
break;
case lltok::LocalVarID: // %42
ID.UIntVal = Lex.getUIntVal();
ID.Kind = ValID::t_LocalID;
break;
case lltok::LocalVar: // %foo
ID.StrVal = Lex.getStrVal();
ID.Kind = ValID::t_LocalName;
break;
case lltok::APSInt:
ID.APSIntVal = Lex.getAPSIntVal();
ID.Kind = ValID::t_APSInt;
break;
case lltok::APFloat:
ID.APFloatVal = Lex.getAPFloatVal();
ID.Kind = ValID::t_APFloat;
break;
case lltok::kw_true:
ID.ConstantVal = ConstantInt::getTrue(Context);
ID.Kind = ValID::t_Constant;
break;
case lltok::kw_false:
ID.ConstantVal = ConstantInt::getFalse(Context);
ID.Kind = ValID::t_Constant;
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::lbrace: {
// ValID ::= '{' ConstVector '}'
Lex.Lex();
SmallVector<Constant*, 16> Elts;
if (ParseGlobalValueVector(Elts) ||
ParseToken(lltok::rbrace, "expected end of struct constant"))
return true;
ID.ConstantStructElts = new Constant*[Elts.size()];
ID.UIntVal = Elts.size();
memcpy(ID.ConstantStructElts, Elts.data(), Elts.size()*sizeof(Elts[0]));
ID.Kind = ValID::t_ConstantStruct;
return false;
}
case lltok::less: {
// ValID ::= '<' ConstVector '>' --> Vector.
// ValID ::= '<' '{' ConstVector '}' '>' --> Packed Struct.
Lex.Lex();
bool isPackedStruct = EatIfPresent(lltok::lbrace);
SmallVector<Constant*, 16> Elts;
LocTy FirstEltLoc = Lex.getLoc();
if (ParseGlobalValueVector(Elts) ||
(isPackedStruct &&
ParseToken(lltok::rbrace, "expected end of packed struct")) ||
ParseToken(lltok::greater, "expected end of constant"))
return true;
if (isPackedStruct) {
ID.ConstantStructElts = new Constant*[Elts.size()];
memcpy(ID.ConstantStructElts, Elts.data(), Elts.size()*sizeof(Elts[0]));
ID.UIntVal = Elts.size();
ID.Kind = ValID::t_PackedConstantStruct;
return false;
}
if (Elts.empty())
return Error(ID.Loc, "constant vector must not be empty");
if (!Elts[0]->getType()->isIntegerTy() &&
!Elts[0]->getType()->isFloatingPointTy() &&
!Elts[0]->getType()->isPointerTy())
return Error(FirstEltLoc,
"vector elements must have integer, pointer or floating point type");
// Verify that all the vector elements have the same type.
for (unsigned i = 1, e = Elts.size(); i != e; ++i)
if (Elts[i]->getType() != Elts[0]->getType())
return Error(FirstEltLoc,
"vector element #" + Twine(i) +
" is not of type '" + getTypeString(Elts[0]->getType()));
ID.ConstantVal = ConstantVector::get(Elts);
ID.Kind = ValID::t_Constant;
return false;
}
case lltok::lsquare: { // Array Constant
Lex.Lex();
SmallVector<Constant*, 16> Elts;
LocTy FirstEltLoc = Lex.getLoc();
if (ParseGlobalValueVector(Elts) ||
ParseToken(lltok::rsquare, "expected end of array constant"))
return true;
// Handle empty element.
if (Elts.empty()) {
// Use undef instead of an array because it's inconvenient to determine
// the element type at this point, there being no elements to examine.
ID.Kind = ValID::t_EmptyArray;
return false;
}
if (!Elts[0]->getType()->isFirstClassType())
return Error(FirstEltLoc, "invalid array element type: " +
getTypeString(Elts[0]->getType()));
ArrayType *ATy = ArrayType::get(Elts[0]->getType(), Elts.size());
// Verify all elements are correct type!
for (unsigned i = 0, e = Elts.size(); i != e; ++i) {
if (Elts[i]->getType() != Elts[0]->getType())
return Error(FirstEltLoc,
"array element #" + Twine(i) +
" is not of type '" + getTypeString(Elts[0]->getType()));
}
ID.ConstantVal = ConstantArray::get(ATy, Elts);
ID.Kind = ValID::t_Constant;
return false;
}
case lltok::kw_c: // c "foo"
Lex.Lex();
ID.ConstantVal = ConstantDataArray::getString(Context, Lex.getStrVal(),
false);
if (ParseToken(lltok::StringConstant, "expected string")) return true;
ID.Kind = ValID::t_Constant;
return false;
case lltok::kw_asm: {
// ValID ::= 'asm' SideEffect? AlignStack? IntelDialect? STRINGCONSTANT ','
// STRINGCONSTANT
bool HasSideEffect, AlignStack, AsmDialect;
Lex.Lex();
if (ParseOptionalToken(lltok::kw_sideeffect, HasSideEffect) ||
ParseOptionalToken(lltok::kw_alignstack, AlignStack) ||
ParseOptionalToken(lltok::kw_inteldialect, AsmDialect) ||
ParseStringConstant(ID.StrVal) ||
ParseToken(lltok::comma, "expected comma in inline asm expression") ||
ParseToken(lltok::StringConstant, "expected constraint string"))
return true;
ID.StrVal2 = Lex.getStrVal();
ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack)<<1) |
(unsigned(AsmDialect)<<2);
ID.Kind = ValID::t_InlineAsm;
return false;
}
case lltok::kw_blockaddress: {
// ValID ::= 'blockaddress' '(' @foo ',' %bar ')'
Lex.Lex();
ValID Fn, Label;
if (ParseToken(lltok::lparen, "expected '(' in block address expression") ||
ParseValID(Fn) ||
ParseToken(lltok::comma, "expected comma in block address expression")||
ParseValID(Label) ||
ParseToken(lltok::rparen, "expected ')' in block address expression"))
return true;
if (Fn.Kind != ValID::t_GlobalID && Fn.Kind != ValID::t_GlobalName)
return Error(Fn.Loc, "expected function name in blockaddress");
if (Label.Kind != ValID::t_LocalID && Label.Kind != ValID::t_LocalName)
return Error(Label.Loc, "expected basic block name in blockaddress");
// Try to find the function (but skip it if it's forward-referenced).
GlobalValue *GV = nullptr;
if (Fn.Kind == ValID::t_GlobalID) {
if (Fn.UIntVal < NumberedVals.size())
GV = NumberedVals[Fn.UIntVal];
} else if (!ForwardRefVals.count(Fn.StrVal)) {
GV = M->getNamedValue(Fn.StrVal);
}
Function *F = nullptr;
if (GV) {
// Confirm that it's actually a function with a definition.
if (!isa<Function>(GV))
return Error(Fn.Loc, "expected function name in blockaddress");
F = cast<Function>(GV);
if (F->isDeclaration())
return Error(Fn.Loc, "cannot take blockaddress inside a declaration");
}
if (!F) {
// Make a global variable as a placeholder for this reference.
GlobalValue *&FwdRef =
ForwardRefBlockAddresses.insert(std::make_pair(
std::move(Fn),
std::map<ValID, GlobalValue *>()))
.first->second.insert(std::make_pair(std::move(Label), nullptr))
.first->second;
if (!FwdRef)
FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), false,
GlobalValue::InternalLinkage, nullptr, "");
ID.ConstantVal = FwdRef;
ID.Kind = ValID::t_Constant;
return false;
}
// We found the function; now find the basic block. Don't use PFS, since we
// might be inside a constant expression.
BasicBlock *BB;
if (BlockAddressPFS && F == &BlockAddressPFS->getFunction()) {
if (Label.Kind == ValID::t_LocalID)
BB = BlockAddressPFS->GetBB(Label.UIntVal, Label.Loc);
else
BB = BlockAddressPFS->GetBB(Label.StrVal, Label.Loc);
if (!BB)
return Error(Label.Loc, "referenced value is not a basic block");
} else {
if (Label.Kind == ValID::t_LocalID)
return Error(Label.Loc, "cannot take address of numeric label after "
"the function is defined");
BB = dyn_cast_or_null<BasicBlock>(
F->getValueSymbolTable().lookup(Label.StrVal));
if (!BB)
return Error(Label.Loc, "referenced value is not a basic block");
}
ID.ConstantVal = BlockAddress::get(F, BB);
ID.Kind = ValID::t_Constant;
return false;
}
case lltok::kw_trunc:
case lltok::kw_zext:
case lltok::kw_sext:
case lltok::kw_fptrunc:
case lltok::kw_fpext:
case lltok::kw_bitcast:
case lltok::kw_addrspacecast:
case lltok::kw_uitofp:
case lltok::kw_sitofp:
case lltok::kw_fptoui:
case lltok::kw_fptosi:
case lltok::kw_inttoptr:
case lltok::kw_ptrtoint: {
unsigned Opc = Lex.getUIntVal();
Type *DestTy = nullptr;
Constant *SrcVal;
Lex.Lex();
if (ParseToken(lltok::lparen, "expected '(' after constantexpr cast") ||
ParseGlobalTypeAndValue(SrcVal) ||
ParseToken(lltok::kw_to, "expected 'to' in constantexpr cast") ||
ParseType(DestTy) ||
ParseToken(lltok::rparen, "expected ')' at end of constantexpr cast"))
return true;
if (!CastInst::castIsValid((Instruction::CastOps)Opc, SrcVal, DestTy))
return Error(ID.Loc, "invalid cast opcode for cast from '" +
getTypeString(SrcVal->getType()) + "' to '" +
getTypeString(DestTy) + "'");
ID.ConstantVal = ConstantExpr::getCast((Instruction::CastOps)Opc,
SrcVal, DestTy);
ID.Kind = ValID::t_Constant;
return false;
}
case lltok::kw_extractvalue: {
Lex.Lex();
Constant *Val;
SmallVector<unsigned, 4> Indices;
if (ParseToken(lltok::lparen, "expected '(' in extractvalue constantexpr")||
ParseGlobalTypeAndValue(Val) ||
ParseIndexList(Indices) ||
ParseToken(lltok::rparen, "expected ')' in extractvalue constantexpr"))
return true;
if (!Val->getType()->isAggregateType())
return Error(ID.Loc, "extractvalue operand must be aggregate type");
if (!ExtractValueInst::getIndexedType(Val->getType(), Indices))
return Error(ID.Loc, "invalid indices for extractvalue");
ID.ConstantVal = ConstantExpr::getExtractValue(Val, Indices);
ID.Kind = ValID::t_Constant;
return false;
}
case lltok::kw_insertvalue: {
Lex.Lex();
Constant *Val0, *Val1;
SmallVector<unsigned, 4> Indices;
if (ParseToken(lltok::lparen, "expected '(' in insertvalue constantexpr")||
ParseGlobalTypeAndValue(Val0) ||
ParseToken(lltok::comma, "expected comma in insertvalue constantexpr")||
ParseGlobalTypeAndValue(Val1) ||
ParseIndexList(Indices) ||
ParseToken(lltok::rparen, "expected ')' in insertvalue constantexpr"))
return true;
if (!Val0->getType()->isAggregateType())
return Error(ID.Loc, "insertvalue operand must be aggregate type");
Type *IndexedType =
ExtractValueInst::getIndexedType(Val0->getType(), Indices);
if (!IndexedType)
return Error(ID.Loc, "invalid indices for insertvalue");
if (IndexedType != Val1->getType())
return Error(ID.Loc, "insertvalue operand and field disagree in type: '" +
getTypeString(Val1->getType()) +
"' instead of '" + getTypeString(IndexedType) +
"'");
ID.ConstantVal = ConstantExpr::getInsertValue(Val0, Val1, Indices);
ID.Kind = ValID::t_Constant;
return false;
}
case lltok::kw_icmp:
case lltok::kw_fcmp: {
unsigned PredVal, Opc = Lex.getUIntVal();
Constant *Val0, *Val1;
Lex.Lex();
if (ParseCmpPredicate(PredVal, Opc) ||
ParseToken(lltok::lparen, "expected '(' in compare constantexpr") ||
ParseGlobalTypeAndValue(Val0) ||
ParseToken(lltok::comma, "expected comma in compare constantexpr") ||
ParseGlobalTypeAndValue(Val1) ||
ParseToken(lltok::rparen, "expected ')' in compare constantexpr"))
return true;
if (Val0->getType() != Val1->getType())
return Error(ID.Loc, "compare operands must have the same type");
CmpInst::Predicate Pred = (CmpInst::Predicate)PredVal;
if (Opc == Instruction::FCmp) {
if (!Val0->getType()->isFPOrFPVectorTy())
return Error(ID.Loc, "fcmp requires floating point operands");
ID.ConstantVal = ConstantExpr::getFCmp(Pred, Val0, Val1);
} else {
assert(Opc == Instruction::ICmp && "Unexpected opcode for CmpInst!");
if (!Val0->getType()->isIntOrIntVectorTy() &&
!Val0->getType()->getScalarType()->isPointerTy())
return Error(ID.Loc, "icmp requires pointer or integer operands");
ID.ConstantVal = ConstantExpr::getICmp(Pred, Val0, Val1);
}
ID.Kind = ValID::t_Constant;
return false;
}
// Binary Operators.
case lltok::kw_add:
case lltok::kw_fadd:
case lltok::kw_sub:
case lltok::kw_fsub:
case lltok::kw_mul:
case lltok::kw_fmul:
case lltok::kw_udiv:
case lltok::kw_sdiv:
case lltok::kw_fdiv:
case lltok::kw_urem:
case lltok::kw_srem:
case lltok::kw_frem:
case lltok::kw_shl:
case lltok::kw_lshr:
case lltok::kw_ashr: {
bool NUW = false;
bool NSW = false;
bool Exact = false;
unsigned Opc = Lex.getUIntVal();
Constant *Val0, *Val1;
Lex.Lex();
LocTy ModifierLoc = Lex.getLoc();
if (Opc == Instruction::Add || Opc == Instruction::Sub ||
Opc == Instruction::Mul || Opc == Instruction::Shl) {
if (EatIfPresent(lltok::kw_nuw))
NUW = true;
if (EatIfPresent(lltok::kw_nsw)) {
NSW = true;
if (EatIfPresent(lltok::kw_nuw))
NUW = true;
}
} else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv ||
Opc == Instruction::LShr || Opc == Instruction::AShr) {
if (EatIfPresent(lltok::kw_exact))
Exact = true;
}
if (ParseToken(lltok::lparen, "expected '(' in binary constantexpr") ||
ParseGlobalTypeAndValue(Val0) ||
ParseToken(lltok::comma, "expected comma in binary constantexpr") ||
ParseGlobalTypeAndValue(Val1) ||
ParseToken(lltok::rparen, "expected ')' in binary constantexpr"))
return true;
if (Val0->getType() != Val1->getType())
return Error(ID.Loc, "operands of constexpr must have same type");
if (!Val0->getType()->isIntOrIntVectorTy()) {
if (NUW)
return Error(ModifierLoc, "nuw only applies to integer operations");
if (NSW)
return Error(ModifierLoc, "nsw only applies to integer operations");
}
// Check that the type is valid for the operator.
switch (Opc) {
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::URem:
case Instruction::SRem:
case Instruction::Shl:
case Instruction::AShr:
case Instruction::LShr:
if (!Val0->getType()->isIntOrIntVectorTy())
return Error(ID.Loc, "constexpr requires integer operands");
break;
case Instruction::FAdd:
case Instruction::FSub:
case Instruction::FMul:
case Instruction::FDiv:
case Instruction::FRem:
if (!Val0->getType()->isFPOrFPVectorTy())
return Error(ID.Loc, "constexpr requires fp operands");
break;
default: llvm_unreachable("Unknown binary operator!");
}
unsigned Flags = 0;
if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap;
if (Exact) Flags |= PossiblyExactOperator::IsExact;
Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags);
ID.ConstantVal = C;
ID.Kind = ValID::t_Constant;
return false;
}
// Logical Operations
case lltok::kw_and:
case lltok::kw_or:
case lltok::kw_xor: {
unsigned Opc = Lex.getUIntVal();
Constant *Val0, *Val1;
Lex.Lex();
if (ParseToken(lltok::lparen, "expected '(' in logical constantexpr") ||
ParseGlobalTypeAndValue(Val0) ||
ParseToken(lltok::comma, "expected comma in logical constantexpr") ||
ParseGlobalTypeAndValue(Val1) ||
ParseToken(lltok::rparen, "expected ')' in logical constantexpr"))
return true;
if (Val0->getType() != Val1->getType())
return Error(ID.Loc, "operands of constexpr must have same type");
if (!Val0->getType()->isIntOrIntVectorTy())
return Error(ID.Loc,
"constexpr requires integer or integer vector operands");
ID.ConstantVal = ConstantExpr::get(Opc, Val0, Val1);
ID.Kind = ValID::t_Constant;
return false;
}
case lltok::kw_getelementptr:
case lltok::kw_shufflevector:
case lltok::kw_insertelement:
case lltok::kw_extractelement:
case lltok::kw_select: {
unsigned Opc = Lex.getUIntVal();
SmallVector<Constant*, 16> Elts;
bool InBounds = false;
Type *Ty;
Lex.Lex();
if (Opc == Instruction::GetElementPtr)
InBounds = EatIfPresent(lltok::kw_inbounds);
if (ParseToken(lltok::lparen, "expected '(' in constantexpr"))
return true;
LocTy ExplicitTypeLoc = Lex.getLoc();
if (Opc == Instruction::GetElementPtr) {
if (ParseType(Ty) ||
ParseToken(lltok::comma, "expected comma after getelementptr's type"))
return true;
}
if (ParseGlobalValueVector(Elts) ||
ParseToken(lltok::rparen, "expected ')' in constantexpr"))
return true;
if (Opc == Instruction::GetElementPtr) {
if (Elts.size() == 0 ||
!Elts[0]->getType()->getScalarType()->isPointerTy())
return Error(ID.Loc, "base of getelementptr must be a pointer");
Type *BaseType = Elts[0]->getType();
auto *BasePointerType = cast<PointerType>(BaseType->getScalarType());
if (Ty != BasePointerType->getElementType())
return Error(
ExplicitTypeLoc,
"explicit pointee type doesn't match operand's pointee type");
ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
for (Constant *Val : Indices) {
Type *ValTy = Val->getType();
if (!ValTy->getScalarType()->isIntegerTy())
return Error(ID.Loc, "getelementptr index must be an integer");
if (ValTy->isVectorTy() != BaseType->isVectorTy())
return Error(ID.Loc, "getelementptr index type missmatch");
if (ValTy->isVectorTy()) {
unsigned ValNumEl = ValTy->getVectorNumElements();
unsigned PtrNumEl = BaseType->getVectorNumElements();
if (ValNumEl != PtrNumEl)
return Error(
ID.Loc,
"getelementptr vector index has a wrong number of elements");
}
}
SmallPtrSet<const Type*, 4> Visited;
if (!Indices.empty() && !Ty->isSized(&Visited))
return Error(ID.Loc, "base element of getelementptr must be sized");
if (!GetElementPtrInst::getIndexedType(Ty, Indices))
return Error(ID.Loc, "invalid getelementptr indices");
ID.ConstantVal =
ConstantExpr::getGetElementPtr(Ty, Elts[0], Indices, InBounds);
} else if (Opc == Instruction::Select) {
if (Elts.size() != 3)
return Error(ID.Loc, "expected three operands to select");
if (const char *Reason = SelectInst::areInvalidOperands(Elts[0], Elts[1],
Elts[2]))
return Error(ID.Loc, Reason);
ID.ConstantVal = ConstantExpr::getSelect(Elts[0], Elts[1], Elts[2]);
} else if (Opc == Instruction::ShuffleVector) {
if (Elts.size() != 3)
return Error(ID.Loc, "expected three operands to shufflevector");
if (!ShuffleVectorInst::isValidOperands(Elts[0], Elts[1], Elts[2]))
return Error(ID.Loc, "invalid operands to shufflevector");
ID.ConstantVal =
ConstantExpr::getShuffleVector(Elts[0], Elts[1],Elts[2]);
} else if (Opc == Instruction::ExtractElement) {
if (Elts.size() != 2)
return Error(ID.Loc, "expected two operands to extractelement");
if (!ExtractElementInst::isValidOperands(Elts[0], Elts[1]))
return Error(ID.Loc, "invalid extractelement operands");
ID.ConstantVal = ConstantExpr::getExtractElement(Elts[0], Elts[1]);
} else {
assert(Opc == Instruction::InsertElement && "Unknown opcode");
if (Elts.size() != 3)
return Error(ID.Loc, "expected three operands to insertelement");
if (!InsertElementInst::isValidOperands(Elts[0], Elts[1], Elts[2]))
return Error(ID.Loc, "invalid insertelement operands");
ID.ConstantVal =
ConstantExpr::getInsertElement(Elts[0], Elts[1],Elts[2]);
}
ID.Kind = ValID::t_Constant;
return false;
}
}
Lex.Lex();
return false;
}