[llvm] f2df4bf - [AsmParser] Support non-consecutive global value numbers (#80013)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 31 08:04:34 PST 2024
Author: Nikita Popov
Date: 2024-01-31T17:04:30+01:00
New Revision: f2df4bfe54cd4161b7a2d89a0bc5dc69e747b01e
URL: https://github.com/llvm/llvm-project/commit/f2df4bfe54cd4161b7a2d89a0bc5dc69e747b01e
DIFF: https://github.com/llvm/llvm-project/commit/f2df4bfe54cd4161b7a2d89a0bc5dc69e747b01e.diff
LOG: [AsmParser] Support non-consecutive global value numbers (#80013)
https://github.com/llvm/llvm-project/pull/78171 added support for
non-consecutive local value numbers. This extends the support for global
value numbers (for globals and functions).
This means that it is now possible to delete an unnamed global
definition/declaration without breaking the IR.
This is a lot less common than unnamed local values, but it seems like
something we should support for consistency. (Unnamed globals are used a
lot in Rust though.)
Added:
llvm/include/llvm/AsmParser/NumberedValues.h
llvm/test/Assembler/skip-value-numbers-globals.ll
Modified:
llvm/include/llvm/AsmParser/LLParser.h
llvm/include/llvm/AsmParser/SlotMapping.h
llvm/lib/AsmParser/LLParser.cpp
llvm/lib/CodeGen/MIRParser/MIParser.cpp
llvm/test/Assembler/skip-value-numbers-invalid.ll
llvm/unittests/AsmParser/AsmParserTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index cf358c384f520..f07f4c61f9d64 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -15,6 +15,7 @@
#include "LLLexer.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/AsmParser/NumberedValues.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/FMF.h"
@@ -133,7 +134,7 @@ namespace llvm {
// Global Value reference information.
std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals;
std::map<unsigned, std::pair<GlobalValue*, LocTy> > ForwardRefValIDs;
- std::vector<GlobalValue*> NumberedVals;
+ NumberedValues<GlobalValue *> NumberedVals;
// Comdat forward reference information.
std::map<std::string, LocTy> ForwardRefComdats;
@@ -346,14 +347,15 @@ namespace llvm {
bool parseGlobalType(bool &IsConstant);
bool parseUnnamedGlobal();
bool parseNamedGlobal();
- bool parseGlobal(const std::string &Name, LocTy NameLoc, unsigned Linkage,
- bool HasLinkage, unsigned Visibility,
+ bool parseGlobal(const std::string &Name, unsigned NameID, LocTy NameLoc,
+ unsigned Linkage, bool HasLinkage, unsigned Visibility,
unsigned DLLStorageClass, bool DSOLocal,
GlobalVariable::ThreadLocalMode TLM,
GlobalVariable::UnnamedAddr UnnamedAddr);
- bool parseAliasOrIFunc(const std::string &Name, LocTy NameLoc, unsigned L,
- unsigned Visibility, unsigned DLLStorageClass,
- bool DSOLocal, GlobalVariable::ThreadLocalMode TLM,
+ bool parseAliasOrIFunc(const std::string &Name, unsigned NameID,
+ LocTy NameLoc, unsigned L, unsigned Visibility,
+ unsigned DLLStorageClass, bool DSOLocal,
+ GlobalVariable::ThreadLocalMode TLM,
GlobalVariable::UnnamedAddr UnnamedAddr);
bool parseComdat();
bool parseStandaloneMetadata();
@@ -452,27 +454,13 @@ namespace llvm {
bool parseFunctionType(Type *&Result);
bool parseTargetExtType(Type *&Result);
- class NumberedValues {
- DenseMap<unsigned, Value *> Vals;
- unsigned NextUnusedID = 0;
-
- public:
- unsigned getNext() const { return NextUnusedID; }
- Value *get(unsigned ID) const { return Vals.lookup(ID); }
- void add(unsigned ID, Value *V) {
- assert(ID >= NextUnusedID && "Invalid value ID");
- Vals.insert({ID, V});
- NextUnusedID = ID + 1;
- }
- };
-
// Function Semantic Analysis.
class PerFunctionState {
LLParser &P;
Function &F;
std::map<std::string, std::pair<Value*, LocTy> > ForwardRefVals;
std::map<unsigned, std::pair<Value*, LocTy> > ForwardRefValIDs;
- NumberedValues NumberedVals;
+ NumberedValues<Value *> NumberedVals;
/// FunctionNumber - If this is an unnamed function, this is the slot
/// number of it, otherwise it is -1.
@@ -614,8 +602,10 @@ namespace llvm {
SmallVectorImpl<unsigned> &UnnamedArgNums,
bool &IsVarArg);
bool parseFunctionHeader(Function *&Fn, bool IsDefine,
+ unsigned &FunctionNumber,
SmallVectorImpl<unsigned> &UnnamedArgNums);
- bool parseFunctionBody(Function &Fn, ArrayRef<unsigned> UnnamedArgNums);
+ bool parseFunctionBody(Function &Fn, unsigned FunctionNumber,
+ ArrayRef<unsigned> UnnamedArgNums);
bool parseBasicBlock(PerFunctionState &PFS);
enum TailCallType { TCT_None, TCT_Tail, TCT_MustTail };
diff --git a/llvm/include/llvm/AsmParser/NumberedValues.h b/llvm/include/llvm/AsmParser/NumberedValues.h
new file mode 100644
index 0000000000000..6ea75754c0c84
--- /dev/null
+++ b/llvm/include/llvm/AsmParser/NumberedValues.h
@@ -0,0 +1,34 @@
+//===-- NumberedValues.h - --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ASMPARSER_NUMBEREDVALUES_H
+#define LLVM_ASMPARSER_NUMBEREDVALUES_H
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+
+/// Mapping from value ID to value, which also remembers what the next unused
+/// ID is.
+template <class T> class NumberedValues {
+ DenseMap<unsigned, T> Vals;
+ unsigned NextUnusedID = 0;
+
+public:
+ unsigned getNext() const { return NextUnusedID; }
+ T get(unsigned ID) const { return Vals.lookup(ID); }
+ void add(unsigned ID, T V) {
+ assert(ID >= NextUnusedID && "Invalid value ID");
+ Vals.insert({ID, V});
+ NextUnusedID = ID + 1;
+ }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/AsmParser/SlotMapping.h b/llvm/include/llvm/AsmParser/SlotMapping.h
index 0e95eb816b4c6..2d2b8d8400bd7 100644
--- a/llvm/include/llvm/AsmParser/SlotMapping.h
+++ b/llvm/include/llvm/AsmParser/SlotMapping.h
@@ -14,6 +14,7 @@
#define LLVM_ASMPARSER_SLOTMAPPING_H
#include "llvm/ADT/StringMap.h"
+#include "llvm/AsmParser/NumberedValues.h"
#include "llvm/IR/TrackingMDRef.h"
#include <map>
#include <vector>
@@ -30,7 +31,7 @@ class Type;
/// textual references to the values in the module can be parsed outside of the
/// module's source.
struct SlotMapping {
- std::vector<GlobalValue *> GlobalValues;
+ NumberedValues<GlobalValue *> GlobalValues;
std::map<unsigned, TrackingMDNodeRef> MetadataNodes;
StringMap<Type *> NamedTypes;
std::map<unsigned, Type *> Types;
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index e111ca9c7e6b5..f35898569e269 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -254,8 +254,8 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
GlobalValue *GV = nullptr;
if (GVRef.Kind == ValID::t_GlobalName) {
GV = M->getNamedValue(GVRef.StrVal);
- } else if (GVRef.UIntVal < NumberedVals.size()) {
- GV = dyn_cast<GlobalValue>(NumberedVals[GVRef.UIntVal]);
+ } else {
+ GV = NumberedVals.get(GVRef.UIntVal);
}
if (!GV)
@@ -684,8 +684,9 @@ bool LLParser::parseDeclare() {
}
Function *F;
+ unsigned FunctionNumber = -1;
SmallVector<unsigned> UnnamedArgNums;
- if (parseFunctionHeader(F, false, UnnamedArgNums))
+ if (parseFunctionHeader(F, false, FunctionNumber, UnnamedArgNums))
return true;
for (auto &MD : MDs)
F->addMetadata(MD.first, *MD.second);
@@ -699,10 +700,11 @@ bool LLParser::parseDefine() {
Lex.Lex();
Function *F;
+ unsigned FunctionNumber = -1;
SmallVector<unsigned> UnnamedArgNums;
- return parseFunctionHeader(F, true, UnnamedArgNums) ||
+ return parseFunctionHeader(F, true, FunctionNumber, UnnamedArgNums) ||
parseOptionalFunctionMetadata(*F) ||
- parseFunctionBody(*F, UnnamedArgNums);
+ parseFunctionBody(*F, FunctionNumber, UnnamedArgNums);
}
/// parseGlobalType
@@ -743,19 +745,21 @@ bool LLParser::parseOptionalUnnamedAddr(
/// OptionalDLLStorageClass
/// ... -> global variable
bool LLParser::parseUnnamedGlobal() {
- unsigned VarID = NumberedVals.size();
+ unsigned VarID;
std::string Name;
LocTy NameLoc = Lex.getLoc();
// Handle the GlobalID form.
if (Lex.getKind() == lltok::GlobalID) {
- if (Lex.getUIntVal() != VarID)
- return error(Lex.getLoc(),
- "variable expected to be numbered '%" + Twine(VarID) + "'");
- Lex.Lex(); // eat GlobalID;
+ VarID = Lex.getUIntVal();
+ if (checkValueID(NameLoc, "global", "@", NumberedVals.getNext(), VarID))
+ return true;
+ Lex.Lex(); // eat GlobalID;
if (parseToken(lltok::equal, "expected '=' after name"))
return true;
+ } else {
+ VarID = NumberedVals.getNext();
}
bool HasLinkage;
@@ -770,11 +774,11 @@ bool LLParser::parseUnnamedGlobal() {
switch (Lex.getKind()) {
default:
- return parseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility,
+ return parseGlobal(Name, VarID, NameLoc, Linkage, HasLinkage, Visibility,
DLLStorageClass, DSOLocal, TLM, UnnamedAddr);
case lltok::kw_alias:
case lltok::kw_ifunc:
- return parseAliasOrIFunc(Name, NameLoc, Linkage, Visibility,
+ return parseAliasOrIFunc(Name, VarID, NameLoc, Linkage, Visibility,
DLLStorageClass, DSOLocal, TLM, UnnamedAddr);
}
}
@@ -803,11 +807,11 @@ bool LLParser::parseNamedGlobal() {
switch (Lex.getKind()) {
default:
- return parseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility,
+ return parseGlobal(Name, -1, NameLoc, Linkage, HasLinkage, Visibility,
DLLStorageClass, DSOLocal, TLM, UnnamedAddr);
case lltok::kw_alias:
case lltok::kw_ifunc:
- return parseAliasOrIFunc(Name, NameLoc, Linkage, Visibility,
+ return parseAliasOrIFunc(Name, -1, NameLoc, Linkage, Visibility,
DLLStorageClass, DSOLocal, TLM, UnnamedAddr);
}
}
@@ -1103,8 +1107,8 @@ static void maybeSetDSOLocal(bool DSOLocal, GlobalValue &GV) {
///
/// Everything through OptionalUnnamedAddr has already been parsed.
///
-bool LLParser::parseAliasOrIFunc(const std::string &Name, LocTy NameLoc,
- unsigned L, unsigned Visibility,
+bool LLParser::parseAliasOrIFunc(const std::string &Name, unsigned NameID,
+ LocTy NameLoc, unsigned L, unsigned Visibility,
unsigned DLLStorageClass, bool DSOLocal,
GlobalVariable::ThreadLocalMode TLM,
GlobalVariable::UnnamedAddr UnnamedAddr) {
@@ -1173,7 +1177,7 @@ bool LLParser::parseAliasOrIFunc(const std::string &Name, LocTy NameLoc,
return error(NameLoc, "redefinition of global '@" + Name + "'");
}
} else {
- auto I = ForwardRefValIDs.find(NumberedVals.size());
+ auto I = ForwardRefValIDs.find(NameID);
if (I != ForwardRefValIDs.end()) {
GVal = I->second.first;
ForwardRefValIDs.erase(I);
@@ -1217,7 +1221,7 @@ bool LLParser::parseAliasOrIFunc(const std::string &Name, LocTy NameLoc,
}
if (Name.empty())
- NumberedVals.push_back(GV);
+ NumberedVals.add(NameID, GV);
if (GVal) {
// Verify that types agree.
@@ -1294,8 +1298,8 @@ bool LLParser::parseSanitizer(GlobalVariable *GV) {
/// Everything up to and including OptionalUnnamedAddr has been parsed
/// already.
///
-bool LLParser::parseGlobal(const std::string &Name, LocTy NameLoc,
- unsigned Linkage, bool HasLinkage,
+bool LLParser::parseGlobal(const std::string &Name, unsigned NameID,
+ LocTy NameLoc, unsigned Linkage, bool HasLinkage,
unsigned Visibility, unsigned DLLStorageClass,
bool DSOLocal, GlobalVariable::ThreadLocalMode TLM,
GlobalVariable::UnnamedAddr UnnamedAddr) {
@@ -1345,7 +1349,12 @@ bool LLParser::parseGlobal(const std::string &Name, LocTy NameLoc,
return error(NameLoc, "redefinition of global '@" + Name + "'");
}
} else {
- auto I = ForwardRefValIDs.find(NumberedVals.size());
+ // Handle @"", where a name is syntactically specified, but semantically
+ // missing.
+ if (NameID == (unsigned)-1)
+ NameID = NumberedVals.getNext();
+
+ auto I = ForwardRefValIDs.find(NameID);
if (I != ForwardRefValIDs.end()) {
GVal = I->second.first;
ForwardRefValIDs.erase(I);
@@ -1357,7 +1366,7 @@ bool LLParser::parseGlobal(const std::string &Name, LocTy NameLoc,
GlobalVariable::NotThreadLocal, AddrSpace);
if (Name.empty())
- NumberedVals.push_back(GV);
+ NumberedVals.add(NameID, GV);
// Set the parsed properties on the global.
if (Init)
@@ -1744,7 +1753,7 @@ GlobalValue *LLParser::getGlobalVal(unsigned ID, Type *Ty, LocTy Loc) {
return nullptr;
}
- GlobalValue *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr;
+ GlobalValue *Val = NumberedVals.get(ID);
// If this is a forward reference for the value, see if we already created a
// forward ref record.
@@ -3800,8 +3809,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
// 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];
+ GV = NumberedVals.get(Fn.UIntVal);
} else if (!ForwardRefVals.count(Fn.StrVal)) {
GV = M->getNamedValue(Fn.StrVal);
}
@@ -3890,8 +3898,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
// 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];
+ GV = NumberedVals.get(Fn.UIntVal);
} else if (!ForwardRefVals.count(Fn.StrVal)) {
GV = M->getNamedValue(Fn.StrVal);
}
@@ -6038,6 +6045,7 @@ bool LLParser::parseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc,
/// '(' ArgList ')' OptAddrSpace OptFuncAttrs OptSection OptionalAlign
/// OptGC OptionalPrefix OptionalPrologue OptPersonalityFn
bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine,
+ unsigned &FunctionNumber,
SmallVectorImpl<unsigned> &UnnamedArgNums) {
// parse the linkage.
LocTy LinkageLoc = Lex.getLoc();
@@ -6096,11 +6104,10 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine,
if (Lex.getKind() == lltok::GlobalVar) {
FunctionName = Lex.getStrVal();
} else if (Lex.getKind() == lltok::GlobalID) { // @42 is ok.
- unsigned NameID = Lex.getUIntVal();
-
- if (NameID != NumberedVals.size())
- return tokError("function expected to be numbered '%" +
- Twine(NumberedVals.size()) + "'");
+ FunctionNumber = Lex.getUIntVal();
+ if (checkValueID(NameLoc, "function", "@", NumberedVals.getNext(),
+ FunctionNumber))
+ return true;
} else {
return tokError("expected function name");
}
@@ -6198,14 +6205,19 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine,
}
} else {
+ // Handle @"", where a name is syntactically specified, but semantically
+ // missing.
+ if (FunctionNumber == (unsigned)-1)
+ FunctionNumber = NumberedVals.getNext();
+
// If this is a definition of a forward referenced function, make sure the
// types agree.
- auto I = ForwardRefValIDs.find(NumberedVals.size());
+ auto I = ForwardRefValIDs.find(FunctionNumber);
if (I != ForwardRefValIDs.end()) {
FwdFn = I->second.first;
if (FwdFn->getType() != PFT)
return error(NameLoc, "type of definition and forward reference of '@" +
- Twine(NumberedVals.size()) +
+ Twine(FunctionNumber) +
"' disagree: "
"expected '" +
getTypeString(PFT) + "' but was '" +
@@ -6220,7 +6232,7 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine,
assert(Fn->getAddressSpace() == AddrSpace && "Created function in wrong AS");
if (FunctionName.empty())
- NumberedVals.push_back(Fn);
+ NumberedVals.add(FunctionNumber, Fn);
Fn->setLinkage((GlobalValue::LinkageTypes)Linkage);
maybeSetDSOLocal(DSOLocal, *Fn);
@@ -6266,7 +6278,7 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine,
ValID ID;
if (FunctionName.empty()) {
ID.Kind = ValID::t_GlobalID;
- ID.UIntVal = NumberedVals.size() - 1;
+ ID.UIntVal = FunctionNumber;
} else {
ID.Kind = ValID::t_GlobalName;
ID.StrVal = FunctionName;
@@ -6321,15 +6333,12 @@ bool LLParser::PerFunctionState::resolveForwardRefBlockAddresses() {
/// parseFunctionBody
/// ::= '{' BasicBlock+ UseListOrderDirective* '}'
-bool LLParser::parseFunctionBody(Function &Fn,
+bool LLParser::parseFunctionBody(Function &Fn, unsigned FunctionNumber,
ArrayRef<unsigned> UnnamedArgNums) {
if (Lex.getKind() != lltok::lbrace)
return tokError("expected '{' in function body");
Lex.Lex(); // eat the {.
- int FunctionNumber = -1;
- if (!Fn.hasName()) FunctionNumber = NumberedVals.size()-1;
-
PerFunctionState PFS(*this, Fn, FunctionNumber, UnnamedArgNums);
// Resolve block addresses and allow basic blocks to be forward-declared
@@ -8264,7 +8273,7 @@ bool LLParser::parseUseListOrderBB() {
if (Fn.Kind == ValID::t_GlobalName)
GV = M->getNamedValue(Fn.StrVal);
else if (Fn.Kind == ValID::t_GlobalID)
- GV = Fn.UIntVal < NumberedVals.size() ? NumberedVals[Fn.UIntVal] : nullptr;
+ GV = NumberedVals.get(Fn.UIntVal);
else
return error(Fn.Loc, "expected function name in uselistorder_bb");
if (!GV)
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 1a31e2ed809af..d41fc97cb8060 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -2181,10 +2181,10 @@ static bool parseGlobalValue(const MIToken &Token,
unsigned GVIdx;
if (getUnsigned(Token, GVIdx, ErrCB))
return true;
- if (GVIdx >= PFS.IRSlots.GlobalValues.size())
+ GV = PFS.IRSlots.GlobalValues.get(GVIdx);
+ if (!GV)
return ErrCB(Token.location(), Twine("use of undefined global value '@") +
Twine(GVIdx) + "'");
- GV = PFS.IRSlots.GlobalValues[GVIdx];
break;
}
default:
diff --git a/llvm/test/Assembler/skip-value-numbers-globals.ll b/llvm/test/Assembler/skip-value-numbers-globals.ll
new file mode 100644
index 0000000000000..95f60299752e7
--- /dev/null
+++ b/llvm/test/Assembler/skip-value-numbers-globals.ll
@@ -0,0 +1,47 @@
+; RUN: opt -S < %s | FileCheck %s
+
+ at 5 = global i8 0
+@"" = global i8 1
+ at 10 = alias i8, ptr @5
+ at 15 = ifunc ptr(), ptr @20
+
+define ptr @20() {
+ ret ptr null
+}
+
+declare void @25()
+
+declare ptr @""(ptr)
+
+define void @test(ptr %p) {
+ store ptr @5, ptr %p
+ store ptr @6, ptr %p
+ store ptr @10, ptr %p
+ store ptr @15, ptr %p
+ store ptr @20, ptr %p
+ store ptr @25, ptr %p
+ store ptr @26, ptr %p
+ ret void
+}
+
+; CHECK: @0 = global i8 0
+; CHECK: @1 = global i8 1
+; CHECK: @2 = alias i8, ptr @0
+; CHECK: @3 = ifunc ptr (), ptr @4
+
+; CHECK-LABEL: define ptr @4() {
+; CHECK-NEXT: ret ptr null
+
+; CHECK: declare void @5()
+
+; CHECK: declare ptr @6(ptr)
+
+; CHECK-LABEL: define void @test(ptr %p) {
+; CHECK-NEXT: store ptr @0, ptr %p, align 8
+; CHECK-NEXT: store ptr @1, ptr %p, align 8
+; CHECK-NEXT: store ptr @2, ptr %p, align 8
+; CHECK-NEXT: store ptr @3, ptr %p, align 8
+; CHECK-NEXT: store ptr @4, ptr %p, align 8
+; CHECK-NEXT: store ptr @5, ptr %p, align 8
+; CHECK-NEXT: store ptr @6, ptr %p, align 8
+; CHECK-NEXT: ret void
diff --git a/llvm/test/Assembler/skip-value-numbers-invalid.ll b/llvm/test/Assembler/skip-value-numbers-invalid.ll
index 67e6b10196bc8..b8173bbaf018c 100644
--- a/llvm/test/Assembler/skip-value-numbers-invalid.ll
+++ b/llvm/test/Assembler/skip-value-numbers-invalid.ll
@@ -2,6 +2,8 @@
; RUN: not llvm-as < %s %t/instr_smaller_id.ll 2>&1 | FileCheck %s --check-prefix=INSTR-SMALLER-ID
; RUN: not llvm-as < %s %t/arg_smaller_id.ll 2>&1 | FileCheck %s --check-prefix=ARG-SMALLER-ID
; RUN: not llvm-as < %s %t/block_smaller_id.ll 2>&1 | FileCheck %s --check-prefix=BLOCK-SMALLER-ID
+; RUN: not llvm-as < %s %t/global_smaller_id.ll 2>&1 | FileCheck %s --check-prefix=GLOBAL-SMALLER-ID
+; RUN: not llvm-as < %s %t/function_smaller_id.ll 2>&1 | FileCheck %s --check-prefix=FUNCTION-SMALLER-ID
;--- instr_smaller_id.ll
@@ -29,3 +31,19 @@ define i32 @test() {
5:
ret i32 0
}
+
+;--- global_smaller_id.ll
+
+; GLOBAL-SMALLER-ID: error: global expected to be numbered '@11' or greater
+
+ at 10 = external global i8
+ at 5 = external global i8
+
+;--- function_smaller_id.ll
+
+; FUNCTION-SMALLER-ID: error: function expected to be numbered '@11' or greater
+
+define void @10() {
+ ret void
+}
+declare void @5()
diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp
index 77dba5bfd4cae..f296848ed665f 100644
--- a/llvm/unittests/AsmParser/AsmParserTest.cpp
+++ b/llvm/unittests/AsmParser/AsmParserTest.cpp
@@ -57,8 +57,8 @@ TEST(AsmParserTest, SlotMappingTest) {
EXPECT_TRUE(Mod != nullptr);
EXPECT_TRUE(Error.getMessage().empty());
- ASSERT_EQ(Mapping.GlobalValues.size(), 1u);
- EXPECT_TRUE(isa<GlobalVariable>(Mapping.GlobalValues[0]));
+ ASSERT_EQ(Mapping.GlobalValues.getNext(), 1u);
+ EXPECT_TRUE(isa<GlobalVariable>(Mapping.GlobalValues.get(0)));
EXPECT_EQ(Mapping.MetadataNodes.size(), 2u);
EXPECT_EQ(Mapping.MetadataNodes.count(0), 1u);
More information about the llvm-commits
mailing list