Skip to content

Commit 155def2

Browse files
authored
Merge pull request swiftlang#39272 from atrick/unaligned-loadstore
2 parents 8cd8ca0 + 4828285 commit 155def2

File tree

15 files changed

+263
-103
lines changed

15 files changed

+263
-103
lines changed

docs/SIL.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6194,7 +6194,8 @@ pointer_to_address
61946194
``````````````````
61956195
::
61966196

6197-
sil-instruction ::= 'pointer_to_address' sil-operand 'to' ('[' 'strict' ']')? sil-type
6197+
sil-instruction ::= 'pointer_to_address' sil-operand 'to' ('[' 'strict' ']')? ('[' 'invariant' ']')? ('[' 'alignment' '=' alignment ']')? sil-type
6198+
alignment ::= [0-9]+
61986199

61996200
%1 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*T
62006201
// %1 will be of type $*T
@@ -6214,6 +6215,12 @@ type. A memory access from an address that is not strict cannot have
62146215
its address substituted with a strict address, even if other nearby
62156216
memory accesses at the same location are strict.
62166217

6218+
The ``invariant`` flag is set if loading from the returned address
6219+
always produces the same value.
6220+
6221+
The ``alignment`` integer value specifies the byte alignment of the
6222+
address. ``alignment=0`` is the default, indicating the natural
6223+
alignment of ``T``.
62176224

62186225
unchecked_ref_cast
62196226
``````````````````

include/swift/SIL/SILBuilder.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,12 +1064,12 @@ class SILBuilder {
10641064
getSILDebugLocation(Loc), Op, Ty));
10651065
}
10661066

1067-
PointerToAddressInst *createPointerToAddress(SILLocation Loc, SILValue Op,
1068-
SILType Ty,
1069-
bool isStrict,
1070-
bool isInvariant = false){
1067+
PointerToAddressInst *
1068+
createPointerToAddress(SILLocation Loc, SILValue Op, SILType Ty,
1069+
bool isStrict, bool isInvariant = false,
1070+
llvm::MaybeAlign alignment = llvm::MaybeAlign()) {
10711071
return insert(new (getModule()) PointerToAddressInst(
1072-
getSILDebugLocation(Loc), Op, Ty, isStrict, isInvariant));
1072+
getSILDebugLocation(Loc), Op, Ty, isStrict, isInvariant, alignment));
10731073
}
10741074

10751075
UncheckedRefCastInst *createUncheckedRefCast(SILLocation Loc, SILValue Op,

include/swift/SIL/SILInstruction.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5127,10 +5127,15 @@ class PointerToAddressInst
51275127
friend SILBuilder;
51285128

51295129
PointerToAddressInst(SILDebugLocation DebugLoc, SILValue Operand, SILType Ty,
5130-
bool IsStrict, bool IsInvariant)
5131-
: UnaryInstructionBase(DebugLoc, Operand, Ty) {
5130+
bool IsStrict, bool IsInvariant,
5131+
llvm::MaybeAlign Alignment)
5132+
: UnaryInstructionBase(DebugLoc, Operand, Ty) {
51325133
SILNode::Bits.PointerToAddressInst.IsStrict = IsStrict;
51335134
SILNode::Bits.PointerToAddressInst.IsInvariant = IsInvariant;
5135+
unsigned encodedAlignment = llvm::encode(Alignment);
5136+
SILNode::Bits.PointerToAddressInst.Alignment = encodedAlignment;
5137+
assert(SILNode::Bits.PointerToAddressInst.Alignment == encodedAlignment
5138+
&& "pointer_to_address alignment overflow");
51345139
}
51355140

51365141
public:
@@ -5146,6 +5151,13 @@ class PointerToAddressInst
51465151
bool isInvariant() const {
51475152
return SILNode::Bits.PointerToAddressInst.IsInvariant;
51485153
}
5154+
5155+
/// The byte alignment of the address. Since the alignment of types isn't
5156+
/// known until IRGen (TypeInfo::getBestKnownAlignment), in SIL an unknown
5157+
/// alignment indicates the natural in-memory alignment of the element type.
5158+
llvm::MaybeAlign alignment() const {
5159+
return llvm::decodeMaybeAlign(SILNode::Bits.PointerToAddressInst.Alignment);
5160+
}
51495161
};
51505162

51515163
/// Convert a heap object reference to a different type without any runtime

include/swift/SIL/SILNode.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -368,10 +368,8 @@ class alignas(8) SILNode :
368368
UIWTDOB_BITFIELD_EMPTY(ObjCMethodInst, MethodInst);
369369

