Restore "Function bitcode index in Value Symbol Table and lazy readin… · llvm/llvm-project@ff642b9 (original) (raw)

`@@ -147,6 +147,7 @@ class BitcodeReader : public GVMaterializer {

`

147

147

` BitstreamCursor Stream;

`

148

148

`uint64_t NextUnreadBit = 0;

`

149

149

`bool SeenValueSymbolTable = false;

`

``

150

`+

unsigned VSTOffset = 0;

`

150

151

``

151

152

` std::vector<Type*> TypeList;

`

152

153

` BitcodeReaderValueList ValueList;

`

`@@ -370,7 +371,9 @@ class BitcodeReader : public GVMaterializer {

`

370

371

` std::error_code parseTypeTable();

`

371

372

` std::error_code parseTypeTableBody();

`

372

373

``

373

``

`-

std::error_code parseValueSymbolTable();

`

``

374

`+

ErrorOr<Value *> recordValue(SmallVectorImpl &Record,

`

``

375

`+

unsigned NameIndex, Triple &TT);

`

``

376

`+

std::error_code parseValueSymbolTable(unsigned Offset = 0);

`

374

377

` std::error_code parseConstants();

`

375

378

` std::error_code rememberAndSkipFunctionBody();

`

376

379

`/// Save the positions of the Metadata blocks and skip parsing the blocks.

`

`@@ -1583,7 +1586,68 @@ std::error_code BitcodeReader::parseTypeTableBody() {

`

1583

1586

` }

`

1584

1587

`}

`

1585

1588

``

1586

``

`-

std::error_code BitcodeReader::parseValueSymbolTable() {

`

``

1589

`+

/// Associate a value with its name from the given index in the provided record.

`

``

1590

`+

ErrorOr<Value *> BitcodeReader::recordValue(SmallVectorImpl &Record,

`

``

1591

`+

unsigned NameIndex, Triple &TT) {

`

``

1592

`+

SmallString<128> ValueName;

`

``

1593

`+

if (convertToString(Record, NameIndex, ValueName))

`

``

1594

`+

return error("Invalid record");

`

``

1595

`+

unsigned ValueID = Record[0];

`

``

1596

`+

if (ValueID >= ValueList.size() || !ValueList[ValueID])

`

``

1597

`+

return error("Invalid record");

`

``

1598

`+

Value *V = ValueList[ValueID];

`

``

1599

+

``

1600

`+

V->setName(StringRef(ValueName.data(), ValueName.size()));

`

``

1601

`+

auto *GO = dyn_cast(V);

`

``

1602

`+

if (GO) {

`

``

1603

`+

if (GO->getComdat() == reinterpret_cast<Comdat *>(1)) {

`

``

1604

`+

if (TT.isOSBinFormatMachO())

`

``

1605

`+

GO->setComdat(nullptr);

`

``

1606

`+

else

`

``

1607

`+

GO->setComdat(TheModule->getOrInsertComdat(V->getName()));

`

``

1608

`+

}

`

``

1609

`+

}

`

``

1610

`+

return V;

`

``

1611

`+

}

`

``

1612

+

``

1613

`+

/// Parse the value symbol table at either the current parsing location or

`

``

1614

`+

/// at the given bit offset if provided.

`

``

1615

`+

std::error_code BitcodeReader::parseValueSymbolTable(unsigned Offset) {

`

``

1616

`+

uint64_t CurrentBit;

`

``

1617

`+

// Pass in the Offset to distinguish between calling for the module-level

`

``

1618

`+

// VST (where we want to jump to the VST offset) and the function-level

`

``

1619

`+

// VST (where we don't).

`

``

1620

`+

if (Offset > 0) {

`

``

1621

`+

// Save the current parsing location so we can jump back at the end

`

``

1622

`+

// of the VST read.

`

``

1623

`+

CurrentBit = Stream.GetCurrentBitNo();

`

``

