Skip to content

Commit

Permalink
SIL: support statically initialized StaticString globals
Browse files Browse the repository at this point in the history
The main part of the change is to support the ptr_to_int builtin in statically initialized globals. This builtin is used to build a StaticString from a string_literal.
On the other hand I removed the support of the FPTrunc builtin, which is not needed anyway (because it can be constant propagated).
  • Loading branch information
eeckstein committed Sep 19, 2017
1 parent da22d25 commit fb935a3
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 13 deletions.
3 changes: 2 additions & 1 deletion include/swift/SIL/SILGlobalVariable.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ class SILGlobalVariable

/// Returns true if \p I is a valid instruction to be contained in the
/// static initializer.
static bool isValidStaticInitializerInst(const SILInstruction *I);
static bool isValidStaticInitializerInst(const SILInstruction *I,
SILModule &M);

void dropAllReferences() {
StaticInitializerBlock.dropAllReferences();
Expand Down
19 changes: 13 additions & 6 deletions lib/IRGen/GenConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "TypeInfo.h"
#include "StructLayout.h"
#include "swift/Basic/Range.h"
#include "swift/SIL/SILModule.h"

using namespace swift;
using namespace irgen;
Expand Down Expand Up @@ -71,18 +72,24 @@ llvm::Constant *irgen::emitAddrOfConstantString(IRGenModule &IGM,
}

static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) {
if (auto *SI = dyn_cast<StructInst>(operand))
if (auto *SI = dyn_cast<StructInst>(operand)) {
return emitConstantStruct(IGM, SI);
else if (auto *TI = dyn_cast<TupleInst>(operand))
} else if (auto *TI = dyn_cast<TupleInst>(operand)) {
return emitConstantTuple(IGM, TI);
else if (auto *ILI = dyn_cast<IntegerLiteralInst>(operand))
} else if (auto *ILI = dyn_cast<IntegerLiteralInst>(operand)) {
return emitConstantInt(IGM, ILI);
else if (auto *FLI = dyn_cast<FloatLiteralInst>(operand))
} else if (auto *FLI = dyn_cast<FloatLiteralInst>(operand)) {
return emitConstantFP(IGM, FLI);
else if (auto *SLI = dyn_cast<StringLiteralInst>(operand))
} else if (auto *SLI = dyn_cast<StringLiteralInst>(operand)) {
return emitAddrOfConstantString(IGM, SLI);
else
} else if (auto *BI = dyn_cast<BuiltinInst>(operand)) {
assert(IGM.getSILModule().getBuiltinInfo(BI->getName()).ID ==
BuiltinValueKind::PtrToInt);
llvm::Constant *ptr = emitConstantValue(IGM, BI->getArguments()[0]);
return llvm::ConstantExpr::getPtrToInt(ptr, IGM.IntPtrTy);
} else {
llvm_unreachable("Unsupported SILInstruction in static initializer!");
}
}

namespace {
Expand Down
7 changes: 4 additions & 3 deletions lib/SIL/SILGlobalVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,13 @@ SILInstruction *SILGlobalVariable::getStaticInitializerValue() {
return &StaticInitializerBlock.back();
}

bool SILGlobalVariable::isValidStaticInitializerInst(const SILInstruction *I) {
bool SILGlobalVariable::isValidStaticInitializerInst(const SILInstruction *I,
SILModule &M) {
switch (I->getKind()) {
case ValueKind::BuiltinInst: {
auto *bi = cast<BuiltinInst>(I);
switch (bi->getBuiltinInfo().ID) {
case BuiltinValueKind::FPTrunc:
switch (M.getBuiltinInfo(bi->getName()).ID) {
case BuiltinValueKind::PtrToInt:
if (isa<LiteralInst>(bi->getArguments()[0]))
return true;
break;
Expand Down
3 changes: 2 additions & 1 deletion lib/SIL/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4494,7 +4494,8 @@ void SILGlobalVariable::verify() const {

// Verify the static initializer.
for (const SILInstruction &I : StaticInitializerBlock) {
assert(isValidStaticInitializerInst(&I) && "illegal static initializer");
assert(isValidStaticInitializerInst(&I, getModule()) &&
"illegal static initializer");
if (&I == &StaticInitializerBlock.back()) {
assert(I.use_empty() && "Init value must not have another use");
} else {
Expand Down
5 changes: 3 additions & 2 deletions lib/SILOptimizer/IPO/GlobalOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,8 @@ static SILGlobalVariable *getVariableOfStaticInitializer(SILFunction *InitFunc,
// global variable for now.
if (!isa<StructInst>(InitVal) && !isa<TupleInst>(InitVal))
return nullptr;
} else if (!SILGlobalVariable::isValidStaticInitializerInst(&I)) {
} else if (!SILGlobalVariable::isValidStaticInitializerInst(&I,
I.getModule())) {
return nullptr;
}
}
Expand Down Expand Up @@ -1008,7 +1009,7 @@ static void getFields(ClassDecl *Cl, SmallVectorImpl<VarDecl *> &Fields) {
/// all it's operands.
static bool isValidInitVal(SILValue V) {
if (SILInstruction *I = dyn_cast<SILInstruction>(V)) {
if (!SILGlobalVariable::isValidStaticInitializerInst(I))
if (!SILGlobalVariable::isValidStaticInitializerInst(I, I->getModule()))
return false;

for (Operand &Op : I->getAllOperands()) {
Expand Down
17 changes: 17 additions & 0 deletions test/SILOptimizer/static_arrays.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
// CHECK: object {{.*}} ({{[^,]*}}, [tail_elems] {{[^,]*}}, {{[^,]*}})
// CHECK-NEXT: }

// CHECK-LABEL: outlined variable #0 of returnStaticStringArray()
// CHECK-NEXT: sil_global private @{{.*}}returnStaticStringArray{{.*}} = {
// CHECK-DAG: string_literal utf8 "a"
// CHECK-DAG: string_literal utf8 "b"
// CHECK: object {{.*}} ({{[^,]*}}, [tail_elems] {{[^,]*}}, {{[^,]*}})
// CHECK-NEXT: }

// CHECK-LABEL: outlined variable #0 of passArray()
// CHECK-NEXT: sil_global private @{{.*}}passArray{{.*}} = {
// CHECK-DAG: integer_literal $Builtin.Int{{[0-9]+}}, 27
Expand Down Expand Up @@ -80,6 +87,14 @@ public func returnArray() -> [Int] {
return [20, 21]
}

// CHECK-LABEL: sil {{.*}}returnStaticStringArray{{.*}} : $@convention(thin) () -> @owned Array<StaticString> {
// CHECK: global_value @{{.*}}returnStaticStringArray{{.*}}
// CHECK: return
@inline(never)
public func returnStaticStringArray() -> [StaticString] {
return ["a", "b"]
}

public var gg: [Int]?

@inline(never)
Expand Down Expand Up @@ -132,6 +147,8 @@ print(globalVariable)
print(arrayLookup(1))
// CHECK-OUTPUT-NEXT: [20, 21]
print(returnArray())
// CHECK-OUTPUT-NEXT: ["a", "b"]
print(returnStaticStringArray())
passArray()
// CHECK-OUTPUT-NEXT: [29]
print(gg!)
Expand Down

0 comments on commit fb935a3

Please sign in to comment.