Skip to content

Commit bddbee5

Browse files
committed
Serialise PHI nodes.
This requires some "patch ups" because PHI nodes may reference instructions that we haven't serialised yet (and thus don't know their instruction indices yet).
1 parent a52f437 commit bddbee5

File tree

1 file changed

+64
-3
lines changed

1 file changed

+64
-3
lines changed

llvm/lib/YkIR/YkIRWriter.cpp

+64-3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ enum OpCode {
5252
OpCodeBinOp,
5353
OpCodeCast,
5454
OpCodeSwitch,
55+
OpCodePHI,
5556
OpCodeUnimplemented = 255, // YKFIXME: Will eventually be deleted.
5657
};
5758

@@ -174,6 +175,18 @@ class YkIRWriter {
174175
vector<llvm::Constant *> Constants;
175176
vector<llvm::GlobalVariable *> Globals;
176177

178+
// Instruction indices that need to be patched up later.
179+
vector<tuple<Instruction *, MCSymbol *>> InstIdxPacthUps;
180+
181+
// Fill in instruction indices that had to be deferred.
182+
void patchUpInstIdxs(ValueLoweringMap &VLMap) {
183+
MCContext &MCtxt = OutStreamer.getContext();
184+
for (auto &[Inst, Sym] : InstIdxPacthUps) {
185+
auto [_, InstIdx] = VLMap.at(Inst);
186+
OutStreamer.emitAssignment(Sym, MCConstantExpr::create(InstIdx, MCtxt));
187+
}
188+
}
189+
177190
// Return the index of the LLVM type `Ty`, inserting a new entry if
178191
// necessary.
179192
size_t typeIndex(llvm::Type *Ty) {
@@ -244,11 +257,33 @@ class YkIRWriter {
244257
}
245258

246259
void serialiseLocalVariableOperand(Instruction *I, ValueLoweringMap &VLMap) {
247-
auto [BBIdx, InstIdx] = VLMap.at(I);
248260
serialiseOperandKind(OperandKindLocal);
249261
OutStreamer.emitSizeT(getIndex(&M, I->getFunction()));
250-
OutStreamer.emitSizeT(BBIdx);
251-
OutStreamer.emitSizeT(InstIdx);
262+
263+
if (VLMap.count(I) == 1) {
264+
auto [BBIdx, InstIdx] = VLMap.at(I);
265+
OutStreamer.emitSizeT(BBIdx);
266+
OutStreamer.emitSizeT(InstIdx);
267+
} else {
268+
// It's a local variable generated by an instruction that we haven't
269+
// serialised yet. This can happen in loop bodies where a PHI node merges
270+
// in a variable from the end of the loop body.
271+
//
272+
// To work around this, we emit a dummy instruction index
273+
// and patch it up later once it becomes known.
274+
//
275+
// The basic block index can be immediately known, since the indices are
276+
// the same in the LLVM IR and our AOT IR.
277+
//
278+
// FIXME: In light of the above, there's no need to store basic block
279+
// indices in the VLMap?
280+
OutStreamer.emitSizeT(getIndex(I->getFunction(), I->getParent()));
281+
282+
MCContext &MCtxt = OutStreamer.getContext();
283+
MCSymbol *PatchUpSym = MCtxt.createTempSymbol();
284+
OutStreamer.emitSymbolValue(PatchUpSym, sizeof(size_t));
285+
InstIdxPacthUps.push_back({I, PatchUpSym});
286+
}
252287
}
253288

254289
void serialiseFunctionOperand(llvm::Function *F) {
@@ -690,6 +725,26 @@ class YkIRWriter {
690725
InstIdx++;
691726
}
692727

728+
void serialisePhiInst(PHINode *I, ValueLoweringMap &VLMap, unsigned BBIdx,
729+
unsigned &InstIdx) {
730+
// opcode:
731+
serialiseOpcode(OpCodePHI);
732+
// num_incoming:
733+
size_t NumIncoming = I->getNumIncomingValues();
734+
OutStreamer.emitSizeT(NumIncoming);
735+
// incoming_bbs:
736+
for (size_t J = 0; J < NumIncoming; J++) {
737+
serialiseBlockLabel(I->getIncomingBlock(J));
738+
}
739+
// incoming_vals:
740+
for (size_t J = 0; J < NumIncoming; J++) {
741+
serialiseOperand(I, VLMap, I->getIncomingValue(J));
742+
}
743+
744+
VLMap[I] = {BBIdx, InstIdx};
745+
InstIdx++;
746+
}
747+
693748
void serialiseInst(Instruction *I, ValueLoweringMap &VLMap, unsigned BBIdx,
694749
unsigned &InstIdx) {
695750
// Macro to make the dispatch below easier to read/sort.
@@ -707,6 +762,7 @@ class YkIRWriter {
707762
INST_SERIALISE(I, ICmpInst, serialiseICmpInst);
708763
INST_SERIALISE(I, InsertValueInst, serialiseInsertValueInst);
709764
INST_SERIALISE(I, LoadInst, serialiseLoadInst);
765+
INST_SERIALISE(I, PHINode, serialisePhiInst);
710766
INST_SERIALISE(I, ReturnInst, serialiseReturnInst);
711767
INST_SERIALISE(I, SExtInst, serialiseSExtInst);
712768
INST_SERIALISE(I, StoreInst, serialiseStoreInst);
@@ -798,6 +854,11 @@ class YkIRWriter {
798854
for (BasicBlock &BB : F) {
799855
serialiseBlock(BB, VLMap, BBIdx);
800856
}
857+
858+
patchUpInstIdxs(VLMap);
859+
// FIXME: it'd be better to make a new patchup struct for each function and
860+
// just let it fall out of scope when done. Lots of plumbing...
861+
InstIdxPacthUps.clear();
801862
}
802863

803864
void serialiseFunctionType(FunctionType *Ty) {

0 commit comments

Comments
 (0)