370370
SWIFT_INLINE_BITFIELD_EMPTY(ConversionInst, SingleValueInstruction);
371-
SWIFT_INLINE_BITFIELD(PointerToAddressInst, ConversionInst, 1+1,
372-
IsStrict : 1,
373-
IsInvariant : 1
374-
);
371+
SWIFT_INLINE_BITFIELD(PointerToAddressInst, ConversionInst, 8 + 1 + 1,
372+
Alignment : 8, IsStrict : 1, IsInvariant : 1);
375373

376374
UIWTDOB_BITFIELD(ConvertFunctionInst, ConversionInst, 1,
377375
WithoutActuallyEscaping : 1);

lib/IRGen/IRGenSIL.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5632,9 +5632,11 @@ void IRGenSILFunction::visitPointerToAddressInst(swift::PointerToAddressInst *i)
56325632

56335633
llvm::Type *destType = ti.getStorageType()->getPointerTo();
56345634
ptrValue = Builder.CreateBitCast(ptrValue, destType);
5635-
5636-
setLoweredAddress(i,
5637-
ti.getAddressForPointer(ptrValue));
5635+
5636+
if (i->alignment())
5637+
setLoweredAddress(i, Address(ptrValue, Alignment(i->alignment()->value())));
5638+
else
5639+
setLoweredAddress(i, ti.getAddressForPointer(ptrValue));
56385640
}
56395641

56405642
static void emitPointerCastInst(IRGenSILFunction &IGF,

lib/SIL/IR/SILPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,6 +1751,8 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
17511751
*this << "[strict] ";
17521752
if (CI->isInvariant())
17531753
*this << "[invariant] ";
1754+
if (CI->alignment())
1755+
*this << "[align=" << CI->alignment()->value() << "] ";
17541756
*this << CI->getType();
17551757
}
17561758
void visitUncheckedRefCastInst(UncheckedRefCastInst *CI) {

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -802,15 +802,35 @@ static SILLinkage resolveSILLinkage(Optional<SILLinkage> linkage,
802802
}
803803
}
804804

805-
static bool parseSILOptional(StringRef &Result, SourceLoc &Loc, SILParser &SP) {
806-
if (SP.P.consumeIf(tok::l_square)) {
807-
Identifier Id;
808-
SP.parseSILIdentifier(Id, Loc, diag::expected_in_attribute_list);
809-
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
810-
Result = Id.str();
805+
// Returns false if no optional exists. Returns true on both success and
806+
// failure. On success, the Result string is nonempty. If the optional is
807+
// assigned to an integer value, \p value contains the parsed value. Otherwise,
808+
// value is set to the maximum uint64_t.
809+
static bool parseSILOptional(StringRef &Result, uint64_t &value, SourceLoc &Loc,
810+
SILParser &SP) {
811+
if (!SP.P.consumeIf(tok::l_square))
812+
return false;
813+
814+
value = ~uint64_t(0);
815+
816+
Identifier Id;
817+
if (SP.parseSILIdentifier(Id, Loc, diag::expected_in_attribute_list))
811818
return true;
819+
820+
if (SP.P.consumeIf(tok::equal)) {
821+
if (SP.parseInteger(value, diag::expected_in_attribute_list))
822+
return true;
812823
}
813-
return false;
824+
if (SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list))
825+
return true;
826+
827+
Result = Id.str();
828+
return true;
829+
}
830+
831+
static bool parseSILOptional(StringRef &Result, SourceLoc &Loc, SILParser &SP) {
832+
uint64_t value;
833+
return parseSILOptional(Result, value, Loc, SP);
814834
}
815835

816836
static bool parseSILOptional(StringRef &Result, SILParser &SP) {
@@ -3603,21 +3623,35 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
36033623
parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
36043624
"to"))
36053625
return true;
3606-
if (parseSILOptional(attr, *this) && attr.empty())
3607-
return true;
3626+
3627+
bool isStrict = false;
3628+
bool isInvariant = false;
3629+
llvm::MaybeAlign alignment;
3630+
uint64_t parsedValue = 0;
3631+
while (parseSILOptional(attr, parsedValue, ToLoc, *this)) {
3632+
if (attr.empty())
3633+
return true;
3634+
3635+
if (attr.equals("strict"))
3636+
isStrict = true;
3637+
3638+
if (attr.equals("invariant"))
3639+
isInvariant = true;
3640+
3641+
if (attr.equals("align"))
3642+
alignment = llvm::Align(parsedValue);
3643+
}
3644+
36083645
if (parseSILType(Ty) || parseSILDebugLocation(InstLoc, B))
36093646
return true;
36103647

