static bool analyzeStaticInitializer(SILFunction *F, SILInstruction *&Val, SILGlobalVariable *&GVar) { Val = nullptr; GVar = nullptr; // We only handle a single SILBasicBlock for now. if (F->size() != 1) return false; SILBasicBlock *BB = &F->front(); GlobalAddrInst *SGA = nullptr; bool HasStore = false; for (auto &I : *BB) { // Make sure we have a single GlobalAddrInst and a single StoreInst. // And the StoreInst writes to the GlobalAddrInst. if (isa<AllocGlobalInst>(&I)) { continue; } else if (auto *sga = dyn_cast<GlobalAddrInst>(&I)) { if (SGA) return false; SGA = sga; GVar = SGA->getReferencedGlobal(); } else if (auto *SI = dyn_cast<StoreInst>(&I)) { if (HasStore || SI->getDest().getDef() != SGA) return false; HasStore = true; Val = dyn_cast<SILInstruction>(SI->getSrc().getDef()); // We only handle StructInst and TupleInst being stored to a // global variable for now. if (!isa<StructInst>(Val) && !isa<TupleInst>(Val)) return false; } else { if (auto *bi = dyn_cast<BuiltinInst>(&I)) { switch (bi->getBuiltinInfo().ID) { case BuiltinValueKind::FPTrunc: if (isa<LiteralInst>(bi->getArguments()[0])) continue; break; default: return false; } } if (I.getKind() != ValueKind::ReturnInst && I.getKind() != ValueKind::StructInst && I.getKind() != ValueKind::TupleInst && I.getKind() != ValueKind::IntegerLiteralInst && I.getKind() != ValueKind::FloatLiteralInst && I.getKind() != ValueKind::StringLiteralInst) return false; } } return true; }
static SILGlobalVariable *getVariableOfStaticInitializer(SILFunction *InitFunc, SingleValueInstruction *&InitVal) { InitVal = nullptr; SILGlobalVariable *GVar = nullptr; // We only handle a single SILBasicBlock for now. if (InitFunc->size() != 1) return nullptr; SILBasicBlock *BB = &InitFunc->front(); GlobalAddrInst *SGA = nullptr; bool HasStore = false; for (auto &I : *BB) { // Make sure we have a single GlobalAddrInst and a single StoreInst. // And the StoreInst writes to the GlobalAddrInst. if (isa<AllocGlobalInst>(&I) || isa<ReturnInst>(&I) || isa<DebugValueInst>(&I)) { continue; } else if (auto *sga = dyn_cast<GlobalAddrInst>(&I)) { if (SGA) return nullptr; SGA = sga; GVar = SGA->getReferencedGlobal(); } else if (auto *SI = dyn_cast<StoreInst>(&I)) { if (HasStore || SI->getDest() != SGA) return nullptr; HasStore = true; SILValue value = SI->getSrc(); // We only handle StructInst and TupleInst being stored to a // global variable for now. if (!isa<StructInst>(value) && !isa<TupleInst>(value)) return nullptr; InitVal = cast<SingleValueInstruction>(value); } else if (!SILGlobalVariable::isValidStaticInitializerInst(&I, I.getModule())) { return nullptr; } } if (!InitVal) return nullptr; return GVar; }