Skip to content

Commit df2a89f

Browse files
committed
SIL: introduce a PlaceholderValue and use it in the parser and deserializer.
... instead of a GlobalAddrInst. This is cleaner and makes the handling of forward-referenced values in the deserializer a bit simpler.
1 parent 8e95ae8 commit df2a89f

File tree

10 files changed

+81
-42
lines changed

10 files changed

+81
-42
lines changed

include/swift/SIL/SILNodes.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,10 @@ VALUE(MultipleValueInstructionResult, ValueBase)
415415

416416
VALUE(SILUndef, ValueBase)
417417

418+
/// Used internally in e.g. the SIL parser and deserializer.
419+
/// A PlaceholderValue must not appear in valid SIL.
420+
VALUE(PlaceholderValue, ValueBase)
421+
418422
ABSTRACT_NODE(SILInstruction, SILNode)
419423

420424
ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)

include/swift/SIL/SILValue.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class PostOrderFunctionInfo;
3737
class ReversePostOrderInfo;
3838
class Operand;
3939
class SILInstruction;
40+
class SILArgument;
4041
class SILLocation;
4142
class DeadEndBlocks;
4243
class ValueBaseUseIterator;
@@ -1353,6 +1354,25 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SILValue V) {
13531354
return OS;
13541355
}
13551356

1357+
/// Used internally in e.g. the SIL parser and deserializer to handle forward-
1358+
/// referenced values.
1359+
/// A PlaceholderValue must not appear in valid SIL.
1360+
class PlaceholderValue : public ValueBase {
1361+
static int numPlaceholderValuesAlive;
1362+
1363+
public:
1364+
PlaceholderValue(SILType type);
1365+
~PlaceholderValue();
1366+
1367+
static int getNumPlaceholderValuesAlive() { return numPlaceholderValuesAlive; }
1368+
1369+
static bool classof(const SILArgument *) = delete;
1370+
static bool classof(const SILInstruction *) = delete;
1371+
static bool classof(SILNodePointer node) {
1372+
return node->getKind() == SILNodeKind::PlaceholderValue;
1373+
}
1374+
};
1375+
13561376
} // end namespace swift
13571377

13581378

lib/SIL/IR/SILModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ void SILModule::checkForLeaks() const {
169169
llvm::errs() << "Instructions in module: " << instsInModule << '\n';
170170
llvm_unreachable("leaking instructions");
171171
}
172+
173+
assert(PlaceholderValue::getNumPlaceholderValuesAlive() == 0 &&
174+
"leaking placeholders");
172175
}
173176

174177
void SILModule::checkForLeaksAfterDestruction() {

lib/SIL/IR/SILPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,12 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
10421042
printSILUndef(cast<SILUndef>(node));
10431043
return;
10441044

1045+
case SILNodeKind::PlaceholderValue:
1046+
// This should really only happen during debugging.
1047+
*this << "placeholder<" << cast<PlaceholderValue>(node)->getType()
1048+
<< ">\n";
1049+
return;
1050+
10451051
case SILNodeKind::MultipleValueInstructionResult:
10461052
printSILMultipleValueInstructionResult(
10471053
cast<MultipleValueInstructionResult>(node));

lib/SIL/IR/SILValue.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,3 +388,19 @@ llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
388388
const OperandOwnership &operandOwnership) {
389389
return os << operandOwnership.asString();
390390
}
391+
392+
//===----------------------------------------------------------------------===//
393+
// PlaceholderValue
394+
//===----------------------------------------------------------------------===//
395+
396+
int PlaceholderValue::numPlaceholderValuesAlive = 0;
397+
398+
PlaceholderValue::PlaceholderValue(SILType type)
399+
: ValueBase(ValueKind::PlaceholderValue, type) {
400+
numPlaceholderValuesAlive++;
401+
}
402+
403+
PlaceholderValue::~PlaceholderValue() {
404+
numPlaceholderValuesAlive--;
405+
}
406+

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,11 @@ ValueOwnershipKind ValueOwnershipKindClassifier::visitSILUndef(SILUndef *arg) {
287287
return arg->getOwnershipKind();
288288
}
289289

