Skip to content

[NO MERGE] implement realloc_ref SIL instruction [INCOMPLETE] #17902

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

Closed
wants to merge 1 commit into from
Closed
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
13 changes: 13 additions & 0 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,19 @@ class SILBuilder {
C.OpenedArchetypes));
}

ReallocRefInst *createReallocRef(SILLocation Loc, SILType ObjectType,
SILValue Val, ArrayRef<SILType> ElementTypes,
ArrayRef<SILValue> ElementCountOperands) {
// ReallocRefInst expand to function calls and can therefore not be
// counted towards the function prologue.
assert(!Loc.isInPrologue() &&
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you an drop the comment. The assert works well enough as docs. Sorry if I was unclear.

"ReallocRefInst can not count towards function prologue since it "
"expands into function calls");
return insert(ReallocRefInst::create(
getSILDebugLocation(Loc), getFunction(), ObjectType, Val, ElementTypes,
ElementCountOperands, C.OpenedArchetypes));
}

AllocRefDynamicInst *createAllocRefDynamic(SILLocation Loc, SILValue operand,
SILType type, bool objc,
ArrayRef<SILType> ElementTypes,
Expand Down
5 changes: 5 additions & 0 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,11 @@ SILCloner<ImplClass>::visitAllocRefInst(AllocRefInst *Inst) {
doPostProcess(Inst, NewInst);
}

template <typename ImplClass>
void SILCloner<ImplClass>::visitReallocRefInst(ReallocRefInst *Inst) {
llvm_unreachable("unimplemented: incomplete realloc_ref implementation");
Copy link
Contributor

Choose a reason for hiding this comment

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

I was thinking about this part of the code this morning and this is really a mid-level infrastructure sort of thing. We should do it in this commit. I would just (again) copy what realloc ref does.

}

template<typename ImplClass>
void
SILCloner<ImplClass>::visitAllocRefDynamicInst(AllocRefDynamicInst *Inst) {
Expand Down
49 changes: 49 additions & 0 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,55 @@ class AllocRefInst final
}
};

/// ReallocRefInst - This represents the reallocation primitive of a reference
/// type. If the reallocation was successfully the reference is returned with
Copy link
Contributor

Choose a reason for hiding this comment

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

was "successful"

/// the altered size. If the reallocation failed the reference is returned at
/// a new address in an allocation with the altered size and the contents are
/// bit-wise copied.
/// This is only useful for tail-allocated arrays and the new size must always
/// be larger than the original size.
class ReallocRefInst final
: public InstructionBaseWithTrailingOperands<
SILInstructionKind::ReallocRefInst,
ReallocRefInst,
AllocRefInstBase, SILType> {
friend AllocRefInstBase;
friend SILBuilder;

ReallocRefInst(SILDebugLocation DebugLoc, SILFunction &F, SILType ObjectType,
SILValue ExistingRef, ArrayRef<SILType> ElementTypes,
ArrayRef<SILValue> AllOperands)
: InstructionBaseWithTrailingOperands(AllOperands, DebugLoc, ObjectType,
false, false, ElementTypes) {
assert(AllOperands.size() >= ElementTypes.size());
std::uninitialized_copy(ElementTypes.begin(), ElementTypes.end(),
getTrailingObjects<SILType>());
}

static ReallocRefInst *create(SILDebugLocation DebugLoc, SILFunction &F,
SILType ObjectType, SILValue ExistingRef,
ArrayRef<SILType> ElementTypes,
ArrayRef<SILValue> ElementCountOperands,
SILOpenedArchetypesState &OpenedArchetypes);

public:
ArrayRef<Operand> getTypeDependentOperands() const {
return getAllOperands().slice(getNumTailTypes());
}

MutableArrayRef<Operand> getTypeDependentOperands() {
return getAllOperands().slice(getNumTailTypes());
}

SILValue getReallocPointer() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Btw, I just made up these names, feel free to use your intuition for better names. The names here that I made up I feel fail the DRY test since realloc is in the class name. Also, generally the way that this sort of thing is implemented is that you define an enum that defines the index and then use that with getOperand(unsigned) to get the right value. See StoreInst which follows that pattern.

llvm_unreachable("Unimplemented! realloc_ref implementation incomplete");
}

