Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 33 additions & 12 deletions lib/IRGen/GenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,9 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM,
substitutions.getReplacementTypes()[0]);

// In Embedded Swift we don't have metadata and witness tables, so we can't
// just use TypeInfo's destroyArray, which needs metadata to emit a call to
// swift_arrayDestroy. Emit a loop to destroy elements directly instead.
if (IGF.IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
SILType elemTy = valueTy.first;
const TypeInfo &elemTI = valueTy.second;
Expand All @@ -1103,8 +1106,9 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
IsTriviallyDestroyable)
return;

llvm::Value *firstElem = IGF.Builder.CreateBitCast(
ptr, elemTI.getStorageType()->getPointerTo());
llvm::Value *firstElem =
IGF.Builder.CreatePtrToInt(IGF.Builder.CreateBitCast(
ptr, elemTI.getStorageType()->getPointerTo()), IGF.IGM.IntPtrTy);

auto *origBB = IGF.Builder.GetInsertBlock();
auto *headerBB = IGF.createBasicBlock("loop_header");
Expand All @@ -1118,8 +1122,12 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
IGF.Builder.CreateCondBr(cmp, loopBB, exitBB);

IGF.Builder.emitBlock(loopBB);
auto *addr = IGF.Builder.CreateInBoundsGEP(elemTI.getStorageType(),
firstElem, phi);

llvm::Value *offset =
IGF.Builder.CreateMul(phi, elemTI.getStaticStride(IGF.IGM));
llvm::Value *added = IGF.Builder.CreateAdd(firstElem, offset);
llvm::Value *addr = IGF.Builder.CreateIntToPtr(
added, elemTI.getStorageType()->getPointerTo());

bool isOutlined = false;
elemTI.destroy(IGF, elemTI.getAddressForPointer(addr), elemTy,
Expand Down Expand Up @@ -1168,6 +1176,9 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
llvm::Value *src = args.claimNext();
llvm::Value *count = args.claimNext();

// In Embedded Swift we don't have metadata and witness tables, so we can't
// just use TypeInfo's initialize... and assign... APIs, which need
// metadata to emit calls. Emit a loop to process elements directly instead.
if (IGF.IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
auto tyPair = getLoweredTypeAndTypeInfo(
IGF.IGM, substitutions.getReplacementTypes()[0]);
Expand All @@ -1183,10 +1194,14 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
return;
}

llvm::Value *firstSrcElem = IGF.Builder.CreateBitCast(
src, elemTI.getStorageType()->getPointerTo());
llvm::Value *firstDestElem = IGF.Builder.CreateBitCast(
dest, elemTI.getStorageType()->getPointerTo());
llvm::Value *firstSrcElem = IGF.Builder.CreatePtrToInt(
IGF.Builder.CreateBitCast(src,
elemTI.getStorageType()->getPointerTo()),
IGF.IGM.IntPtrTy);
llvm::Value *firstDestElem = IGF.Builder.CreatePtrToInt(
IGF.Builder.CreateBitCast(dest,
elemTI.getStorageType()->getPointerTo()),
IGF.IGM.IntPtrTy);

auto *origBB = IGF.Builder.GetInsertBlock();
auto *headerBB = IGF.createBasicBlock("loop_header");
Expand Down Expand Up @@ -1214,10 +1229,16 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
break;
}

auto *srcElem = IGF.Builder.CreateInBoundsGEP(elemTI.getStorageType(),
firstSrcElem, idx);
auto *destElem = IGF.Builder.CreateInBoundsGEP(elemTI.getStorageType(),
firstDestElem, idx);
llvm::Value *offset =
IGF.Builder.CreateMul(idx, elemTI.getStaticStride(IGF.IGM));

llvm::Value *srcAdded = IGF.Builder.CreateAdd(firstSrcElem, offset);
auto *srcElem = IGF.Builder.CreateIntToPtr(
srcAdded, elemTI.getStorageType()->getPointerTo());
llvm::Value *dstAdded = IGF.Builder.CreateAdd(firstDestElem, offset);
auto *destElem = IGF.Builder.CreateIntToPtr(
dstAdded, elemTI.getStorageType()->getPointerTo());

Address destAddr = elemTI.getAddressForPointer(destElem);
Address srcAddr = elemTI.getAddressForPointer(srcElem);

Expand Down
7 changes: 7 additions & 0 deletions test/embedded/array-builtins-exec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ struct Large : P {
}
}

enum Enum {
case nontrivial(Noisy)
case trivial(Int)
}

func exerciseArrayValueWitnesses<T>(_ value: T) {
let buf = UnsafeMutablePointer<T>.allocate(capacity: 5)

Expand All @@ -52,6 +57,8 @@ func test() {
exerciseArrayValueWitnesses(44)
exerciseArrayValueWitnesses(Noisy())
exerciseArrayValueWitnesses(Large())
exerciseArrayValueWitnesses(Enum.trivial(42))
exerciseArrayValueWitnesses(Enum.nontrivial(Noisy()))
}
precondition(NoisyLifeCount == NoisyDeathCount)
print("Checks out")
Expand Down
20 changes: 20 additions & 0 deletions test/embedded/arrays-enums.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -parse-as-library -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s

// REQUIRES: swift_in_compiler
// REQUIRES: executable_test
// REQUIRES: optimized_stdlib
// REQUIRES: OS=macosx || OS=linux-gnu

enum Node {
indirect case inner(Node, Node)
case leaf(Int)
}

@main
struct Main {
static func main() {
_ = [Node.leaf(42), Node.leaf(42)]
print("OK!")
// CHECK: OK!
}
}