Skip to content

[NFC] A trio of patches to improve incremental build times and compiler abstraction #34172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 3, 2020
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
6 changes: 6 additions & 0 deletions cmake/modules/AddSwift.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -630,3 +630,9 @@ macro(add_swift_tool_symlink name dest component)
add_llvm_tool_symlink(${name} ${dest} ALWAYS_GENERATE)
llvm_install_symlink(${name} ${dest} ALWAYS_GENERATE COMPONENT ${component})
endmacro()

# Declare that files in this library are built with LLVM's support
# libraries available.
macro(set_swift_llvm_is_available)
add_compile_options(-DSWIFT_LLVM_SUPPORT_IS_AVAILABLE)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not instead of this just forward to __swift::__runtime::llvm_unreachable instead of llvm_unreachable? We should have that in the LLVMSupport in the runtime as well (or can be trivially restored).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a lot of code in headers, some of which can be usefully included in multiple environments: the compiler (which links LLVM support), the runtime (which can have a limited support library), and various other tools (which we generally shouldn't add linker assumptions to). This define tells those headers which environment we're in so that they can use the best implementation mechanism for that environment. This means that in code we can provide a single interface that works anywhere instead of expecting clients to carefully pick which interface they use; for example, it's now always fine to just use swift_unreachable.

I think what you're suggesting doesn't address that problem at all, because we'd be assuming the existence of a swift::runtime::unreachable. Without some level of configuration awareness, that actually makes the problem worse, because we'd have to actually put that function somewhere that gets linked into everything. Whereas if we want the runtime to have a better unreachable implementation than the current non-LLVM one, we could certainly just extend my approach to pass -DSWIFT_RUNTIME_SUPPORT_IS_AVAILABLE and make Unreachable.h take advantage of that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was suggesting that for anything in stdlib, swift_unreachable just maps to __swift::__runtime::llvm_unavailable which is part of stdlib/LLVMSupport and for the compiler we just use llvm_unreachable from LLVMSupport which is linked against anyways.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Not everything in stdlib/ is linked into the runtime. It might be linked with the runtime, but we don't want to export symbols like this from the runtime.
  2. I'm pretty sure that not everything in lib/ is linked with LLVMSupport.
  3. The whole point of the cmake stuff here is telling the compiler what kind of thing we're building as part of, because that's not currently passed down in any other way that I can see.

endmacro()
14 changes: 7 additions & 7 deletions include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
#include "swift/Basic/RelativePointer.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/Basic/Unreachable.h"
#include "../../../stdlib/public/SwiftShims/HeapObject.h"
#if SWIFT_OBJC_INTEROP
#include <objc/runtime.h>
Expand Down Expand Up @@ -4664,7 +4664,7 @@ int32_t TargetTypeContextDescriptor<Runtime>::getGenericArgumentOffset() const {
return llvm::cast<TargetStructDescriptor<Runtime>>(this)
->getGenericArgumentOffset();
default:
swift_runtime_unreachable("Not a type context descriptor.");
swift_unreachable("Not a type context descriptor.");
}
}

Expand All @@ -4682,7 +4682,7 @@ TargetTypeContextDescriptor<Runtime>::getFullGenericContextHeader() const {
return llvm::cast<TargetStructDescriptor<Runtime>>(this)
->getFullGenericContextHeader();
default:
swift_runtime_unreachable("Not a type context descriptor.");
swift_unreachable("Not a type context descriptor.");
}
}

Expand All @@ -4699,7 +4699,7 @@ TargetTypeContextDescriptor<Runtime>::getGenericParams() const {
case ContextDescriptorKind::OpaqueType:
return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)->getGenericParams();
default:
swift_runtime_unreachable("Not a type context descriptor.");
swift_unreachable("Not a type context descriptor.");
}
}

Expand All @@ -4717,7 +4717,7 @@ TargetTypeContextDescriptor<Runtime>::getForeignMetadataInitialization() const {
return llvm::cast<TargetStructDescriptor<Runtime>>(this)
->getForeignMetadataInitialization();
default:
swift_runtime_unreachable("Not a type context descriptor.");
swift_unreachable("Not a type context descriptor.");
}
}

Expand All @@ -4735,7 +4735,7 @@ TargetTypeContextDescriptor<Runtime>::getSingletonMetadataInitialization() const
return llvm::cast<TargetClassDescriptor<Runtime>>(this)
->getSingletonMetadataInitialization();
default:
swift_runtime_unreachable("Not a enum, struct or class type descriptor.");
swift_unreachable("Not a enum, struct or class type descriptor.");
}
}

Expand All @@ -4753,7 +4753,7 @@ TargetTypeContextDescriptor<Runtime>::getCanonicicalMetadataPrespecializations()
return llvm::cast<TargetClassDescriptor<Runtime>>(this)
->getCanonicicalMetadataPrespecializations();
default:
swift_runtime_unreachable("Not a type context descriptor.");
swift_unreachable("Not a type context descriptor.");
}
}