290+
ValueOwnershipKind ValueOwnershipKindClassifier::
291+
visitPlaceholderValue(PlaceholderValue *v) {
292+
return OwnershipKind::None;
293+
}
294+
290295
ValueOwnershipKind ValueOwnershipKindClassifier::
291296
visitMultipleValueInstructionResult(MultipleValueInstructionResult *Result) {
292297
return Result->getOwnershipKind();

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,7 @@ SILParser::~SILParser() {
500500
for (auto &Entry : ForwardRefLocalValues) {
501501
if (ValueBase *dummyVal = LocalValues[Entry.first()]) {
502502
dummyVal->replaceAllUsesWith(SILUndef::get(dummyVal->getType(), SILMod));
503-
SILInstruction::destroy(cast<GlobalAddrInst>(dummyVal));
504-
SILMod.deallocateInst(cast<GlobalAddrInst>(dummyVal));
503+
::delete cast<PlaceholderValue>(dummyVal);
505504
}
506505
}
507506
}
@@ -687,7 +686,7 @@ SILValue SILParser::getLocalValue(UnresolvedValueName Name, SILType Type,
687686
// it until we see a real definition.
688687
ForwardRefLocalValues[Name.Name] = Name.NameLoc;
689688

690-
Entry = new (SILMod) GlobalAddrInst(getDebugLoc(B, Loc), Type);
689+
Entry = ::new PlaceholderValue(Type);
691690
return Entry;
692691
}
693692

@@ -715,8 +714,7 @@ void SILParser::setLocalValue(ValueBase *Value, StringRef Name,
715714
} else {
716715
// Forward references only live here if they have a single result.
717716
Entry->replaceAllUsesWith(Value);
718-
SILInstruction::destroy(cast<GlobalAddrInst>(Entry));
719-
SILMod.deallocateInst(cast<GlobalAddrInst>(Entry));
717+
::delete cast<PlaceholderValue>(Entry);
720718
}
721719
Entry = Value;
722720
return;

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
11111111
// Verify some basis structural stuff about an instruction's operands.
11121112
for (auto &operand : I->getAllOperands()) {
11131113
require(operand.get(), "instruction has null operand");
1114+
require(!isa<PlaceholderValue>(operand.get()),
1115+
"instruction has placeholder operand");
11141116

11151117
if (auto *valueI = operand.get()->getDefiningInstruction()) {
11161118
require(valueI->getParent(),

lib/Serialization/DeserializeSIL.cpp

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -262,29 +262,23 @@ SILDeserializer::readFuncTable(ArrayRef<uint64_t> fields, StringRef blobData) {
262262

263263
/// A high-level overview of how forward references work in serializer and
264264
/// deserializer:
265-
/// In serializer, we pre-assign a value ID in order, to each basic block
265+
/// In the serializer, we pre-assign a value ID in order, to each basic block
266266
/// argument and each SILInstruction that has a value.
267-
/// In deserializer, we use LocalValues to store the definitions and
268-
/// ForwardLocalValues for forward-referenced values (values that are
269-
/// used but not yet defined). LocalValues are updated in setLocalValue where
270-
/// the ID passed in assumes the same ordering as in serializer: in-order
271-
/// for each basic block argument and each SILInstruction that has a value.
272-
/// We update ForwardLocalValues in getLocalValue and when a value is defined
273-
/// in setLocalValue, the corresponding entry in ForwardLocalValues will be
274-
/// erased.
267+
/// In the deserializer, we create a PlaceholderValue for a forward-referenced
268+
/// value (a value that is used but not yet defined). LocalValues are updated in
269+
/// setLocalValue where the ID passed in assumes the same ordering as in
270+
/// serializer: in-order for each basic block argument and each SILInstruction
271+
/// that has a value.
272+
/// When a forward-referenced value is defined, it replaces the PlaceholderValue
273+
/// in LocalValues.
275274
void SILDeserializer::setLocalValue(ValueBase *Value, ValueID Id) {
276275
ValueBase *&Entry = LocalValues[Id];
277-
assert(!Entry && "We should not redefine the same value.");
278276

279-
auto It = ForwardLocalValues.find(Id);
280-
if (It != ForwardLocalValues.end()) {
281-
// Take the information about the forward ref out of the map.
282-
ValueBase *Placeholder = It->second;
283-
284-
// Remove the entries from the map.
285-
ForwardLocalValues.erase(It);
286-
287-
Placeholder->replaceAllUsesWith(Value);
277+
if (auto *placeholder = dyn_cast_or_null<PlaceholderValue>(Entry)) {
278+
placeholder->replaceAllUsesWith(Value);
279+
::delete placeholder;
280+
} else {
281+
assert(!Entry && "We should not redefine the same value.");
288282
}
289283

290284
// Store it in our map.
@@ -301,19 +295,15 @@ SILValue SILDeserializer::getLocalValue(ValueID Id,
301295
"changes that without updating this code if needed");
302296

303297
// Check to see if this is already defined.
304-
ValueBase *Entry = LocalValues.lookup(Id);
305-
if (Entry) {
306-
// If this value was already defined, check it to make sure types match.
307-
assert(Entry->getType() == Type && "Value Type mismatch?");
308-
return Entry;
309-
}
310-
311-
// Otherwise, this is a forward reference. Create a dummy node to represent
312-
// it until we see a real definition.
313-
ValueBase *&Placeholder = ForwardLocalValues[Id];
314-
if (!Placeholder)
315-
Placeholder = new (SILMod) GlobalAddrInst(SILDebugLocation(), Type);
316-
return Placeholder;
298+
ValueBase *&Entry = LocalValues[Id];
299+
if (!Entry) {
300+
// Otherwise, this is a forward reference. Create a dummy node to represent
301+
// it until we see a real definition.
302+
Entry = ::new PlaceholderValue(Type);
303+
}
304+
// If this value was already defined, check it to make sure types match.
305+
assert(Entry->getType() == Type && "Value Type mismatch?");
306+
return Entry;
317307
}
318308

319309
/// Return the SILBasicBlock of a given ID.
@@ -807,7 +797,6 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
807797
// The first two IDs are reserved for SILUndef.
808798
LastValueID = 1;
809799
LocalValues.clear();
810-
ForwardLocalValues.clear();
811800

812801
SILOpenedArchetypesTracker OpenedArchetypesTracker(fn);
813802
SILBuilder Builder(*fn);
@@ -3034,11 +3023,9 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
30343023
SILBuilder Builder(v);
30353024

30363025
llvm::DenseMap<uint32_t, ValueBase*> SavedLocalValues;
3037-
llvm::DenseMap<uint32_t, ValueBase*> SavedForwardLocalValues;
30383026
serialization::ValueID SavedLastValueID = 1;
30393027

30403028
SavedLocalValues.swap(LocalValues);
3041-
SavedForwardLocalValues.swap(ForwardLocalValues);
30423029
std::swap(SavedLastValueID, LastValueID);
30433030

30443031
while (kind != SIL_FUNCTION && kind != SIL_VTABLE && kind != SIL_GLOBALVAR &&
@@ -3066,7 +3053,6 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
30663053
}
30673054

30683055
SavedLocalValues.swap(LocalValues);
3069-
SavedForwardLocalValues.swap(ForwardLocalValues);
30703056
std::swap(SavedLastValueID, LastValueID);
30713057

30723058
return v;

lib/Serialization/DeserializeSIL.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ namespace swift {
8585

8686
/// Data structures used to perform name lookup for local values.
8787
llvm::DenseMap<uint32_t, ValueBase*> LocalValues;
88-
llvm::DenseMap<uint32_t, ValueBase*> ForwardLocalValues;
8988

9089
/// The first two local values are reserved for SILUndef.
9190
serialization::ValueID LastValueID = 1;

0 commit comments

Comments
 (0)