Files
swift-mirror/lib/IRGen/GenPointerAuth.h
Dario Rexin a8d4d57f11 [IRGen] Generate compressed representation of value witnesses (#63813)
rdar://105837040

* WIP: Store layout string in type metadata

* WIP: More cases working

* WIP: Layout strings almost working

* Add layout string pointer to struct metadata

* Fetch bytecode layout strings from metadata in runtime

* More efficient bytecode layout

* Add support for interpreted generics in layout strings

* Layout string instantiation, take and more

* Remove duplicate information from layout strings

* Include size of previous object in next objects offset to reduce number of increments at runtime

* Add support for existentials

* Build type layout strings with StructBuilder to support target sizes and metadata pointers

* Add support for resilient types

* Properly cache layout strings in compiler

* Generic resilient types working

* Non-generic resilient types working

* Instantiate resilient type in layout when possible

* Fix a few issues around alignment and signing

* Disable generics, fix static alignment

* Fix MultiPayloadEnum size when no extra tag is necessary

* Fixes after rebase

* Cleanup

* Fix most tests

* Fix objcImplementattion and non-Darwin builds

* Fix BytecodeLayouts on non-Darwin

* Fix Linux build

* Fix sizes in linux tests

* Sign layout string pointers

* Use nullptr instead of debug value
2023-02-24 15:40:28 -08:00

210 lines
7.0 KiB
C++

//===--- GenPointerAuth.h - IRGen for pointer authentication ----*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the basic interface for generating LLVM IR for pointer
// authentication.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_IRGEN_GENPOINTERAUTH_H
#define SWIFT_IRGEN_GENPOINTERAUTH_H
#include "swift/IRGen/ValueWitness.h"
#include "swift/Basic/ExternalUnion.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/ProtocolAssociations.h"
#include "swift/AST/Types.h"
#include "swift/SIL/SILDeclRef.h"
namespace llvm {
class ConstantInt;
class Value;
}
namespace clang {
class PointerAuthSchema;
}
namespace swift {
namespace irgen {
class FunctionPointer;
class IRGenFunction;
class IRGenModule;
class PointerAuthInfo;
/// Additional information about the source of a function pointer.
class PointerAuthEntity {
public:
enum class Special {
BlockCopyHelper,
BlockDisposeHelper,
HeapDestructor,
PartialApplyCapture,
TypeDescriptor,
TypeDescriptorAsArgument,
KeyPathDestroy,
KeyPathCopy,
KeyPathEquals,
KeyPathHash,
KeyPathGetter,
KeyPathNonmutatingSetter,
KeyPathMutatingSetter,
KeyPathGetLayout,
KeyPathInitializer,
KeyPathMetadataAccessor,
DynamicReplacementKey,
ProtocolConformanceDescriptor,
ProtocolConformanceDescriptorAsArgument,
TypeLayoutString,
};
private:
enum class Kind {
None,
Special,
ValueWitness,
AssociatedType,
AssociatedConformance,
CanSILFunctionType,
CoroutineYieldTypes,
SILDeclRef,
SILFunction,
} StoredKind;
using Members = ExternalUnionMembers<void,
Special,
ValueWitness,
AssociatedType,
AssociatedConformance,
CanSILFunctionType,
SILDeclRef,
SILFunction *>;
static Members::Index getStorageIndexForKind(Kind kind) {
switch (kind) {
case Kind::None:
return Members::indexOf<void>();
case Kind::Special:
return Members::indexOf<Special>();
case Kind::ValueWitness:
return Members::indexOf<ValueWitness>();
case Kind::CoroutineYieldTypes:
case Kind::CanSILFunctionType:
return Members::indexOf<CanSILFunctionType>();
case Kind::SILDeclRef:
return Members::indexOf<SILDeclRef>();
case Kind::AssociatedType:
return Members::indexOf<AssociatedType>();
case Kind::AssociatedConformance:
return Members::indexOf<AssociatedConformance>();
case Kind::SILFunction:
return Members::indexOf<SILFunction *>();
}
llvm_unreachable("bad kind");
}
ExternalUnion<Kind, Members, getStorageIndexForKind> Storage;
static_assert(decltype(Storage)::union_is_trivially_copyable,
"please add copy/move/dtor if you need a non-trivial type");
public:
PointerAuthEntity()
: StoredKind(Kind::None) {
}
PointerAuthEntity(Special specialKind)
: StoredKind(Kind::Special) {
Storage.emplace<Special>(StoredKind, specialKind);
}
PointerAuthEntity(CanSILFunctionType type)
: StoredKind(Kind::CanSILFunctionType) {
Storage.emplace<CanSILFunctionType>(StoredKind, type);
}
PointerAuthEntity(SILDeclRef decl)
: StoredKind(Kind::SILDeclRef) {
Storage.emplace<SILDeclRef>(StoredKind, decl);
}
PointerAuthEntity(ValueWitness witness)
: StoredKind(Kind::ValueWitness) {
assert(isValueWitnessFunction(witness));
Storage.emplace<ValueWitness>(StoredKind, witness);
}
PointerAuthEntity(AssociatedType association)
: StoredKind(Kind::AssociatedType) {
Storage.emplaceAggregate<AssociatedType>(StoredKind, association);
}
PointerAuthEntity(const AssociatedConformance &association)
: StoredKind(Kind::AssociatedConformance) {
Storage.emplaceAggregate<AssociatedConformance>(StoredKind, association);
}
PointerAuthEntity(SILFunction *f)
: StoredKind(Kind::SILFunction) {
Storage.emplace<SILFunction *>(StoredKind, f);
}
static PointerAuthEntity forYieldTypes(CanSILFunctionType fnType) {
assert(fnType->isCoroutine());
PointerAuthEntity result;
result.StoredKind = Kind::CoroutineYieldTypes;
result.Storage.emplace<CanSILFunctionType>(result.StoredKind, fnType);
return result;
}
llvm::ConstantInt *getDeclDiscriminator(IRGenModule &IGM) const;
llvm::ConstantInt *getTypeDiscriminator(IRGenModule &IGM) const;
};
std::pair<clang::PointerAuthSchema, PointerAuthEntity>
getCoroutineResumeFunctionPointerAuth(IRGenModule &IGM,
CanSILFunctionType coroutineFnType);
/// Blend a small integer discriminator with the given address value
/// in a way that is assumed to maximally preserve entropy from both.
llvm::Value *emitPointerAuthBlend(IRGenFunction &IGF,
llvm::Value *address,
llvm::Value *discriminator);
/// Strip the signature of a signed pointer value.
/// The return value has the same type as the input.
llvm::Value *emitPointerAuthStrip(IRGenFunction &IGF, llvm::Value *fnPtr,
unsigned Key);
/// Sign the given pointer value, which is assumed to be unsigned.
/// The return value has the same type as the input. This is a no-op if
/// the target auth info has disabled signing.
llvm::Value *emitPointerAuthSign(IRGenFunction &IGF, llvm::Value *fnPtr,
const PointerAuthInfo &newAuth);
/// Authenticate the given pointer value and return an unsigned value.
llvm::Value *emitPointerAuthAuth(IRGenFunction &IGF, llvm::Value *fnPtr,
const PointerAuthInfo &oldAuth);
/// Resign the given function pointer.
FunctionPointer emitPointerAuthResign(IRGenFunction &IGF,
const FunctionPointer &fn,
const PointerAuthInfo &newAuth);
/// Resign the given pointer value. This function does the right thing
/// for unsigned input and result schemas. The result will have the same
/// type as the input.
llvm::Value *emitPointerAuthResign(IRGenFunction &IGF,
llvm::Value *fnPtr,
const PointerAuthInfo &oldAuth,
const PointerAuthInfo &newAuth);
/// The (non-ABI) discriminator used for non-constant captures of
/// partial apply functions.
const uint16_t PointerAuthDiscriminator_PartialApplyCapture = 7185;
} // end namespace irgen
} // end namespace swift
#endif