Expand Down
29 changes: 2 additions & 27 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
#define SWIFT_ABI_METADATAVALUES_H

#include "swift/ABI/KeyPath.h"
#include "swift/ABI/ProtocolDispatchStrategy.h"
#include "swift/AST/Ownership.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/FlagSet.h"
#include "swift/Runtime/Unreachable.h"

#include <stdlib.h>
#include <stdint.h>
Expand Down Expand Up @@ -410,20 +410,6 @@ enum class SpecialProtocol: uint8_t {
Error = 1,
};

/// Identifiers for protocol method dispatch strategies.
enum class ProtocolDispatchStrategy: uint8_t {
/// Uses ObjC method dispatch.
///
/// This must be 0 for ABI compatibility with Objective-C protocol_t records.
ObjC = 0,

/// Uses Swift protocol witness table dispatch.
///
/// To invoke methods of this protocol, a pointer to a protocol witness table
/// corresponding to the protocol conformance must be available.
Swift = 1,
};

/// Flags for protocol descriptors.
class ProtocolDescriptorFlags {
typedef uint32_t int_type;
Expand Down Expand Up @@ -486,18 +472,7 @@ class ProtocolDescriptorFlags {

/// Does the protocol require a witness table for method dispatch?
bool needsWitnessTable() const {
return needsWitnessTable(getDispatchStrategy());
}

static bool needsWitnessTable(ProtocolDispatchStrategy strategy) {
switch (strategy) {
case ProtocolDispatchStrategy::ObjC:
return false;
case ProtocolDispatchStrategy::Swift:
return true;
}

swift_runtime_unreachable("Unhandled ProtocolDispatchStrategy in switch.");
return swift::protocolRequiresWitnessTable(getDispatchStrategy());
}

/// Return the identifier if this is a special runtime-known protocol.
Expand Down
54 changes: 54 additions & 0 deletions include/swift/ABI/ProtocolDispatchStrategy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//===--- ProtocolDispatchStrategy.h - ---------------------------*- 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 header declares the ProtocolDispatchStrategy enum and some
// related operations. It's split out because we would otherwise need
// to include MetadataValues.h in some relatively central headers.s
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_ABI_PROTOCOLDISPATCHSTRATEGY_H
#define SWIFT_ABI_PROTOCOLDISPATCHSTRATEGY_H

#include "swift/Basic/Unreachable.h"

namespace swift {

/// Identifiers for protocol method dispatch strategies.
enum class ProtocolDispatchStrategy: uint8_t {
/// Uses ObjC method dispatch.
///
/// This must be 0 for ABI compatibility with Objective-C protocol_t records.
ObjC = 0,

/// Uses Swift protocol witness table dispatch.
///
/// To invoke methods of this protocol, a pointer to a protocol witness table
/// corresponding to the protocol conformance must be available.
Swift = 1,
};

/// Does a protocol using the given strategy require a witness table?
inline bool protocolRequiresWitnessTable(ProtocolDispatchStrategy strategy) {
switch (strategy) {
case ProtocolDispatchStrategy::ObjC:
return false;
case ProtocolDispatchStrategy::Swift:
return true;
}

swift_unreachable("Unhandled ProtocolDispatchStrategy in switch.");
}

}

#endif
49 changes: 49 additions & 0 deletions include/swift/Basic/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,59 @@
#define SWIFT_ASSUME(x)
#endif

/// Attributes.

#if __has_attribute(constructor)
#define SWIFT_CONSTRUCTOR __attribute__((constructor))
#else
#define SWIFT_CONSTRUCTOR
#endif

/// \macro SWIFT_GNUC_PREREQ
/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't
/// available.
#ifndef SWIFT_GNUC_PREREQ
# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
# define SWIFT_GNUC_PREREQ(maj, min, patch) \
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
((maj) << 20) + ((min) << 10) + (patch))
# elif defined(__GNUC__) && defined(__GNUC_MINOR__)
# define SWIFT_GNUC_PREREQ(maj, min, patch) \
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
# else
# define SWIFT_GNUC_PREREQ(maj, min, patch) 0
# endif
#endif


/// SWIFT_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,
/// mark a method "not for inlining".
#if __has_attribute(noinline) || SWIFT_GNUC_PREREQ(3, 4, 0)
#define SWIFT_ATTRIBUTE_NOINLINE __attribute__((noinline))
#elif defined(_MSC_VER)
#define SWIFT_ATTRIBUTE_NOINLINE __declspec(noinline)
#else
#define SWIFT_ATTRIBUTE_NOINLINE
#endif

/// SWIFT_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do
/// so, mark a method "always inline" because it is performance sensitive. GCC
/// 3.4 supported this but is buggy in various cases and produces unimplemented
/// errors, just use it in GCC 4.0 and later.
#if __has_attribute(always_inline) || SWIFT_GNUC_PREREQ(4, 0, 0)
#define SWIFT_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
#elif defined(_MSC_VER)
#define SWIFT_ATTRIBUTE_ALWAYS_INLINE __forceinline
#else
#define SWIFT_ATTRIBUTE_ALWAYS_INLINE
#endif

#ifdef __GNUC__
#define SWIFT_ATTRIBUTE_NORETURN __attribute__((noreturn))
#elif defined(_MSC_VER)
#define SWIFT_ATTRIBUTE_NORETURN __declspec(noreturn)
#else
#define SWIFT_ATTRIBUTE_NORETURN
#endif

#endif // SWIFT_BASIC_COMPILER_H
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===--- Unreachable.h - Implements swift_runtime_unreachable ---*- C++ -*-===//
//===--- Unreachable.h - Implements swift_unreachable ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
Expand All @@ -10,24 +10,38 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines swift_runtime_unreachable, an LLVM-independent
// implementation of llvm_unreachable.
// This file defines swift_unreachable, which provides the
// functionality of llvm_unreachable without necessarily depending on
// the LLVM support libraries.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_RUNTIME_UNREACHABLE_H
#define SWIFT_RUNTIME_UNREACHABLE_H
#ifndef SWIFT_BASIC_UNREACHABLE_H
#define SWIFT_BASIC_UNREACHABLE_H

#ifdef SWIFT_LLVM_SUPPORT_IS_AVAILABLE

// The implementation when LLVM is available.

#include "llvm/Support/ErrorHandling.h"
#define swift_unreachable llvm_unreachable

#else

// The implementation when LLVM is not available.

#include <assert.h>
#include <stdlib.h>

#include "swift/Runtime/Config.h"

SWIFT_RUNTIME_ATTRIBUTE_NORETURN
inline static void swift_runtime_unreachable(const char *msg) {
inline static void swift_unreachable(const char *msg) {
assert(false && msg);
(void)msg;
abort();
}

#endif // SWIFT_RUNTIME_UNREACHABLE_H
#endif

#endif
2 changes: 1 addition & 1 deletion include/swift/Demangling/TypeDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "swift/Demangling/Demangler.h"
#include "swift/Demangling/NamespaceMacros.h"
#include "swift/Runtime/Portability.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/Basic/Unreachable.h"
#include "swift/Strings.h"
#include "llvm/ADT/ArrayRef.h"
#include <vector>
Expand Down
4 changes: 2 additions & 2 deletions include/swift/Reflection/ReflectionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include "swift/Reflection/TypeLowering.h"
#include "swift/Reflection/TypeRef.h"
#include "swift/Reflection/TypeRefBuilder.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/Basic/Unreachable.h"

#include <set>
#include <unordered_map>
Expand Down Expand Up @@ -1302,7 +1302,7 @@ class ReflectionContext
return true;
}

swift_runtime_unreachable("Unhandled MetadataSourceKind in switch.");
swift_unreachable("Unhandled MetadataSourceKind in switch.");
}

