Files
swift-mirror/lib/IRGen/IRGenMangler.cpp
Arnold Schwaighofer 43b9d13a2e Add value witnesses for single payload enums
So far single payload enums were implemented in terms of runtime functions which
internally emitted several calls to value witnesses.

This commit adds value witnesses to get and store the enum tag side stepping the
need for witness calls as this information is statically available in many cases

/// int (*getEnumTagSinglePayload)(const T* enum, UINT_TYPE emptyCases)
/// Given an instance of valid single payload enum with a payload of this
/// witness table's type (e.g Optional<ThisType>) , get the tag of the enum.

/// void (*storeEnumTagSinglePayload)(T* enum, INT_TYPE whichCase,
///                                   UINT_TYPE emptyCases)
/// Given uninitialized memory for an instance of a single payload enum with a
/// payload of this witness table's type (e.g Optional<ThisType>), store the
/// tag.

A simple 'for element in array' loop in generic code operating on a
ContigousArray of Int is ~25% faster on arm64.

rdar://31408033
2017-10-23 13:31:46 -07:00

143 lines
4.5 KiB
C++

//===--- IRGenMangler.cpp - mangling of IRGen symbols ---------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "IRGenMangler.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Runtime/Metadata.h"
using namespace swift;
using namespace irgen;
const char *getManglingForWitness(swift::Demangle::ValueWitnessKind kind) {
switch (kind) {
#define VALUE_WITNESS(MANGLING, NAME) \
case swift::Demangle::ValueWitnessKind::NAME: return #MANGLING;
#include "swift/Demangling/ValueWitnessMangling.def"
}
llvm_unreachable("not a function witness");
}
std::string IRGenMangler::mangleValueWitness(Type type, ValueWitness witness) {
beginMangling();
appendType(type);
const char *Code = nullptr;
switch (witness) {
#define GET_MANGLING(ID) \
case ValueWitness::ID: Code = getManglingForWitness(swift::Demangle::ValueWitnessKind::ID); break;
GET_MANGLING(InitializeBufferWithCopyOfBuffer) \
GET_MANGLING(Destroy) \
GET_MANGLING(InitializeWithCopy) \
GET_MANGLING(AssignWithCopy) \
GET_MANGLING(InitializeWithTake) \
GET_MANGLING(AssignWithTake) \
GET_MANGLING(InitializeBufferWithTakeOfBuffer) \
GET_MANGLING(GetEnumTagSinglePayload) \
GET_MANGLING(StoreEnumTagSinglePayload) \
GET_MANGLING(StoreExtraInhabitant) \
GET_MANGLING(GetExtraInhabitantIndex) \
GET_MANGLING(GetEnumTag) \
GET_MANGLING(DestructiveProjectEnumData) \
GET_MANGLING(DestructiveInjectEnumTag)
#undef GET_MANGLING
case ValueWitness::Size:
case ValueWitness::Flags:
case ValueWitness::Stride:
case ValueWitness::ExtraInhabitantFlags:
llvm_unreachable("not a function witness");
}
appendOperator("w", Code);
return finalize();
}
std::string IRGenMangler::manglePartialApplyForwarder(StringRef FuncName) {
if (FuncName.empty()) {
beginMangling();
} else {
if (FuncName.startswith(MANGLING_PREFIX_STR)) {
Buffer << FuncName;
} else {
beginMangling();
appendIdentifier(FuncName);
}
}
appendOperator("TA");
return finalize();
}
std::string IRGenMangler::mangleTypeForReflection(Type Ty,
ModuleDecl *Module,
bool isSingleFieldOfBox) {
Mod = Module;
OptimizeProtocolNames = false;
appendType(Ty);
if (isSingleFieldOfBox)
appendOperator("Xb");
return finalize();
}
std::string IRGenMangler::mangleTypeForLLVMTypeName(CanType Ty) {
// To make LLVM IR more readable we always add a 'T' prefix so that type names
// don't start with a digit and don't need to be quoted.
Buffer << 'T';
if (auto P = dyn_cast<ProtocolType>(Ty)) {
appendProtocolName(P->getDecl());
appendOperator("P");
} else {
appendType(Ty);
}
return finalize();
}
std::string IRGenMangler::
mangleProtocolForLLVMTypeName(ProtocolCompositionType *type) {
ExistentialLayout layout = type->getExistentialLayout();
if (type->isAny()) {
Buffer << "Any";
} else if (layout.isAnyObject()) {
Buffer << "AnyObject";
} else {
// To make LLVM IR more readable we always add a 'T' prefix so that type names
// don't start with a digit and don't need to be quoted.
Buffer << 'T';
auto protocols = layout.getProtocols();
for (unsigned i = 0, e = protocols.size(); i != e; ++i) {
appendProtocolName(protocols[i]->getDecl());
if (i == 0)
appendOperator("_");
}
if (layout.superclass) {
auto superclassTy = layout.superclass;
// We share type infos for different instantiations of a generic type
// when the archetypes have the same exemplars. We cannot mangle
// archetypes, and the mangling does not have to be unique, so we just
// mangle the unbound generic form of the type.
if (superclassTy->hasArchetype()) {
superclassTy = superclassTy->getClassOrBoundGenericClass()
->getDeclaredType();
}
appendType(CanType(superclassTy));
appendOperator("Xc");
} else if (layout.getLayoutConstraint()) {
appendOperator("Xl");
} else {
appendOperator("p");
}
}
return finalize();
}