SILValue getReallocSize() {
llvm_unreachable("Unimplemented! realloc_ref implementation incomplete");
}
};

/// AllocRefDynamicInst - This represents the primitive allocation of
/// an instance of a reference type whose runtime type is provided by
/// the given metatype value. Aside from the reference count, the
Expand Down
2 changes: 2 additions & 0 deletions include/swift/SIL/SILNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
AllocationInst, None, DoesNotRelease)
SINGLE_VALUE_INST(AllocRefInst, alloc_ref,
AllocationInst, None, DoesNotRelease)
SINGLE_VALUE_INST(ReallocRefInst, realloc_ref,
AllocationInst, None, DoesNotRelease)
SINGLE_VALUE_INST(AllocRefDynamicInst, alloc_ref_dynamic,
AllocationInst, None, DoesNotRelease)
SINGLE_VALUE_INST(AllocValueBufferInst, alloc_value_buffer,
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
const uint16_t VERSION_MINOR = 426; // SIL key path external components with local attempts
const uint16_t VERSION_MINOR = 427; // Last change: add realloc_ref

using DeclIDField = BCFixed<31>;

Expand Down
5 changes: 5 additions & 0 deletions lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,7 @@ class IRGenSILFunction :
llvm::Value *addr);
void visitAllocStackInst(AllocStackInst *i);
void visitAllocRefInst(AllocRefInst *i);
void visitReallocRefInst(ReallocRefInst *i);
void visitAllocRefDynamicInst(AllocRefDynamicInst *i);
void visitAllocBoxInst(AllocBoxInst *i);

Expand Down Expand Up @@ -4095,6 +4096,10 @@ void IRGenSILFunction::visitAllocRefInst(swift::AllocRefInst *i) {
setLoweredExplosion(i, e);
}

void IRGenSILFunction::visitReallocRefInst(swift::ReallocRefInst *i) {
llvm_unreachable("unimplemented: incomplete realloc_ref implementation");
}