/// Read metadata for a captured generic type from a closure context.
Expand Down
4 changes: 2 additions & 2 deletions include/swift/Reflection/TypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "llvm/Support/Casting.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/Remote/MetadataReader.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/Basic/Unreachable.h"

namespace swift {
namespace reflection {
Expand Down Expand Up @@ -856,7 +856,7 @@ class TypeRefVisitor {
#include "swift/Reflection/TypeRefs.def"
}

swift_runtime_unreachable("Unhandled TypeRefKind in switch.");
swift_unreachable("Unhandled TypeRefKind in switch.");
}
};

Expand Down
6 changes: 3 additions & 3 deletions include/swift/Remote/MetadataReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "swift/ABI/TypeIdentity.h"
#include "swift/Runtime/ExistentialContainer.h"
#include "swift/Runtime/HeapObject.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/Basic/Unreachable.h"

#include <vector>
#include <unordered_map>
Expand Down Expand Up @@ -923,7 +923,7 @@ class MetadataReader {
}
}

swift_runtime_unreachable("Unhandled MetadataKind in switch");
swift_unreachable("Unhandled MetadataKind in switch");
}

TypeLookupErrorOr<typename BuilderType::BuiltType>
Expand Down Expand Up @@ -1295,7 +1295,7 @@ class MetadataReader {
}
}

swift_runtime_unreachable("Unhandled IsaEncodingKind in switch.");
swift_unreachable("Unhandled IsaEncodingKind in switch.");
}

/// Read the offset of the generic parameters of a class from the nominal
Expand Down
Loading