X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAsmParser%2FLLParser.cpp;h=65e622af66c372ea9419a95cd18df7af36388fa9;hb=22feef493a694e618634b535cc289a12da54ac92;hp=25b2a3150236e7b0ea468021bfe6f31e0a12fe03;hpb=4762c0b5d11f0de20aafd3e9310d9fc565497bd3;p=oota-llvm.git diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 25b2a315023..65e622af66c 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -16,6 +16,7 @@ #include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InlineAsm.h" @@ -749,7 +750,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, return true; } - if (Ty->isFunctionTy() || Ty->isLabelTy()) + if (Ty->isFunctionTy() || !PointerType::isValidElementType(Ty)) return Error(TyLoc, "invalid type for global variable"); GlobalValue *GVal = nullptr; @@ -1633,6 +1634,7 @@ bool LLParser::ParseIndexList(SmallVectorImpl &Indices, while (EatIfPresent(lltok::comma)) { if (Lex.getKind() == lltok::MetadataVar) { + if (Indices.empty()) return TokError("expected index"); AteExtraComma = true; return false; } @@ -2268,13 +2270,13 @@ bool LLParser::PerFunctionState::SetInstName(int NameID, /// forward reference record if needed. BasicBlock *LLParser::PerFunctionState::GetBB(const std::string &Name, LocTy Loc) { - return cast_or_null(GetVal(Name, - Type::getLabelTy(F.getContext()), Loc)); + return dyn_cast_or_null(GetVal(Name, + Type::getLabelTy(F.getContext()), Loc)); } BasicBlock *LLParser::PerFunctionState::GetBB(unsigned ID, LocTy Loc) { - return cast_or_null(GetVal(ID, - Type::getLabelTy(F.getContext()), Loc)); + return dyn_cast_or_null(GetVal(ID, + Type::getLabelTy(F.getContext()), Loc)); } /// DefineBB - Define the specified basic block, which is either named or @@ -2510,7 +2512,12 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { if (!F) { // Make a global variable as a placeholder for this reference. - GlobalValue *&FwdRef = ForwardRefBlockAddresses[Fn][Label]; + GlobalValue *&FwdRef = + ForwardRefBlockAddresses.insert(std::make_pair( + std::move(Fn), + std::map())) + .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, ""); @@ -2607,8 +2614,15 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { return true; if (!Val0->getType()->isAggregateType()) return Error(ID.Loc, "insertvalue operand must be aggregate type"); - if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices)) + 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; @@ -2774,11 +2788,33 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { if (Opc == Instruction::GetElementPtr) { if (Elts.size() == 0 || !Elts[0]->getType()->getScalarType()->isPointerTy()) - return Error(ID.Loc, "getelementptr requires pointer operand"); + return Error(ID.Loc, "base of getelementptr must be a pointer"); + + Type *BaseType = Elts[0]->getType(); + auto *BasePointerType = cast(BaseType->getScalarType()); ArrayRef 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 = cast(ValTy)->getNumElements(); + unsigned PtrNumEl = cast(BaseType)->getNumElements(); + if (ValNumEl != PtrNumEl) + return Error( + ID.Loc, + "getelementptr vector index has a wrong number of elements"); + } + } + + if (!Indices.empty() && !BasePointerType->getElementType()->isSized()) + return Error(ID.Loc, "base element of getelementptr must be sized"); + if (!GetElementPtrInst::getIndexedType(Elts[0]->getType(), Indices)) - return Error(ID.Loc, "invalid indices for getelementptr"); + return Error(ID.Loc, "invalid getelementptr indices"); ID.ConstantVal = ConstantExpr::getGetElementPtr(Elts[0], Indices, InBounds); } else if (Opc == Instruction::Select) { @@ -2930,6 +2966,7 @@ template struct MDFieldImpl { explicit MDFieldImpl(FieldTy Default) : Val(std::move(Default)), Seen(false) {} }; + struct MDUnsignedField : public MDFieldImpl { uint64_t Max; @@ -2944,10 +2981,42 @@ struct ColumnField : public MDUnsignedField { }; struct DwarfTagField : public MDUnsignedField { DwarfTagField() : MDUnsignedField(0, dwarf::DW_TAG_hi_user) {} + DwarfTagField(dwarf::Tag DefaultTag) + : MDUnsignedField(DefaultTag, dwarf::DW_TAG_hi_user) {} +}; +struct DwarfAttEncodingField : public MDUnsignedField { + DwarfAttEncodingField() : MDUnsignedField(0, dwarf::DW_ATE_hi_user) {} +}; +struct DwarfVirtualityField : public MDUnsignedField { + DwarfVirtualityField() : MDUnsignedField(0, dwarf::DW_VIRTUALITY_max) {} +}; +struct DwarfLangField : public MDUnsignedField { + DwarfLangField() : MDUnsignedField(0, dwarf::DW_LANG_hi_user) {} +}; + +struct DIFlagField : public MDUnsignedField { + DIFlagField() : MDUnsignedField(0, UINT32_MAX) {} +}; + +struct MDSignedField : public MDFieldImpl { + int64_t Min; + int64_t Max; + + MDSignedField(int64_t Default = 0) + : ImplTy(Default), Min(INT64_MIN), Max(INT64_MAX) {} + MDSignedField(int64_t Default, int64_t Min, int64_t Max) + : ImplTy(Default), Min(Min), Max(Max) {} +}; + +struct MDBoolField : public MDFieldImpl { + MDBoolField(bool Default = false) : ImplTy(Default) {} }; struct MDField : public MDFieldImpl { MDField() : ImplTy(nullptr) {} }; +struct MDConstant : public MDFieldImpl { + MDConstant() : ImplTy(nullptr) {} +}; struct MDStringField : public MDFieldImpl { MDStringField() : ImplTy(std::string()) {} }; @@ -3002,8 +3071,143 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfTagField &Result) { return false; } +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + DwarfVirtualityField &Result) { + if (Lex.getKind() == lltok::APSInt) + return ParseMDField(Loc, Name, static_cast(Result)); + + if (Lex.getKind() != lltok::DwarfVirtuality) + return TokError("expected DWARF virtuality code"); + + unsigned Virtuality = dwarf::getVirtuality(Lex.getStrVal()); + if (!Virtuality) + return TokError("invalid DWARF virtuality code" + Twine(" '") + + Lex.getStrVal() + "'"); + assert(Virtuality <= Result.Max && "Expected valid DWARF virtuality code"); + Result.assign(Virtuality); + Lex.Lex(); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfLangField &Result) { + if (Lex.getKind() == lltok::APSInt) + return ParseMDField(Loc, Name, static_cast(Result)); + + if (Lex.getKind() != lltok::DwarfLang) + return TokError("expected DWARF language"); + + unsigned Lang = dwarf::getLanguage(Lex.getStrVal()); + if (!Lang) + return TokError("invalid DWARF language" + Twine(" '") + Lex.getStrVal() + + "'"); + assert(Lang <= Result.Max && "Expected valid DWARF language"); + Result.assign(Lang); + Lex.Lex(); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + DwarfAttEncodingField &Result) { + if (Lex.getKind() == lltok::APSInt) + return ParseMDField(Loc, Name, static_cast(Result)); + + if (Lex.getKind() != lltok::DwarfAttEncoding) + return TokError("expected DWARF type attribute encoding"); + + unsigned Encoding = dwarf::getAttributeEncoding(Lex.getStrVal()); + if (!Encoding) + return TokError("invalid DWARF type attribute encoding" + Twine(" '") + + Lex.getStrVal() + "'"); + assert(Encoding <= Result.Max && "Expected valid DWARF language"); + Result.assign(Encoding); + Lex.Lex(); + return false; +} + +/// DIFlagField +/// ::= uint32 +/// ::= DIFlagVector +/// ::= DIFlagVector '|' DIFlagFwdDecl '|' uint32 '|' DIFlagPublic +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DIFlagField &Result) { + assert(Result.Max == UINT32_MAX && "Expected only 32-bits"); + + // Parser for a single flag. + auto parseFlag = [&](unsigned &Val) { + if (Lex.getKind() == lltok::APSInt && !Lex.getAPSIntVal().isSigned()) + return ParseUInt32(Val); + + if (Lex.getKind() != lltok::DIFlag) + return TokError("expected debug info flag"); + + Val = DIDescriptor::getFlag(Lex.getStrVal()); + if (!Val) + return TokError(Twine("invalid debug info flag flag '") + + Lex.getStrVal() + "'"); + Lex.Lex(); + return false; + }; + + // Parse the flags and combine them together. + unsigned Combined = 0; + do { + unsigned Val; + if (parseFlag(Val)) + return true; + Combined |= Val; + } while (EatIfPresent(lltok::bar)); + + Result.assign(Combined); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + MDSignedField &Result) { + if (Lex.getKind() != lltok::APSInt) + return TokError("expected signed integer"); + + auto &S = Lex.getAPSIntVal(); + if (S < Result.Min) + return TokError("value for '" + Name + "' too small, limit is " + + Twine(Result.Min)); + if (S > Result.Max) + return TokError("value for '" + Name + "' too large, limit is " + + Twine(Result.Max)); + Result.assign(S.getExtValue()); + assert(Result.Val >= Result.Min && "Expected value in range"); + assert(Result.Val <= Result.Max && "Expected value in range"); + Lex.Lex(); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDBoolField &Result) { + switch (Lex.getKind()) { + default: + return TokError("expected 'true' or 'false'"); + case lltok::kw_true: + Result.assign(true); + break; + case lltok::kw_false: + Result.assign(false); + break; + } + Lex.Lex(); + return false; +} + template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) { + if (Lex.getKind() == lltok::kw_null) { + Lex.Lex(); + Result.assign(nullptr); + return false; + } + Metadata *MD; if (ParseMetadata(MD, nullptr)) return true; @@ -3012,6 +3216,16 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) { return false; } +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDConstant &Result) { + Metadata *MD; + if (ParseValueAsMetadata(MD, "expected constant", nullptr)) + return true; + + Result.assign(cast(MD)); + return false; +} + template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) { std::string S; @@ -3136,63 +3350,407 @@ bool LLParser::ParseGenericDebugNode(MDNode *&Result, bool IsDistinct) { return false; } +/// ParseMDSubrange: +/// ::= !MDSubrange(count: 30, lowerBound: 2) bool LLParser::ParseMDSubrange(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(count, MDSignedField, (-1, -1, INT64_MAX)); \ + OPTIONAL(lowerBound, MDSignedField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDSubrange, (Context, count.Val, lowerBound.Val)); + return false; } + +/// ParseMDEnumerator: +/// ::= !MDEnumerator(value: 30, name: "SomeKind") bool LLParser::ParseMDEnumerator(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(name, MDStringField, ); \ + REQUIRED(value, MDSignedField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDEnumerator, (Context, value.Val, name.Val)); + return false; } + +/// ParseMDBasicType: +/// ::= !MDBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32) bool LLParser::ParseMDBasicType(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(encoding, DwarfAttEncodingField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDBasicType, (Context, tag.Val, name.Val, size.Val, + align.Val, encoding.Val)); + return false; } + +/// ParseMDDerivedType: +/// ::= !MDDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0, +/// line: 7, scope: !1, baseType: !2, size: 32, +/// align: 32, offset: 0, flags: 0, extraData: !3) bool LLParser::ParseMDDerivedType(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(scope, MDField, ); \ + REQUIRED(baseType, MDField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(extraData, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDDerivedType, + (Context, tag.Val, name.Val, file.Val, line.Val, + scope.Val, baseType.Val, size.Val, align.Val, + offset.Val, flags.Val, extraData.Val)); + return false; } + bool LLParser::ParseMDCompositeType(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(baseType, MDField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(elements, MDField, ); \ + OPTIONAL(runtimeLang, DwarfLangField, ); \ + OPTIONAL(vtableHolder, MDField, ); \ + OPTIONAL(templateParams, MDField, ); \ + OPTIONAL(identifier, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + MDCompositeType, + (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, + size.Val, align.Val, offset.Val, flags.Val, elements.Val, + runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val)); + return false; } + bool LLParser::ParseMDSubroutineType(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(flags, DIFlagField, ); \ + REQUIRED(types, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDSubroutineType, (Context, flags.Val, types.Val)); + return false; } + +/// ParseMDFileType: +/// ::= !MDFileType(filename: "path/to/file", directory: "/path/to/dir") bool LLParser::ParseMDFile(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(filename, MDStringField, ); \ + REQUIRED(directory, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDFile, (Context, filename.Val, directory.Val)); + return false; } + +/// ParseMDCompileUnit: +/// ::= !MDCompileUnit(language: DW_LANG_C99, file: !0, producer: "clang", +/// isOptimized: true, flags: "-O2", runtimeVersion: 1, +/// splitDebugFilename: "abc.debug", emissionKind: 1, +/// enums: !1, retainedTypes: !2, subprograms: !3, +/// globals: !4, imports: !5) bool LLParser::ParseMDCompileUnit(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(language, DwarfLangField, ); \ + REQUIRED(file, MDField, ); \ + OPTIONAL(producer, MDStringField, ); \ + OPTIONAL(isOptimized, MDBoolField, ); \ + OPTIONAL(flags, MDStringField, ); \ + OPTIONAL(runtimeVersion, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(splitDebugFilename, MDStringField, ); \ + OPTIONAL(emissionKind, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(enums, MDField, ); \ + OPTIONAL(retainedTypes, MDField, ); \ + OPTIONAL(subprograms, MDField, ); \ + OPTIONAL(globals, MDField, ); \ + OPTIONAL(imports, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDCompileUnit, + (Context, language.Val, file.Val, producer.Val, + isOptimized.Val, flags.Val, runtimeVersion.Val, + splitDebugFilename.Val, emissionKind.Val, enums.Val, + retainedTypes.Val, subprograms.Val, globals.Val, + imports.Val)); + return false; } + +/// ParseMDSubprogram: +/// ::= !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoo", +/// file: !1, line: 7, type: !2, isLocal: false, +/// isDefinition: true, scopeLine: 8, containingType: !3, +/// virtuality: DW_VIRTUALTIY_pure_virtual, +/// virtualIndex: 10, flags: 11, +/// isOptimized: false, function: void ()* @_Z3foov, +/// templateParams: !4, declaration: !5, variables: !6) bool LLParser::ParseMDSubprogram(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(scope, MDField, ); \ + REQUIRED(name, MDStringField, ); \ + OPTIONAL(linkageName, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(isLocal, MDBoolField, ); \ + OPTIONAL(isDefinition, MDBoolField, (true)); \ + OPTIONAL(scopeLine, LineField, ); \ + OPTIONAL(containingType, MDField, ); \ + OPTIONAL(virtuality, DwarfVirtualityField, ); \ + OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(isOptimized, MDBoolField, ); \ + OPTIONAL(function, MDConstant, ); \ + OPTIONAL(templateParams, MDField, ); \ + OPTIONAL(declaration, MDField, ); \ + OPTIONAL(variables, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + MDSubprogram, (Context, scope.Val, name.Val, linkageName.Val, file.Val, + line.Val, type.Val, isLocal.Val, isDefinition.Val, + scopeLine.Val, containingType.Val, virtuality.Val, + virtualIndex.Val, flags.Val, isOptimized.Val, function.Val, + templateParams.Val, declaration.Val, variables.Val)); + return false; } + +/// ParseMDLexicalBlock: +/// ::= !MDLexicalBlock(scope: !0, file: !2, line: 7, column: 9) bool LLParser::ParseMDLexicalBlock(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(column, ColumnField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + MDLexicalBlock, (Context, scope.Val, file.Val, line.Val, column.Val)); + return false; } + +/// ParseMDLexicalBlockFile: +/// ::= !MDLexicalBlockFile(scope: !0, file: !2, discriminator: 9) bool LLParser::ParseMDLexicalBlockFile(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(file, MDField, ); \ + REQUIRED(discriminator, MDUnsignedField, (0, UINT32_MAX)); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDLexicalBlockFile, + (Context, scope.Val, file.Val, discriminator.Val)); + return false; } + +/// ParseMDNamespace: +/// ::= !MDNamespace(scope: !0, file: !2, name: "SomeNamespace", line: 9) bool LLParser::ParseMDNamespace(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(line, LineField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDNamespace, + (Context, scope.Val, file.Val, name.Val, line.Val)); + return false; } + +/// ParseMDTemplateTypeParameter: +/// ::= !MDTemplateTypeParameter(name: "Ty", type: !1) bool LLParser::ParseMDTemplateTypeParameter(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(name, MDStringField, ); \ + REQUIRED(type, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = + GET_OR_DISTINCT(MDTemplateTypeParameter, (Context, name.Val, type.Val)); + return false; } + +/// ParseMDTemplateValueParameter: +/// ::= !MDTemplateValueParameter(tag: DW_TAG_template_value_parameter, +/// name: "V", type: !1, value: i32 7) bool LLParser::ParseMDTemplateValueParameter(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_template_value_parameter)); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(type, MDField, ); \ + REQUIRED(value, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDTemplateValueParameter, + (Context, tag.Val, name.Val, type.Val, value.Val)); + return false; } + +/// ParseMDGlobalVariable: +/// ::= !MDGlobalVariable(scope: !0, name: "foo", linkageName: "foo", +/// file: !1, line: 7, type: !2, isLocal: false, +/// isDefinition: true, variable: i32* @foo, +/// declaration: !3) bool LLParser::ParseMDGlobalVariable(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(scope, MDField, ); \ + REQUIRED(name, MDStringField, ); \ + OPTIONAL(linkageName, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(isLocal, MDBoolField, ); \ + OPTIONAL(isDefinition, MDBoolField, (true)); \ + OPTIONAL(variable, MDConstant, ); \ + OPTIONAL(declaration, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDGlobalVariable, + (Context, scope.Val, name.Val, linkageName.Val, + file.Val, line.Val, type.Val, isLocal.Val, + isDefinition.Val, variable.Val, declaration.Val)); + return false; } + +/// ParseMDLocalVariable: +/// ::= !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !0, name: "foo", +/// file: !1, line: 7, type: !2, arg: 2, flags: 7, +/// inlinedAt: !3) bool LLParser::ParseMDLocalVariable(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(arg, MDUnsignedField, (0, UINT8_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(inlinedAt, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + MDLocalVariable, (Context, tag.Val, scope.Val, name.Val, file.Val, + line.Val, type.Val, arg.Val, flags.Val, inlinedAt.Val)); + return false; } + +/// ParseMDExpression: +/// ::= !MDExpression(0, 7, -1) bool LLParser::ParseMDExpression(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + Lex.Lex(); + + if (ParseToken(lltok::lparen, "expected '(' here")) + return true; + + SmallVector Elements; + if (Lex.getKind() != lltok::rparen) + do { + if (Lex.getKind() == lltok::DwarfOp) { + if (unsigned Op = dwarf::getOperationEncoding(Lex.getStrVal())) { + Lex.Lex(); + Elements.push_back(Op); + continue; + } + return TokError(Twine("invalid DWARF op '") + Lex.getStrVal() + "'"); + } + + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + return TokError("expected unsigned integer"); + + auto &U = Lex.getAPSIntVal(); + if (U.ugt(UINT64_MAX)) + return TokError("element too large, limit is " + Twine(UINT64_MAX)); + Elements.push_back(U.getZExtValue()); + Lex.Lex(); + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + Result = GET_OR_DISTINCT(MDExpression, (Context, Elements)); + return false; } + +/// ParseMDObjCProperty: +/// ::= !MDObjCProperty(name: "foo", file: !1, line: 7, setter: "setFoo", +/// getter: "getFoo", attributes: 7, type: !2) bool LLParser::ParseMDObjCProperty(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(setter, MDStringField, ); \ + OPTIONAL(getter, MDStringField, ); \ + OPTIONAL(attributes, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(type, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDObjCProperty, + (Context, name.Val, file.Val, line.Val, setter.Val, + getter.Val, attributes.Val, type.Val)); + return false; } + +/// ParseMDImportedEntity: +/// ::= !MDImportedEntity(tag: DW_TAG_imported_module, scope: !0, entity: !1, +/// line: 7, name: "foo") bool LLParser::ParseMDImportedEntity(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(entity, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(name, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDImportedEntity, (Context, tag.Val, scope.Val, + entity.Val, line.Val, name.Val)); + return false; } + #undef PARSE_MD_FIELD #undef NOP_FIELD #undef REQUIRE_FIELD @@ -3219,10 +3777,11 @@ bool LLParser::ParseMetadataAsValue(Value *&V, PerFunctionState &PFS) { /// ::= i32 %local /// ::= i32 @global /// ::= i32 7 -bool LLParser::ParseValueAsMetadata(Metadata *&MD, PerFunctionState *PFS) { +bool LLParser::ParseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg, + PerFunctionState *PFS) { Type *Ty; LocTy Loc; - if (ParseType(Ty, "expected metadata operand", Loc)) + if (ParseType(Ty, TypeMsg, Loc)) return true; if (Ty->isMetadataTy()) return Error(Loc, "invalid metadata-value-metadata roundtrip"); @@ -3255,7 +3814,7 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) { // ValueAsMetadata: // if (Lex.getKind() != lltok::exclaim) - return ParseValueAsMetadata(MD, PFS); + return ParseValueAsMetadata(MD, "expected metadata operand", PFS); // '!'. assert(Lex.getKind() == lltok::exclaim && "Expected '!' here"); @@ -3745,7 +4304,9 @@ bool LLParser::ParseBasicBlock(PerFunctionState &PFS) { } BasicBlock *BB = PFS.DefineBB(Name, NameLoc); - if (!BB) return true; + if (!BB) + return Error(NameLoc, + "unable to create block named '" + Name + "'"); std::string NameStr; @@ -4187,10 +4748,14 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { if (I != E) return Error(CallLoc, "not enough parameters specified for call"); - if (FnAttrs.hasAttributes()) + if (FnAttrs.hasAttributes()) { + if (FnAttrs.hasAlignmentAttr()) + return Error(CallLoc, "invoke instructions may not have an alignment"); + Attrs.push_back(AttributeSet::get(RetType->getContext(), AttributeSet::FunctionIndex, FnAttrs)); + } // Finish off the Attribute and check them AttributeSet PAL = AttributeSet::get(Context, Attrs); @@ -4476,7 +5041,7 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { ParseTypeAndValue(PersFn, PersFnLoc, PFS)) return true; - LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, 0); + std::unique_ptr LP(LandingPadInst::Create(Ty, PersFn, 0)); LP->setCleanup(EatIfPresent(lltok::kw_cleanup)); while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){ @@ -4490,10 +5055,8 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { Value *V; LocTy VLoc; - if (ParseTypeAndValue(V, VLoc, PFS)) { - delete LP; + if (ParseTypeAndValue(V, VLoc, PFS)) return true; - } // A 'catch' type expects a non-array constant. A filter clause expects an // array constant. @@ -4505,10 +5068,13 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { Error(VLoc, "'filter' clause has an invalid type"); } - LP->addClause(cast(V)); + Constant *CV = dyn_cast(V); + if (!CV) + return Error(VLoc, "clause argument must be a constant"); + LP->addClause(CV); } - Inst = LP; + Inst = LP.release(); return false; } @@ -4600,10 +5166,14 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, if (I != E) return Error(CallLoc, "not enough parameters specified for call"); - if (FnAttrs.hasAttributes()) + if (FnAttrs.hasAttributes()) { + if (FnAttrs.hasAlignmentAttr()) + return Error(CallLoc, "call instructions may not have an alignment"); + Attrs.push_back(AttributeSet::get(RetType->getContext(), AttributeSet::FunctionIndex, FnAttrs)); + } // Finish off the Attribute and check them AttributeSet PAL = AttributeSet::get(Context, Attrs); @@ -4625,13 +5195,16 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, /// ::= 'alloca' 'inalloca'? Type (',' TypeAndValue)? (',' 'align' i32)? int LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS) { Value *Size = nullptr; - LocTy SizeLoc; + LocTy SizeLoc, TyLoc; unsigned Alignment = 0; Type *Ty = nullptr; bool IsInAlloca = EatIfPresent(lltok::kw_inalloca); - if (ParseType(Ty)) return true; + if (ParseType(Ty, TyLoc)) return true; + + if (Ty->isFunctionTy() || !PointerType::isValidElementType(Ty)) + return Error(TyLoc, "invalid type for alloca"); bool AteExtraComma = false; if (EatIfPresent(lltok::comma)) { @@ -4678,7 +5251,11 @@ int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS) { Lex.Lex(); } - if (ParseTypeAndValue(Val, Loc, PFS) || + Type *Ty = nullptr; + LocTy ExplicitTypeLoc = Lex.getLoc(); + if (ParseType(Ty) || + ParseToken(lltok::comma, "expected comma after load's type") || + ParseTypeAndValue(Val, Loc, PFS) || ParseScopeAndOrdering(isAtomic, Scope, Ordering) || ParseOptionalCommaAlign(Alignment, AteExtraComma)) return true; @@ -4691,6 +5268,10 @@ int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS) { if (Ordering == Release || Ordering == AcquireRelease) return Error(Loc, "atomic load cannot use Release ordering"); + if (Ty != cast(Val->getType())->getElementType()) + return Error(ExplicitTypeLoc, + "explicit pointee type doesn't match operand's pointee type"); + Inst = new LoadInst(Val, "", isVolatile, Alignment, Ordering, Scope); return AteExtraComma ? InstExtraComma : InstNormal; } @@ -4877,13 +5458,22 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { bool InBounds = EatIfPresent(lltok::kw_inbounds); - if (ParseTypeAndValue(Ptr, Loc, PFS)) return true; + Type *Ty = nullptr; + LocTy ExplicitTypeLoc = Lex.getLoc(); + if (ParseType(Ty) || + ParseToken(lltok::comma, "expected comma after getelementptr's type") || + ParseTypeAndValue(Ptr, Loc, PFS)) + return true; Type *BaseType = Ptr->getType(); PointerType *BasePointerType = dyn_cast(BaseType->getScalarType()); if (!BasePointerType) return Error(Loc, "base of getelementptr must be a pointer"); + if (Ty != BasePointerType->getElementType()) + return Error(ExplicitTypeLoc, + "explicit pointee type doesn't match operand's pointee type"); + SmallVector Indices; bool AteExtraComma = false; while (EatIfPresent(lltok::comma)) { @@ -4951,8 +5541,13 @@ int LLParser::ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS) { if (!Val0->getType()->isAggregateType()) return Error(Loc0, "insertvalue operand must be aggregate type"); - if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices)) + Type *IndexedType = ExtractValueInst::getIndexedType(Val0->getType(), Indices); + if (!IndexedType) return Error(Loc0, "invalid indices for insertvalue"); + if (IndexedType != Val1->getType()) + return Error(Loc1, "insertvalue operand and field disagree in type: '" + + getTypeString(Val1->getType()) + "' instead of '" + + getTypeString(IndexedType) + "'"); Inst = InsertValueInst::Create(Val0, Val1, Indices); return AteExtraComma ? InstExtraComma : InstNormal; }