3611-
bool isStrict = attr.equals("strict");
3612-
bool isInvariant = attr.equals("invariant");
3613-
36143648
if (ToToken.str() != "to") {
36153649
P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
36163650
return true;
36173651
}
36183652

3619-
ResultVal =
3620-
B.createPointerToAddress(InstLoc, Val, Ty, isStrict, isInvariant);
3653+
ResultVal = B.createPointerToAddress(InstLoc, Val, Ty, isStrict,
3654+
isInvariant, alignment);
36213655
break;
36223656
}
36233657
case SILInstructionKind::RefToBridgeObjectInst: {

lib/Serialization/DeserializeSIL.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,6 +1104,12 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
11041104
TyID2, TyCategory2,
11051105
ValID);
11061106
break;
1107+
case SIL_ONE_TYPE_ONE_OPERAND_EXTRA_ATTR:
1108+
SILOneTypeOneOperandExtraAttributeLayout::readRecord(scratch, RawOpCode,
1109+
Attr, TyID, TyCategory,
1110+
TyID2, TyCategory2,
1111+
ValID);
1112+
break;
11071113
case SIL_INIT_EXISTENTIAL:
11081114
SILInitExistentialLayout::readRecord(scratch, RawOpCode,
11091115
TyID, TyCategory,
@@ -1358,16 +1364,17 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
13581364
break;
13591365
}
13601366
case SILInstructionKind::PointerToAddressInst: {
1361-
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
1367+
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND_EXTRA_ATTR &&
13621368
"Layout should be OneTypeOneOperand.");
1363-
bool isStrict = Attr & 0x01;
1364-
bool isInvariant = Attr & 0x02;
1369+
auto alignment = llvm::decodeMaybeAlign(Attr & 0xFF);
1370+
bool isStrict = Attr & 0x100;
1371+
bool isInvariant = Attr & 0x200;
13651372
ResultInst = Builder.createPointerToAddress(
13661373
Loc,
13671374
getLocalValue(ValID, getSILType(MF->getType(TyID2),
13681375
(SILValueCategory)TyCategory2, Fn)),
13691376
getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn),
1370-
isStrict, isInvariant);
1377+
isStrict, isInvariant, alignment);
13711378
break;
13721379
}
13731380
case SILInstructionKind::DeallocExistentialBoxInst: {

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5656
/// describe what change you made. The content of this comment isn't important;
5757
/// it just ensures a conflict if two people change the module format.
5858
/// Don't worry about adhering to the 80-column limit for this line.
59-
const uint16_t SWIFTMODULE_VERSION_MINOR = 627; // move_value inst
59+
const uint16_t SWIFTMODULE_VERSION_MINOR = 628; // unaligned pointer
6060

6161
/// A standard hash seed used for all string hashes in a serialized module.
6262
///

lib/Serialization/SILFormat.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ namespace sil_block {
149149
SIL_SPECIALIZE_ATTR,
150150
SIL_PROPERTY,
151151
SIL_ONE_OPERAND_EXTRA_ATTR,
152+
SIL_ONE_TYPE_ONE_OPERAND_EXTRA_ATTR,
152153
SIL_TWO_OPERANDS_EXTRA_ATTR,
153154
SIL_INST_DIFFERENTIABLE_FUNCTION,
154155
SIL_INST_LINEAR_FUNCTION,
@@ -333,7 +334,7 @@ namespace sil_block {
333334
using SILOneTypeOneOperandLayout = BCRecordLayout<
334335
SIL_ONE_TYPE_ONE_OPERAND,
335336
SILInstOpCodeField,
336-
BCFixed<2>, // Optional attributes
337+
BCFixed<1>, // Optional attribute
337338
TypeIDField,
338339
SILTypeCategoryField,
339340
TypeIDField,
@@ -419,6 +420,13 @@ namespace sil_block {
419420
TypeIDField, SILTypeCategoryField, ValueIDField
420421
>;
421422

423+
// SIL instructions with one type, one typed valueref, and extra bits.
424+
using SILOneTypeOneOperandExtraAttributeLayout =
425+
BCRecordLayout<SIL_ONE_TYPE_ONE_OPERAND_EXTRA_ATTR, SILInstOpCodeField,
426+
BCFixed<10>, // Optional attributes
427+
TypeIDField, SILTypeCategoryField, TypeIDField,
428+
SILTypeCategoryField, ValueIDField>;
429+
422430
// SIL instructions with two typed values.
423431
using SILTwoOperandsLayout = BCRecordLayout<
424432
SIL_TWO_OPERANDS,

0 commit comments

Comments
 (0)