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
1 change: 1 addition & 0 deletions lib/IRGen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_swift_library(swiftIRGen STATIC
AllocStackHoisting.cpp
ClassLayout.cpp
DebugTypeInfo.cpp
EnumPayload.cpp
ExtraInhabitants.cpp
Expand Down
56 changes: 56 additions & 0 deletions lib/IRGen/ClassLayout.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//===--- ClassLayout.cpp - Layout of class instances ---------------------===//
//
// 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 implements algorithms for laying out class instances.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/ASTContext.h"

#include "IRGenFunction.h"
#include "IRGenModule.h"
#include "ClassLayout.h"
#include "TypeInfo.h"

using namespace swift;
using namespace irgen;

ClassLayout::ClassLayout(const StructLayoutBuilder &builder,
bool isFixedSize,
bool metadataRequiresDynamicInitialization,
llvm::Type *classTy,
ArrayRef<VarDecl *> allStoredProps,
ArrayRef<FieldAccess> allFieldAccesses,
ArrayRef<ElementLayout> allElements)
: MinimumAlign(builder.getAlignment()),
MinimumSize(builder.getSize()),
IsFixedLayout(builder.isFixedLayout()),
IsFixedSize(isFixedSize),
MetadataRequiresDynamicInitialization(metadataRequiresDynamicInitialization),
Ty(classTy),
AllStoredProperties(allStoredProps),
AllFieldAccesses(allFieldAccesses),
AllElements(allElements) { }

Size ClassLayout::getInstanceStart() const {
if (AllElements.empty())
return getSize();

auto element = AllElements[0];
if (element.getKind() == ElementLayout::Kind::Fixed ||
element.getKind() == ElementLayout::Kind::Empty) {
// FIXME: assumes layout is always sequential!
return element.getByteOffset();
}

return Size(0);
}
116 changes: 116 additions & 0 deletions lib/IRGen/ClassLayout.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//===--- ClassLayout.h - Class instance layout ------------------*- 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 some routines that are useful for calculating class
// instance layout.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_IRGEN_CLASSLAYOUT_H
#define SWIFT_IRGEN_CLASSLAYOUT_H

#include "llvm/ADT/ArrayRef.h"
#include "IRGen.h"
#include "StructLayout.h"

namespace swift {
namespace irgen {

/// Different policies for accessing a physical field.
enum class FieldAccess : uint8_t {
/// Instance variable offsets are constant.
ConstantDirect,

/// Instance variable offsets must be loaded from "direct offset"
/// global variables.
NonConstantDirect,

/// Instance variable offsets are kept in fields in metadata, but
/// the offsets of those fields within the metadata are constant.
ConstantIndirect
};

class ClassLayout {
/// The statically-known minimum bound on the alignment.
Alignment MinimumAlign;

/// The statically-known minimum bound on the size.
Size MinimumSize;

/// Whether this layout is fixed in size. If so, the size and
/// alignment are exact.
bool IsFixedLayout;

/// Do instances of this class have a size and layout known at compile time?
///
/// Note: This is a stronger condition than having a fixed layout. The latter
/// is true even when the class requires sliding ivars by the Objective-C
/// runtime.
bool IsFixedSize;

/// Does the class metadata require dynamic initialization?
bool MetadataRequiresDynamicInitialization;

/// The LLVM type for instances of this class.
llvm::Type *Ty;

/// Lazily-initialized array of all fragile stored properties directly defined
/// in the class itself.
ArrayRef<VarDecl *> AllStoredProperties;

/// Lazily-initialized array of all field access methods.
ArrayRef<FieldAccess> AllFieldAccesses;

/// Fixed offsets of fields, if known (does not take Objective-C sliding into
/// account).
ArrayRef<ElementLayout> AllElements;

public:
ClassLayout(const StructLayoutBuilder &builder,
bool isFixedSize,
bool metadataRequiresDynamicInitialization,
llvm::Type *classTy,
ArrayRef<VarDecl *> allStoredProps,
ArrayRef<FieldAccess> allFieldAccesses,
ArrayRef<ElementLayout> allElements);

Size getInstanceStart() const;

llvm::Type *getType() const { return Ty; }
Size getSize() const { return MinimumSize; }
Alignment getAlignment() const { return MinimumAlign; }
Size getAlignMask() const { return getAlignment().asSize() - Size(1); }

bool isFixedLayout() const { return IsFixedLayout; }

bool isFixedSize() const { return IsFixedSize; }

bool doesMetadataRequireDynamicInitialization() const {
return MetadataRequiresDynamicInitialization;
}

std::pair<FieldAccess, ElementLayout>
getFieldAccessAndElement(VarDecl *field) const {
// FIXME: This is algorithmically terrible.
auto found = std::find(AllStoredProperties.begin(),
AllStoredProperties.end(), field);
assert(found != AllStoredProperties.end() && "didn't find field in type?!");
unsigned index = found - AllStoredProperties.begin();

return std::make_pair(AllFieldAccesses[index], AllElements[index]);
}
};

} // end namespace irgen
} // end namespace swift

#endif
Loading