Skip to content

[stdlib] Slab #76438

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 15 commits into from
Jan 12, 2025
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
2 changes: 1 addition & 1 deletion include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3958,7 +3958,7 @@ class GenericTypeParamDecl final
/// type parameter.
///
/// \code
/// struct Vector<Element, let N: Int>
/// struct Slab<let count: Int, Element: ~Copyable>
/// \endcode
bool isValue() const {
return getParamKind() == GenericTypeParamKind::Value;
Expand Down
7 changes: 7 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -8175,6 +8175,13 @@ ERROR(availability_value_generic_type_only_version_newer, none,
ERROR(invalid_value_for_type_same_type,none,
"cannot constrain type parameter %0 to be integer %1", (Type, Type))

//===----------------------------------------------------------------------===//
// MARK: Slab
//===----------------------------------------------------------------------===//

ERROR(slab_literal_incorrect_count,none,
"expected %0 elements in slab literal, but got %1", (Type, Type))

//===----------------------------------------------------------------------===//
// MARK: @abi Attribute
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/KnownStdlibTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,6 @@ KNOWN_STDLIB_TYPE_DECL(DecodingError, NominalTypeDecl, 0)

KNOWN_STDLIB_TYPE_DECL(Result, NominalTypeDecl, 2)

KNOWN_STDLIB_TYPE_DECL(Slab, NominalTypeDecl, 2)

#undef KNOWN_STDLIB_TYPE_DECL
2 changes: 1 addition & 1 deletion include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -7246,7 +7246,7 @@ class GenericTypeParamType : public SubstitutableType,
/// Returns \c true if this type parameter is declared as a value.
///
/// \code
/// struct Vector<Element, let N: Int>
/// struct Slab<let count: Int, Element: ~Copyable>
/// \endcode
bool isValue() const {
return ParamKind == GenericTypeParamKind::Value;
Expand Down
19 changes: 19 additions & 0 deletions include/swift/RemoteInspection/TypeLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ enum class TypeInfoKind : unsigned {
Reference,
Invalid,
Enum,
Array,
};

class TypeInfo {
Expand Down Expand Up @@ -350,6 +351,24 @@ class ReferenceTypeInfo : public TypeInfo {
}
};

/// Array based layouts like Builtin.FixedArray<N, T>
class ArrayTypeInfo : public TypeInfo {
const TypeInfo *ElementTI;

public:
explicit ArrayTypeInfo(intptr_t size, const TypeInfo *elementTI);

bool readExtraInhabitantIndex(remote::MemoryReader &reader,
remote::RemoteAddress address,
int *extraInhabitantIndex) const override;

BitMask getSpareBits(TypeConverter &TC, bool &hasAddrOnly) const override;

static bool classof(const TypeInfo *TI) {
return TI->getKind() == TypeInfoKind::Array;
}
};

/// This class owns the memory for all TypeInfo instances that it vends.
class TypeConverter {
TypeRefBuilder &Builder;
Expand Down
62 changes: 62 additions & 0 deletions include/swift/RemoteInspection/TypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,68 @@ class SILBoxTypeWithLayoutTypeRef final : public TypeRef {
}
};

class IntegerTypeRef final : public TypeRef {
intptr_t Value;

static TypeRefID Profile(const intptr_t &Value) {
TypeRefID ID;
ID.addInteger((uint64_t)Value);
return ID;
}

public:
IntegerTypeRef(const intptr_t &Value)
: TypeRef(TypeRefKind::Integer), Value(Value) {}

template <typename Allocator>
static const IntegerTypeRef *create(Allocator &A, intptr_t Value) {
FIND_OR_CREATE_TYPEREF(A, IntegerTypeRef, Value);
}

const intptr_t &getValue() const {
return Value;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::Integer;
}
};

class BuiltinFixedArrayTypeRef final : public TypeRef {
const TypeRef *Size;
const TypeRef *Element;

static TypeRefID Profile(const TypeRef *Size, const TypeRef *Element) {
TypeRefID ID;
ID.addPointer(Size);
ID.addPointer(Element);
return ID;
}

public:
BuiltinFixedArrayTypeRef(const TypeRef *Size, const TypeRef *Element)
: TypeRef(TypeRefKind::BuiltinFixedArray), Size(Size), Element(Element) {}

template <typename Allocator>
static const BuiltinFixedArrayTypeRef *create(Allocator &A,
const TypeRef *Size,
const TypeRef *Element) {
FIND_OR_CREATE_TYPEREF(A, BuiltinFixedArrayTypeRef, Size, Element);
}

const TypeRef *getSizeType() const {
return Size;
}

const TypeRef *getElementType() const {
return Element;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::BuiltinFixedArray;
}
};

template <typename ImplClass, typename RetTy = void, typename... Args>
class TypeRefVisitor {
public:
Expand Down
9 changes: 3 additions & 6 deletions include/swift/RemoteInspection/TypeRefBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -929,19 +929,16 @@ class TypeRefBuilder {
}

const TypeRef *createIntegerType(intptr_t value) {
// FIXME: implement
return nullptr;
return IntegerTypeRef::create(*this, value);
}

const TypeRef *createNegativeIntegerType(intptr_t value) {
// FIXME: implement
return nullptr;
return IntegerTypeRef::create(*this, value);
}

const TypeRef *createBuiltinFixedArrayType(const TypeRef *size,
const TypeRef *element) {
// FIXME: implement
return nullptr;
return BuiltinFixedArrayTypeRef::create(*this, size, element);
}

// Construct a bound generic type ref along with the parent type info
Expand Down
2 changes: 2 additions & 0 deletions include/swift/RemoteInspection/TypeRefs.def
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,7 @@ TYPEREF(OpaqueArchetype, TypeRef)
#include "swift/AST/ReferenceStorage.def"
TYPEREF(SILBox, TypeRef)
TYPEREF(SILBoxTypeWithLayout, TypeRef)
TYPEREF(Integer, TypeRef)
TYPEREF(BuiltinFixedArray, TypeRef)

#undef TYPEREF
28 changes: 28 additions & 0 deletions include/swift/Sema/CSFix.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,10 @@ enum class FixKind : uint8_t {
/// sending result, but is passed a function typed parameter without a sending
/// result.
AllowSendingMismatch,

/// Ignore when a 'Slab' literal has mismatched number of elements to the
/// type it's attempting to bind to.
AllowSlabLiteralCountMismatch,
};

class ConstraintFix {
Expand Down Expand Up @@ -3837,6 +3841,30 @@ class IgnoreKeyPathSubscriptIndexMismatch final : public ConstraintFix {
}
};

class AllowSlabLiteralCountMismatch final : public ConstraintFix {
Type lhsCount, rhsCount;

AllowSlabLiteralCountMismatch(ConstraintSystem &cs, Type lhsCount,
Type rhsCount, ConstraintLocator *locator)
: ConstraintFix(cs, FixKind::AllowSlabLiteralCountMismatch, locator),
lhsCount(lhsCount), rhsCount(rhsCount) {}

public:
std::string getName() const override {
return "allow vector literal count mismatch";
}

bool diagnose(const Solution &solution, bool asNote = false) const override;

static AllowSlabLiteralCountMismatch *
create(ConstraintSystem &cs, Type lhsCount, Type rhsCount,
ConstraintLocator *locator);

static bool classof(const ConstraintFix *fix) {
return fix->getKind() == FixKind::AllowSlabLiteralCountMismatch;
}
};

} // end namespace constraints
} // end namespace swift

Expand Down
3 changes: 3 additions & 0 deletions include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ typedef enum swift_layout_kind {
// swift_reflection_infoForTypeRef().
SWIFT_CLASS_INSTANCE,
SWIFT_CLOSURE_CONTEXT,

// A contiguous list of N Ts, typically for Builtin.FixedArray<N, T>.
SWIFT_ARRAY,
} swift_layout_kind_t;

struct swift_childinfo;
Expand Down
1 change: 1 addition & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,7 @@ namespace {
break;
case GenericTypeParamKind::Value:
printField((StringRef)"value", "param_kind");
printRec(decl->getValueType(), "value_type");
break;
}
printAttributes(decl);
Expand Down
32 changes: 26 additions & 6 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ enum class BuiltinThrowsKind : uint8_t {
static FuncDecl *getBuiltinGenericFunction(
Identifier Id, ArrayRef<AnyFunctionType::Param> ArgParamTypes, Type ResType,
GenericParamList *GenericParams, GenericSignature Sig, bool Async,
BuiltinThrowsKind Throws, bool SendingResult) {
BuiltinThrowsKind Throws, Type ThrownError, bool SendingResult) {
assert(GenericParams && "Missing generic parameters");
auto &Context = ResType->getASTContext();

Expand Down Expand Up @@ -471,7 +471,7 @@ static FuncDecl *getBuiltinGenericFunction(
Context, StaticSpellingKind::None, Name,
/*NameLoc=*/SourceLoc(),
Async,
Throws != BuiltinThrowsKind::None, /*thrownType=*/Type(),
Throws != BuiltinThrowsKind::None, ThrownError,
GenericParams, paramList, ResType, DC);

func->setSendingResult(SendingResult);
Expand Down Expand Up @@ -696,6 +696,7 @@ namespace {
Type InterfaceResult;
bool Async = false;
BuiltinThrowsKind Throws = BuiltinThrowsKind::None;
Type ThrownError;
bool SendingResult = false;

// Accumulate params and requirements here, so that we can call
Expand Down Expand Up @@ -740,6 +741,11 @@ namespace {
InterfaceResult = generator.build(*this);
}

template <class G>
void setThrownError(const G &generator) {
ThrownError = generator.build(*this);
}

template <class G>
void addConformanceRequirement(const G &generator, KnownProtocolKind kp) {
addConformanceRequirement(generator, Context.getProtocol(kp));
Expand Down Expand Up @@ -776,7 +782,7 @@ namespace {
/*allowInverses=*/false);
return getBuiltinGenericFunction(name, InterfaceParams, InterfaceResult,
TheGenericParamList, GenericSig, Async,
Throws, SendingResult);
Throws, ThrownError, SendingResult);
}

// Don't use these generator classes directly; call the make{...}
Expand Down Expand Up @@ -2231,17 +2237,31 @@ static ValueDecl *getAddressOfRawLayout(ASTContext &ctx, Identifier id) {
}

static ValueDecl *getEmplace(ASTContext &ctx, Identifier id) {
BuiltinFunctionBuilder builder(ctx, /* genericParamCount */ 1);
BuiltinFunctionBuilder builder(ctx, /* genericParamCount */ 2);

auto T = makeGenericParam();
// <T: ~Copyable, E: Error>(
// _: (Builtin.RawPointer) throws(E) -> ()
// ) throws(E) -> T

auto T = makeGenericParam(0);
builder.addConformanceRequirement(T, KnownProtocolKind::Escapable);

auto E = makeGenericParam(1);
builder.addConformanceRequirement(E, KnownProtocolKind::Error);

auto extInfo = ASTExtInfoBuilder()
.withNoEscape()
.withThrows(/* throws */ true, E.build(builder))
.build();

auto fnParamTy = FunctionType::get(FunctionType::Param(ctx.TheRawPointerType),
ctx.TheEmptyTupleType,
ASTExtInfo().withNoEscape());
extInfo);

builder.addParameter(makeConcrete(fnParamTy), ParamSpecifier::Borrowing);
builder.setResult(T);
builder.setThrows();
builder.setThrownError(E);

return builder.build(id);
}
Expand Down
7 changes: 7 additions & 0 deletions lib/AST/GenericParamList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "swift/AST/GenericParamList.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/Assertions.h"

Expand Down Expand Up @@ -78,6 +79,12 @@ GenericParamList::clone(DeclContext *dc) const {
dc, param->getName(), GenericTypeParamDecl::InvalidDepth,
param->getIndex(), param->getParamKind(), param->getOpaqueTypeRepr());
newParam->setInherited(param->getInherited().getEntries());

// Cache the value type computed from the previous param to the new one.
ctx.evaluator.cacheOutput(
GenericTypeParamDeclGetValueTypeRequest{newParam},
param->getValueType());

params.push_back(newParam);
}

Expand Down
5 changes: 4 additions & 1 deletion lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -808,8 +808,11 @@ CanType CanType::wrapInOptionalTypeImpl(CanType type) {

Type TypeBase::isArrayType() {
if (auto boundStruct = getAs<BoundGenericStructType>()) {
if (boundStruct->getDecl() == getASTContext().getArrayDecl())
if (isArray())
return boundStruct->getGenericArgs()[0];

if (isSlab())
return boundStruct->getGenericArgs()[1];
}
return Type();
}
Expand Down
3 changes: 2 additions & 1 deletion lib/ClangImporter/ImportType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,12 +645,13 @@ namespace {
return Type();

auto size = type->getSize().getZExtValue();

// An array of size N is imported as an N-element tuple which
// takes very long to compile. We chose 4096 as the upper limit because
// we don't want to break arrays of size PATH_MAX.
if (size > 4096)
return Type();

if (size == 1)
return elementType;

Expand Down
Loading