void IRGenSILFunction::visitAllocRefDynamicInst(swift::AllocRefDynamicInst *i) {
SmallVector<std::pair<SILType, llvm::Value *>, 4> TailArrays;
buildTailArrays(*this, TailArrays, i);
Expand Down
41 changes: 41 additions & 0 deletions lib/ParseSIL/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3602,6 +3602,47 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
}
break;
}
case SILInstructionKind::ReallocRefInst: {
SmallVector<SILType, 2> ElementTypes;
SmallVector<SILValue, 2> ElementCounts;
while (P.consumeIf(tok::l_square)) {
Identifier Id;
parseSILIdentifier(Id, diag::expected_in_attribute_list);
StringRef Optional = Id.str();
if (Optional == "tail_elems") {
SILType ElemTy;
if (parseSILType(ElemTy) || !P.Tok.isAnyOperator() ||
P.Tok.getText() != "*")
return true;
P.consumeToken();

SILValue ElemCount;
if (parseTypedValueRef(ElemCount, B))
return true;

ElementTypes.push_back(ElemTy);
ElementCounts.push_back(ElemCount);
} else {
return true;
}
P.parseToken(tok::r_square, diag::expected_in_attribute_list);
}
SILValue Metadata;
if (parseTypedValueRef(Val, B) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
return true;

SILType ObjectType;
if (parseSILType(ObjectType))
return true;

if (parseSILDebugLocation(InstLoc, B))
return true;

ResultVal = B.createReallocRef(InstLoc, ObjectType, Val, ElementTypes,
ElementCounts);
break;
}
case SILInstructionKind::AllocRefInst:
case SILInstructionKind::AllocRefDynamicInst: {
bool IsObjC = false;
Expand Down
12 changes: 12 additions & 0 deletions lib/SIL/Linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,18 @@ void SILLinkerVisitor::visitAllocRefInst(AllocRefInst *ARI) {
linkInVTable(D);
}

void SILLinkerVisitor::visitReallocRefInst(ReallocRefInst *RRI) {
if (!isLinkAll())
return;

// Grab the class decl from the alloc ref inst.
ClassDecl *D = RRI->getType().getClassOrBoundGenericClass();
if (!D)
return;

linkInVTable(D);
}

void SILLinkerVisitor::visitMetatypeInst(MetatypeInst *MI) {
if (!isLinkAll())
return;
Expand Down
1 change: 1 addition & 0 deletions lib/SIL/Linker.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class SILLinkerVisitor : public SILInstructionVisitor<SILLinkerVisitor, void> {
void visitInitExistentialAddrInst(InitExistentialAddrInst *IEI);
void visitInitExistentialRefInst(InitExistentialRefInst *IERI);
void visitAllocRefInst(AllocRefInst *ARI);
void visitReallocRefInst(ReallocRefInst *RRI);
void visitMetatypeInst(MetatypeInst *MI);

private:
Expand Down
2 changes: 2 additions & 0 deletions lib/SIL/SILInstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ namespace {
return true;
}

bool visitReallocRefInst(const ReallocRefInst *RHS) { return true; }
Copy link
Contributor

Choose a reason for hiding this comment

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

You were right here. You should copy what alloc_ref tail does. I was wrong.


bool visitAllocRefDynamicInst(const AllocRefDynamicInst *RHS) {
return true;
}
Expand Down
21 changes: 21 additions & 0 deletions lib/SIL/SILInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,27 @@ AllocRefInst *AllocRefInst::create(SILDebugLocation Loc, SILFunction &F,
ElementTypes, AllOperands);
}

ReallocRefInst *
ReallocRefInst::create(SILDebugLocation Loc, SILFunction &F, SILType ObjectType,
SILValue ExistingRef, ArrayRef<SILType> ElementTypes,
ArrayRef<SILValue> ElementCountOperands,
SILOpenedArchetypesState &OpenedArchetypes) {
assert(ElementTypes.size() == ElementCountOperands.size());
SmallVector<SILValue, 8> AllOperands(ElementCountOperands.begin(),
ElementCountOperands.end());
for (SILType ElemType : ElementTypes) {
collectTypeDependentOperands(AllOperands, OpenedArchetypes, F,
ElemType.getASTType());
}
collectTypeDependentOperands(AllOperands, OpenedArchetypes, F,
ObjectType.getASTType());
auto Size = totalSizeToAlloc<swift::Operand, SILType>(AllOperands.size(),
ElementTypes.size());
auto Buffer = F.getModule().allocateInst(Size, alignof(ReallocRefInst));
return ::new (Buffer) ReallocRefInst(Loc, F, ObjectType, ExistingRef,
ElementTypes, AllOperands);
}

AllocRefDynamicInst *
AllocRefDynamicInst::create(SILDebugLocation DebugLoc, SILFunction &F,
SILValue metatypeOperand, SILType ty, bool objc,
Expand Down
11 changes: 11 additions & 0 deletions lib/SIL/SILOwnershipVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,17 @@ OwnershipCompatibilityUseChecker::visitAllocRefInst(AllocRefInst *I) {
UseLifetimeConstraint::MustBeLive};
}

OwnershipUseCheckerResult
OwnershipCompatibilityUseChecker::visitReallocRefInst(ReallocRefInst *I) {
if (getValue() == I->getReallocPointer()) {
return {compatibleWithOwnership(ValueOwnershipKind::Owned),
UseLifetimeConstraint::MustBeInvalidated};
}
assert(getValue() == I->getReallocSize());
return {compatibleWithOwnership(ValueOwnershipKind::Trivial),
UseLifetimeConstraint::MustBeLive};
}

OwnershipUseCheckerResult
OwnershipCompatibilityUseChecker::visitAllocRefDynamicInst(
AllocRefDynamicInst *I) {
Expand Down
5 changes: 5 additions & 0 deletions lib/SIL/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,11 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
*this << ARI->getType();
}

void visitReallocRefInst(ReallocRefInst *RRI) {
printAllocRefInstBase(RRI);
*this << RRI->getType();
}

void visitAllocRefDynamicInst(AllocRefDynamicInst *ARDI) {
printAllocRefInstBase(ARDI);
*this << getIDAndType(ARDI->getMetatypeOperand());
Expand Down
1 change: 1 addition & 0 deletions lib/SIL/ValueOwnershipKindClassifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ CONSTANT_OWNERSHIP_INST(Guaranteed, LoadBorrow)
CONSTANT_OWNERSHIP_INST(Owned, AllocBox)
CONSTANT_OWNERSHIP_INST(Owned, AllocExistentialBox)
CONSTANT_OWNERSHIP_INST(Owned, AllocRef)
CONSTANT_OWNERSHIP_INST(Owned, ReallocRef)
CONSTANT_OWNERSHIP_INST(Owned, AllocRefDynamic)
CONSTANT_OWNERSHIP_INST(Trivial, AllocValueBuffer)
CONSTANT_OWNERSHIP_INST(Owned, CopyBlock)
Expand Down
1 change: 1 addition & 0 deletions lib/SILOptimizer/SILCombiner/SILCombiner.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ class SILCombiner :
SILInstruction *visitIndexAddrInst(IndexAddrInst *IA);
SILInstruction *visitAllocStackInst(AllocStackInst *AS);
SILInstruction *visitAllocRefInst(AllocRefInst *AR);
SILInstruction *visitReallocRefInst(ReallocRefInst *AR);
SILInstruction *visitSwitchEnumAddrInst(SwitchEnumAddrInst *SEAI);
SILInstruction *visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI);
SILInstruction *visitPointerToAddressInst(PointerToAddressInst *PTAI);
Expand Down
4 changes: 4 additions & 0 deletions lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,10 @@ SILInstruction *SILCombiner::visitAllocRefInst(AllocRefInst *AR) {
return nullptr;
}

SILInstruction *SILCombiner::visitReallocRefInst(ReallocRefInst *RRI) {
return nullptr;
}

/// Returns the base address if \p val is an index_addr with constant index.
static SILValue isConstIndexAddr(SILValue val, unsigned &index) {
auto *IA = dyn_cast<IndexAddrInst>(val);
Expand Down
1 change: 1 addition & 0 deletions lib/SILOptimizer/Utils/SILInliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
case SILInstructionKind::AllocBoxInst:
case SILInstructionKind::AllocExistentialBoxInst:
case SILInstructionKind::AllocRefInst:
case SILInstructionKind::ReallocRefInst:
case SILInstructionKind::AllocRefDynamicInst:
case SILInstructionKind::AllocStackInst:
case SILInstructionKind::AllocValueBufferInst:
Expand Down
1 change: 1 addition & 0 deletions lib/Serialization/DeserializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
}
break;
}
case SILInstructionKind::ReallocRefInst:
case SILInstructionKind::AllocRefInst:
case SILInstructionKind::AllocRefDynamicInst: {
assert(RecordKind == SIL_ONE_TYPE_VALUES &&
Expand Down
1 change: 1 addition & 0 deletions lib/Serialization/SerializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
break;
}
case SILInstructionKind::AllocRefInst:
case SILInstructionKind::ReallocRefInst:
case SILInstructionKind::AllocRefDynamicInst: {
const AllocRefInstBase *ARI = cast<AllocRefInstBase>(&SI);
unsigned abbrCode = SILAbbrCodes[SILOneTypeValuesLayout::Code];
Expand Down
13 changes: 13 additions & 0 deletions test/SIL/Parser/basic.sil
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,19 @@ bb0(%0 : $Builtin.Word, %1 : $Builtin.Word):
return %3 : $()
}

// CHECK-LABEL: sil @test_realloc_tail_elems
sil @test_realloc_tail_elems : $@convention(thin) (Builtin.Word, Builtin.Word) -> () {
bb0(%0 : $Builtin.Word, %1 : $Builtin.Word):
// CHECK: alloc_ref [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * %1 : $Builtin.Word] $Class1
%2 = alloc_ref [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * %1 : $Builtin.Word] $Class1
// CHECK: %3 = realloc_ref [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * % %1 : $Builtin.Word] %2, $Class1
%3 = realloc_ref [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * % %1 : $Builtin.Word] %2, $Class1
// CHECK: dealloc_ref %3 : $Class1
dealloc_ref %3 : $Class1
%4 = tuple ()
return %4 : $()
}

// CHECK-LABEL: sil @test_tail_elems_dynamic
sil @test_tail_elems_dynamic : $@convention(thin) (Builtin.Word, Builtin.Word, @thick Class1.Type) -> () {
bb0(%0 : $Builtin.Word, %1 : $Builtin.Word, %2 : $@thick Class1.Type):
Expand Down