1624

`+

Stream.JumpToBit(Offset * 32);

`

``

1625

`+

#ifndef NDEBUG

`

``

1626

`+

// Do some checking if we are in debug mode.

`

``

1627

`+

BitstreamEntry Entry = Stream.advance();

`

``

1628

`+

assert(Entry.Kind == BitstreamEntry::SubBlock);

`

``

1629

`+

assert(Entry.ID == bitc::VALUE_SYMTAB_BLOCK_ID);

`

``

1630

`+

#else

`

``

1631

`+

// In NDEBUG mode ignore the output so we don't get an unused variable

`

``

1632

`+

// warning.

`

``

1633

`+

Stream.advance();

`

``

1634

`+

#endif

`

``

1635

`+

}

`

``

1636

+

``

1637

`+

// Compute the delta between the bitcode indices in the VST (the word offset

`

``

1638

`+

// to the word-aligned ENTER_SUBBLOCK for the function block, and that

`

``

1639

`+

// expected by the lazy reader. The reader's EnterSubBlock expects to have

`

``

1640

`+

// already read the ENTER_SUBBLOCK code (size getAbbrevIDWidth) and BlockID

`

``

1641

`+

// (size BlockIDWidth). Note that we access the stream's AbbrevID width here

`

``

1642

`+

// just before entering the VST subblock because: 1) the EnterSubBlock

`

``

1643

`+

// changes the AbbrevID width; 2) the VST block is nested within the same

`

``

1644

`+

// outer MODULE_BLOCK as the FUNCTION_BLOCKs and therefore have the same

`

``

1645

`+

// AbbrevID width before calling EnterSubBlock; and 3) when we want to

`

``

1646

`+

// jump to the FUNCTION_BLOCK using this offset later, we don't want

`

``

1647

`+

// to rely on the stream's AbbrevID width being that of the MODULE_BLOCK.

`

``

1648

`+

unsigned FuncBitcodeOffsetDelta =

`

``

1649

`+

Stream.getAbbrevIDWidth() + bitc::BlockIDWidth;

`

``

1650

+

1587

1651

`if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))

`

1588

1652

`return error("Invalid record");

`

1589

1653

``

`@@ -1601,6 +1665,8 @@ std::error_code BitcodeReader::parseValueSymbolTable() {

`

1601

1665

`case BitstreamEntry::Error:

`

1602

1666

`return error("Malformed block");

`

1603

1667

`case BitstreamEntry::EndBlock:

`

``

1668

`+

if (Offset > 0)

`

``

1669

`+

Stream.JumpToBit(CurrentBit);

`

1604

1670

`return std::error_code();

`

1605

1671

`case BitstreamEntry::Record:

`

1606

1672

`// The interesting case.

`

`@@ -1613,23 +1679,39 @@ std::error_code BitcodeReader::parseValueSymbolTable() {

`

1613

1679

`default: // Default behavior: unknown type.

`

1614

1680

`break;

`

1615

1681

`case bitc::VST_CODE_ENTRY: { // VST_ENTRY: [valueid, namechar x N]

`

1616

``

`-

if (convertToString(Record, 1, ValueName))

`

1617

``

`-

return error("Invalid record");

`

1618

``

`-

unsigned ValueID = Record[0];

`

1619

``

`-

if (ValueID >= ValueList.size() || !ValueList[ValueID])

`

1620

``

`-

return error("Invalid record");

`

1621

``

`-

Value *V = ValueList[ValueID];

`

1622

``

-

1623

``

`-

V->setName(StringRef(ValueName.data(), ValueName.size()));

`

1624

``

`-

if (auto *GO = dyn_cast(V)) {

`

1625

``

`-

if (GO->getComdat() == reinterpret_cast<Comdat *>(1)) {

`

1626

``

`-

if (TT.isOSBinFormatMachO())

`

1627

``

`-

GO->setComdat(nullptr);

`

