Skip to content

Commit 73ffc00

Browse files
authored
Merge pull request rust-lang#148 from vext01/phi
Serialise PHI nodes.
2 parents a52f437 + bddbee5 commit 73ffc00

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)