mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
168 lines
5.4 KiB
C++
168 lines
5.4 KiB
C++
//===--- SILGlobalVariable.cpp - Defines SILGlobalVariable structure ------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/SIL/SILGlobalVariable.h"
|
|
#include "swift/SIL/SILModule.h"
|
|
|
|
using namespace swift;
|
|
|
|
SILGlobalVariable *SILGlobalVariable::create(SILModule &M, SILLinkage linkage,
|
|
bool IsFragile,
|
|
StringRef name,
|
|
SILType loweredType,
|
|
Optional<SILLocation> loc,
|
|
VarDecl *Decl) {
|
|
// Get a StringMapEntry for the variable. As a sop to error cases,
|
|
// allow the name to have an empty string.
|
|
llvm::StringMapEntry<SILGlobalVariable*> *entry = nullptr;
|
|
if (!name.empty()) {
|
|
entry = &*M.GlobalVariableMap.insert(std::make_pair(name, nullptr)).first;
|
|
assert(!entry->getValue() && "global variable already exists");
|
|
name = entry->getKey();
|
|
}
|
|
|
|
auto var = new (M) SILGlobalVariable(M, linkage, IsFragile, name,
|
|
loweredType, loc, Decl);
|
|
|
|
if (entry) entry->setValue(var);
|
|
return var;
|
|
}
|
|
|
|
|
|
SILGlobalVariable::SILGlobalVariable(SILModule &Module, SILLinkage Linkage,
|
|
bool IsFragile,
|
|
StringRef Name, SILType LoweredType,
|
|
Optional<SILLocation> Loc, VarDecl *Decl)
|
|
: Module(Module),
|
|
Name(Name),
|
|
LoweredType(LoweredType),
|
|
Location(Loc),
|
|
Linkage(unsigned(Linkage)),
|
|
Fragile(IsFragile),
|
|
VDecl(Decl) {
|
|
IsDeclaration = isAvailableExternally(Linkage);
|
|
setLet(Decl ? Decl->isLet() : false);
|
|
InitializerF = nullptr;
|
|
Module.silGlobals.push_back(this);
|
|
}
|
|
|
|
void SILGlobalVariable::setInitializer(SILFunction *InitF) {
|
|
if (InitializerF)
|
|
InitializerF->decrementRefCount();
|
|
// Increment the ref count to make sure it will not be eliminated.
|
|
InitF->incrementRefCount();
|
|
InitializerF = InitF;
|
|
}
|
|
|
|
SILGlobalVariable::~SILGlobalVariable() {
|
|
getModule().GlobalVariableMap.erase(Name);
|
|
}
|
|
|
|
// FIXME
|
|
|
|
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() != SGA)
|
|
return false;
|
|
HasStore = true;
|
|
Val = dyn_cast<SILInstruction>(SI->getSrc());
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
// Objective-C selector string literals cannot be used in static
|
|
// initializers.
|
|
if (auto *stringLit = dyn_cast<StringLiteralInst>(&I)) {
|
|
switch (stringLit->getEncoding()) {
|
|
case StringLiteralInst::Encoding::UTF8:
|
|
case StringLiteralInst::Encoding::UTF16:
|
|
continue;
|
|
|
|
case StringLiteralInst::Encoding::ObjCSelector:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (I.getKind() != ValueKind::ReturnInst &&
|
|
I.getKind() != ValueKind::StructInst &&
|
|
I.getKind() != ValueKind::TupleInst &&
|
|
I.getKind() != ValueKind::IntegerLiteralInst &&
|
|
I.getKind() != ValueKind::FloatLiteralInst)
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool SILGlobalVariable::canBeStaticInitializer(SILFunction *F) {
|
|
SILInstruction *dummySI;
|
|
SILGlobalVariable *dummyGV;
|
|
return analyzeStaticInitializer(F, dummySI, dummyGV);
|
|
}
|
|
|
|
/// Check if a given SILFunction can be a static initializer. If yes, return
|
|
/// the SILGlobalVariable that it writes to.
|
|
SILGlobalVariable *SILGlobalVariable::getVariableOfStaticInitializer(
|
|
SILFunction *F) {
|
|
SILInstruction *dummySI;
|
|
SILGlobalVariable *GV;
|
|
if(analyzeStaticInitializer(F, dummySI, GV))
|
|
return GV;
|
|
return nullptr;
|
|
}
|
|
|
|
/// Return the value that is written into the global variable.
|
|
SILInstruction *SILGlobalVariable::getValueOfStaticInitializer() {
|
|
if (!InitializerF)
|
|
return nullptr;
|
|
|
|
SILInstruction *SI;
|
|
SILGlobalVariable *dummyGV;
|
|
if(analyzeStaticInitializer(InitializerF, SI, dummyGV))
|
|
return SI;
|
|
return nullptr;
|
|
}
|