1628

``

`-

else

`

1629

``

`-

GO->setComdat(TheModule->getOrInsertComdat(V->getName()));

`

1630

``

`-

}

`

``

1682

`+

ErrorOr<Value *> ValOrErr = recordValue(Record, 1, TT);

`

``

1683

`+

if (std::error_code EC = ValOrErr.getError())

`

``

1684

`+

return EC;

`

``

1685

`+

ValOrErr.get();

`

``

1686

`+

break;

`

``

1687

`+

}

`

``

1688

`+

case bitc::VST_CODE_FNENTRY: {

`

``

1689

`+

// VST_FNENTRY: [valueid, offset, namechar x N]

`

``

1690

`+

ErrorOr<Value *> ValOrErr = recordValue(Record, 2, TT);

`

``

1691

`+

if (std::error_code EC = ValOrErr.getError())

`

``

1692

`+

return EC;

`

``

1693

`+

Value *V = ValOrErr.get();

`

``

1694

+

``

1695

`+

auto *GO = dyn_cast(V);

`

``

1696

`+

if (!GO) {

`

``

1697

`+

// If this is an alias, need to get the actual Function object

`

``

1698

`+

// it aliases, in order to set up the DeferredFunctionInfo entry below.

`

``

1699

`+

auto *GA = dyn_cast(V);

`

``

1700

`+

if (GA)

`

``

1701

`+

GO = GA->getBaseObject();

`

``

1702

`+

assert(GO);

`

1631

1703

` }

`

1632

``

`-

ValueName.clear();

`

``

1704

+

``

1705

`+

uint64_t FuncWordOffset = Record[1];

`

``

1706

`+

Function *F = dyn_cast(GO);

`

``

1707

`+

assert(F);

`

``

1708

`+

uint64_t FuncBitOffset = FuncWordOffset * 32;

`

``

1709

`+

DeferredFunctionInfo[F] = FuncBitOffset + FuncBitcodeOffsetDelta;

`

``

1710

`+

// Set the NextUnreadBit to point to the last function block.

`

``

1711

`+

// Later when parsing is resumed after function materialization,

`

``

1712

`+

// we can simply skip that last function block.

`

``

1713

`+

if (FuncBitOffset > NextUnreadBit)

`

``

1714

`+

NextUnreadBit = FuncBitOffset;

`

1633

1715

`break;

`

1634

1716

` }

`

1635

1717

`case bitc::VST_CODE_BBENTRY: {

`

`@@ -2852,9 +2934,23 @@ std::error_code BitcodeReader::parseModule(bool Resume,

`

2852

2934

`return EC;

`

2853

2935

`break;

`

2854

2936

`case bitc::VALUE_SYMTAB_BLOCK_ID:

`

2855

``

`-

if (std::error_code EC = parseValueSymbolTable())

`

2856

``

`-

return EC;

`

2857

``

`-

SeenValueSymbolTable = true;

`

``

2937

`+

if (!SeenValueSymbolTable) {

`

``

2938

`+

// Either this is an old form VST without function index and an

`

``

2939

`+

// associated VST forward declaration record (which would have caused

`

``

2940

`+

// the VST to be jumped to and parsed before it was encountered

`

``

2941

`+

// normally in the stream), or there were no function blocks to

`

``

2942

`+

// trigger an earlier parsing of the VST.

`

``

2943

`+

assert(VSTOffset == 0 || FunctionsWithBodies.empty());

`

``

2944

`+

if (std::error_code EC = parseValueSymbolTable())

`

``

2945

`+

return EC;

`

``

2946

`+

SeenValueSymbolTable = true;

`

``

2947

`+

} else {

`

``

2948

`+

// We must have had a VST forward declaration record, which caused

`

``

2949

`+

// the parser to jump to and parse the VST earlier.

`

``

2950

`+

assert(VSTOffset > 0);

`

``

2951

`+

if (Stream.SkipBlock())

`

``

2952

`+

return error("Invalid record");

`

``

2953

`+

}

`

2858

2954

`break;

`

2859

2955

`case bitc::CONSTANTS_BLOCK_ID:

`

2860

2956

`if (std::error_code EC = parseConstants())

`

`@@ -2882,6 +2978,32 @@ std::error_code BitcodeReader::parseModule(bool Resume,

`

2882

2978

` SeenFirstFunctionBody = true;

`

2883

2979

` }

`

2884

2980

``

``

2981

`+

if (VSTOffset > 0) {

`

``

2982

`+

// If we have a VST forward declaration record, make sure we

`

``

2983

`+

// parse the VST now if we haven't already. It is needed to

`

``

2984

`+

// set up the DeferredFunctionInfo vector for lazy reading.

`

``

2985

`+

if (!SeenValueSymbolTable) {

`

``

2986

`+

if (std::error_code EC =

`

``

2987

`+

BitcodeReader::parseValueSymbolTable(VSTOffset))

`

``

2988

`+

return EC;

`

``

2989

`+

SeenValueSymbolTable = true;

`

``

2990

`+

return std::error_code();

`

``

2991

`+

} else {

`

``

2992

`+

// If we have a VST forward declaration record, but have already

`

``

2993

`+

// parsed the VST (just above, when the first function body was

`

``

2994

`+

// encountered here), then we are resuming the parse after

`

``

2995

`+

// materializing functions. The NextUnreadBit points to the start

`

``

2996

`+

// of the last function block recorded in the VST (set when

`

``

2997

`+

// parsing the VST function entries). Skip it.

`

``

2998

`+

if (Stream.SkipBlock())

`

``

2999

`+

return error("Invalid record");

`

``

3000

`+

continue;

`

``

3001

`+

}

`

``

3002

`+

}

`

``

3003

+

``

3004

`+

// Support older bitcode files that did not have the function

`

``

3005

`+

// index in the VST, nor a VST forward declaration record.

`

``

3006

`+

// Build the DeferredFunctionInfo vector on the fly.

`

2885

3007

`if (std::error_code EC = rememberAndSkipFunctionBody())

`

2886

3008

`return EC;

`

2887

3009

`// Suspend parsing when we reach the function bodies. Subsequent

`

`@@ -3185,6 +3307,12 @@ std::error_code BitcodeReader::parseModule(bool Resume,

`

3185

3307

`return error("Invalid record");

`

3186

3308

` ValueList.shrinkTo(Record[0]);

`

3187

3309

`break;

`

``

3310

`+

/// MODULE_CODE_VSTOFFSET: [offset]

`

``

3311

`+

case bitc::MODULE_CODE_VSTOFFSET:

`

``

3312

`+

if (Record.size() < 1)

`

``

3313

`+

return error("Invalid record");

`

``

3314

`+

VSTOffset = Record[0];

`

``

3315

`+

break;

`

3188

3316

` }

`

3189

3317

` Record.clear();

`

3190

3318

` }

`

`@@ -4642,6 +4770,11 @@ std::error_code BitcodeReader::findFunctionInStream(

`

4642

4770

` Function *F,

`

4643

4771

` DenseMap<Function *, uint64_t>::iterator DeferredFunctionInfoIterator) {

`

4644

4772

`while (DeferredFunctionInfoIterator->second == 0) {

`

``

4773

`+

// This is the fallback handling for the old format bitcode that

`

``

4774

`+

// didn't contain the function index in the VST. Assert if we end up

`

``

4775

`+

// here for the new format (which is the only time the VSTOffset would

`

``

4776

`+

// be non-zero).

`

``

4777

`+

assert(VSTOffset == 0);

`

4645

4778

`if (Stream.AtEndOfStream())

`

4646

4779

`return error("Could not find function in stream");

`

4647

4780

`// ParseModule will parse the next body in the stream and set its

`