@@ -128,9 +128,11 @@ struct FieldInfo;
128
128
struct StructInfo {
129
129
StringRef Name;
130
130
bool IsUnion = false ;
131
+ bool Initializable = true ;
131
132
unsigned Alignment = 0 ;
132
- unsigned Size = 0 ;
133
133
unsigned AlignmentSize = 0 ;
134
+ unsigned NextOffset = 0 ;
135
+ unsigned Size = 0 ;
134
136
std::vector<FieldInfo> Fields;
135
137
StringMap<size_t > FieldsByName;
136
138
@@ -322,7 +324,7 @@ struct StructInitializer {
322
324
323
325
struct FieldInfo {
324
326
// Offset of the field within the containing STRUCT.
325
- size_t Offset = 0 ;
327
+ unsigned Offset = 0 ;
326
328
327
329
// Total size of the field (= LengthOf * Type).
328
330
unsigned SizeOf = 0 ;
@@ -344,11 +346,10 @@ FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT,
344
346
FieldsByName[FieldName.lower ()] = Fields.size ();
345
347
Fields.emplace_back (FT);
346
348
FieldInfo &Field = Fields.back ();
347
- if (IsUnion) {
348
- Field.Offset = 0 ;
349
- } else {
350
- Size = llvm::alignTo (Size, std::min (Alignment, FieldAlignmentSize));
351
- Field.Offset = Size;
349
+ Field.Offset =
350
+ llvm::alignTo (NextOffset, std::min (Alignment, FieldAlignmentSize));
351
+ if (!IsUnion) {
352
+ NextOffset = std::max (NextOffset, Field.Offset );
352
353
}
353
354
AlignmentSize = std::max (AlignmentSize, FieldAlignmentSize);
354
355
return Field;
@@ -669,6 +670,7 @@ class MasmParser : public MCAsmParser {
669
670
DK_REAL8,
670
671
DK_REAL10,
671
672
DK_ALIGN,
673
+ DK_EVEN,
672
674
DK_ORG,
673
675
DK_ENDR,
674
676
DK_EXTERN,
@@ -871,8 +873,11 @@ class MasmParser : public MCAsmParser {
871
873
bool parseDirectiveEquate (StringRef IDVal, StringRef Name,
872
874
DirectiveKind DirKind, SMLoc NameLoc);
873
875
874
- bool parseDirectiveOrg (); // ".org"
876
+ bool parseDirectiveOrg (); // "org"
877
+
878
+ bool emitAlignTo (int64_t Alignment);
875
879
bool parseDirectiveAlign (); // "align"
880
+ bool parseDirectiveEven (); // "even"
876
881
877
882
// ".file", ".line", ".loc", ".stabs"
878
883
bool parseDirectiveFile (SMLoc DirectiveLoc);
@@ -2332,6 +2337,8 @@ bool MasmParser::parseStatement(ParseStatementInfo &Info,
2332
2337
return parseDirectiveNestedEnds ();
2333
2338
case DK_ALIGN:
2334
2339
return parseDirectiveAlign ();
2340
+ case DK_EVEN:
2341
+ return parseDirectiveEven ();
2335
2342
case DK_ORG:
2336
2343
return parseDirectiveOrg ();
2337
2344
case DK_EXTERN:
@@ -3663,10 +3670,11 @@ bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
3663
3670
3664
3671
Field.SizeOf = Field.Type * IntInfo.Values .size ();
3665
3672
Field.LengthOf = IntInfo.Values .size ();
3666
- if (Struct.IsUnion )
3667
- Struct.Size = std::max (Struct.Size , Field.SizeOf );
3668
- else
3669
- Struct.Size += Field.SizeOf ;
3673
+ const unsigned FieldEnd = Field.Offset + Field.SizeOf ;
3674
+ if (!Struct.IsUnion ) {
3675
+ Struct.NextOffset = FieldEnd;
3676
+ }
3677
+ Struct.Size = std::max (Struct.Size , FieldEnd);
3670
3678
return false ;
3671
3679
}
3672
3680
@@ -3869,10 +3877,12 @@ bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics,
3869
3877
Field.Type = RealInfo.AsIntValues .back ().getBitWidth () / 8 ;
3870
3878
Field.LengthOf = RealInfo.AsIntValues .size ();
3871
3879
Field.SizeOf = Field.Type * Field.LengthOf ;
3872
- if (Struct.IsUnion )
3873
- Struct.Size = std::max (Struct.Size , Field.SizeOf );
3874
- else
3875
- Struct.Size += Field.SizeOf ;
3880
+
3881
+ const unsigned FieldEnd = Field.Offset + Field.SizeOf ;
3882
+ if (!Struct.IsUnion ) {
3883
+ Struct.NextOffset = FieldEnd;
3884
+ }
3885
+ Struct.Size = std::max (Struct.Size , FieldEnd);
3876
3886
return false ;
3877
3887
}
3878
3888
@@ -4281,14 +4291,16 @@ bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
4281
4291
const StructFieldInfo &Contents,
4282
4292
const StructFieldInfo &Initializer) {
4283
4293
for (const auto &Init : Initializer.Initializers ) {
4284
- emitStructInitializer (Contents.Structure , Init);
4294
+ if (emitStructInitializer (Contents.Structure , Init))
4295
+ return true ;
4285
4296
}
4286
4297
// Default-initialize all remaining values.
4287
4298
for (auto It =
4288
4299
Contents.Initializers .begin () + Initializer.Initializers .size ();
4289
4300
It != Contents.Initializers .end (); ++It) {
4290
4301
const auto &Init = *It;
4291
- emitStructInitializer (Contents.Structure , Init);
4302
+ if (emitStructInitializer (Contents.Structure , Init))
4303
+ return true ;
4292
4304
}
4293
4305
return false ;
4294
4306
}
@@ -4311,6 +4323,10 @@ bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
4311
4323
4312
4324
bool MasmParser::emitStructInitializer (const StructInfo &Structure,
4313
4325
const StructInitializer &Initializer) {
4326
+ if (!Structure.Initializable )
4327
+ return Error (getLexer ().getLoc (),
4328
+ " cannot initialize a value of type '" + Structure.Name +
4329
+ " '; 'org' was used in the type's declaration" );
4314
4330
size_t Index = 0 , Offset = 0 ;
4315
4331
for (const auto &Init : Initializer.FieldInitializers ) {
4316
4332
const auto &Field = Structure.Fields [Index++];
@@ -4367,10 +4383,12 @@ bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
4367
4383
4368
4384
Field.LengthOf = StructInfo.Initializers .size ();
4369
4385
Field.SizeOf = Field.Type * Field.LengthOf ;
4370
- if (OwningStruct.IsUnion )
4371
- OwningStruct.Size = std::max (OwningStruct.Size , Field.SizeOf );
4372
- else
4373
- OwningStruct.Size += Field.SizeOf ;
4386
+
4387
+ const unsigned FieldEnd = Field.Offset + Field.SizeOf ;
4388
+ if (!OwningStruct.IsUnion ) {
4389
+ OwningStruct.NextOffset = FieldEnd;
4390
+ }
4391
+ OwningStruct.Size = std::max (OwningStruct.Size , FieldEnd);
4374
4392
4375
4393
return false ;
4376
4394
}
@@ -4520,6 +4538,8 @@ bool MasmParser::parseDirectiveNestedEnds() {
4520
4538
4521
4539
StructInfo &ParentStruct = StructInProgress.back ();
4522
4540
if (Structure.Name .empty ()) {
4541
+ // Anonymous substructures' fields are addressed as if they belong to the
4542
+ // parent structure - so we transfer them to the parent here.
4523
4543
const size_t OldFields = ParentStruct.Fields .size ();
4524
4544
ParentStruct.Fields .insert (
4525
4545
ParentStruct.Fields .end (),
@@ -4529,17 +4549,28 @@ bool MasmParser::parseDirectiveNestedEnds() {
4529
4549
ParentStruct.FieldsByName [FieldByName.getKey ()] =
4530
4550
FieldByName.getValue () + OldFields;
4531
4551
}
4532
- if (!ParentStruct.IsUnion ) {
4552
+
4553
+ unsigned FirstFieldOffset = 0 ;
4554
+ if (!Structure.Fields .empty () && !ParentStruct.IsUnion ) {
4555
+ FirstFieldOffset = llvm::alignTo (
4556
+ ParentStruct.NextOffset ,
4557
+ std::min (ParentStruct.Alignment , Structure.AlignmentSize ));
4558
+ }
4559
+
4560
+ if (ParentStruct.IsUnion ) {
4561
+ ParentStruct.Size = std::max (ParentStruct.Size , Structure.Size );
4562
+ } else {
4533
4563
for (auto FieldIter = ParentStruct.Fields .begin () + OldFields;
4534
4564
FieldIter != ParentStruct.Fields .end (); ++FieldIter) {
4535
- FieldIter->Offset += ParentStruct. Size ;
4565
+ FieldIter->Offset += FirstFieldOffset ;
4536
4566
}
4537
- }
4538
4567
4539
- if (ParentStruct.IsUnion )
4540
- ParentStruct.Size = std::max (ParentStruct.Size , Structure.Size );
4541
- else
4542
- ParentStruct.Size += Structure.Size ;
4568
+ const unsigned StructureEnd = FirstFieldOffset + Structure.Size ;
4569
+ if (!ParentStruct.IsUnion ) {
4570
+ ParentStruct.NextOffset = StructureEnd;
4571
+ }
4572
+ ParentStruct.Size = std::max (ParentStruct.Size , StructureEnd);
4573
+ }
4543
4574
} else {
4544
4575
FieldInfo &Field = ParentStruct.addField (Structure.Name , FT_STRUCT,
4545
4576
Structure.AlignmentSize );
@@ -4548,10 +4579,11 @@ bool MasmParser::parseDirectiveNestedEnds() {
4548
4579
Field.LengthOf = 1 ;
4549
4580
Field.SizeOf = Structure.Size ;
4550
4581
4551
- if (ParentStruct.IsUnion )
4552
- ParentStruct.Size = std::max (ParentStruct.Size , Field.SizeOf );
4553
- else
4554
- ParentStruct.Size += Field.SizeOf ;
4582
+ const unsigned StructureEnd = Field.Offset + Field.SizeOf ;
4583
+ if (!ParentStruct.IsUnion ) {
4584
+ ParentStruct.NextOffset = StructureEnd;
4585
+ }
4586
+ ParentStruct.Size = std::max (ParentStruct.Size , StructureEnd);
4555
4587
4556
4588
StructInfo.Structure = Structure;
4557
4589
StructInfo.Initializers .emplace_back ();
@@ -4565,22 +4597,66 @@ bool MasmParser::parseDirectiveNestedEnds() {
4565
4597
}
4566
4598
4567
4599
// / parseDirectiveOrg
4568
- // / ::= . org expression [ , expression ]
4600
+ // / ::= org expression
4569
4601
bool MasmParser::parseDirectiveOrg () {
4570
4602
const MCExpr *Offset;
4571
4603
SMLoc OffsetLoc = Lexer.getLoc ();
4572
4604
if (checkForValidSection () || parseExpression (Offset))
4573
4605
return true ;
4574
-
4575
- // Parse optional fill expression.
4576
- int64_t FillExpr = 0 ;
4577
- if (parseOptionalToken (AsmToken::Comma))
4578
- if (parseAbsoluteExpression (FillExpr))
4579
- return addErrorSuffix (" in '.org' directive" );
4580
4606
if (parseToken (AsmToken::EndOfStatement))
4581
- return addErrorSuffix (" in '.org' directive" );
4607
+ return addErrorSuffix (" in 'org' directive" );
4608
+
4609
+ if (StructInProgress.empty ()) {
4610
+ // Not in a struct; change the offset for the next instruction or data
4611
+ if (checkForValidSection ())
4612
+ return addErrorSuffix (" in 'org' directive" );
4613
+
4614
+ getStreamer ().emitValueToOffset (Offset, 0 , OffsetLoc);
4615
+ } else {
4616
+ // Offset the next field of this struct
4617
+ StructInfo &Structure = StructInProgress.back ();
4618
+ int64_t OffsetRes;
4619
+ if (!Offset->evaluateAsAbsolute (OffsetRes, getStreamer ().getAssemblerPtr ()))
4620
+ return Error (OffsetLoc,
4621
+ " expected absolute expression in 'org' directive" );
4622
+ if (OffsetRes < 0 )
4623
+ return Error (
4624
+ OffsetLoc,
4625
+ " expected non-negative value in struct's 'org' directive; was " +
4626
+ std::to_string (OffsetRes));
4627
+ Structure.NextOffset = static_cast <unsigned >(OffsetRes);
4628
+
4629
+ // ORG-affected structures cannot be initialized
4630
+ Structure.Initializable = false ;
4631
+ }
4632
+
4633
+ return false ;
4634
+ }
4635
+
4636
+ bool MasmParser::emitAlignTo (int64_t Alignment) {
4637
+ if (StructInProgress.empty ()) {
4638
+ // Not in a struct; align the next instruction or data
4639
+ if (checkForValidSection ())
4640
+ return true ;
4641
+
4642
+ // Check whether we should use optimal code alignment for this align
4643
+ // directive.
4644
+ const MCSection *Section = getStreamer ().getCurrentSectionOnly ();
4645
+ assert (Section && " must have section to emit alignment" );
4646
+ if (Section->UseCodeAlign ()) {
4647
+ getStreamer ().emitCodeAlignment (Alignment, /* MaxBytesToEmit=*/ 0 );
4648
+ } else {
4649
+ // FIXME: Target specific behavior about how the "extra" bytes are filled.
4650
+ getStreamer ().emitValueToAlignment (Alignment, /* Value=*/ 0 ,
4651
+ /* ValueSize=*/ 1 ,
4652
+ /* MaxBytesToEmit=*/ 0 );
4653
+ }
4654
+ } else {
4655
+ // Align the next field of this struct
4656
+ StructInfo &Structure = StructInProgress.back ();
4657
+ Structure.NextOffset = llvm::alignTo (Structure.NextOffset , Alignment);
4658
+ }
4582
4659
4583
- getStreamer ().emitValueToOffset (Offset, FillExpr, OffsetLoc);
4584
4660
return false ;
4585
4661
}
4586
4662
@@ -4590,8 +4666,6 @@ bool MasmParser::parseDirectiveAlign() {
4590
4666
SMLoc AlignmentLoc = getLexer ().getLoc ();
4591
4667
int64_t Alignment;
4592
4668
4593
- if (checkForValidSection ())
4594
- return addErrorSuffix (" in align directive" );
4595
4669
// Ignore empty 'align' directives.
4596
4670
if (getTok ().is (AsmToken::EndOfStatement)) {
4597
4671
return Warning (AlignmentLoc,
@@ -4602,31 +4676,32 @@ bool MasmParser::parseDirectiveAlign() {
4602
4676
parseToken (AsmToken::EndOfStatement))
4603
4677
return addErrorSuffix (" in align directive" );
4604
4678
4605
- // Always emit an alignment here even if we thrown an error.
4679
+ // Always emit an alignment here even if we throw an error.
4606
4680
bool ReturnVal = false ;
4607
4681
4608
- // Reject alignments that aren't either a power of two or zero, for gas
4682
+ // Reject alignments that aren't either a power of two or zero, for ML.exe
4609
4683
// compatibility. Alignment of zero is silently rounded up to one.
4610
4684
if (Alignment == 0 )
4611
4685
Alignment = 1 ;
4612
4686
if (!isPowerOf2_64 (Alignment))
4613
- ReturnVal |= Error (AlignmentLoc, " alignment must be a power of 2" );
4614
-
4615
- // Check whether we should use optimal code alignment for this align
4616
- // directive.
4617
- const MCSection *Section = getStreamer ().getCurrentSectionOnly ();
4618
- assert (Section && " must have section to emit alignment" );
4619
- if (Section->UseCodeAlign ()) {
4620
- getStreamer ().emitCodeAlignment (Alignment, /* MaxBytesToEmit=*/ 0 );
4621
- } else {
4622
- // FIXME: Target specific behavior about how the "extra" bytes are filled.
4623
- getStreamer ().emitValueToAlignment (Alignment, /* Value=*/ 0 , /* ValueSize=*/ 1 ,
4624
- /* MaxBytesToEmit=*/ 0 );
4625
- }
4687
+ ReturnVal |= Error (AlignmentLoc, " alignment must be a power of 2; was " +
4688
+ std::to_string (Alignment));
4689
+
4690
+ if (emitAlignTo (Alignment))
4691
+ ReturnVal |= addErrorSuffix (" in align directive" );
4626
4692
4627
4693
return ReturnVal;
4628
4694
}
4629
4695
4696
+ // / parseDirectiveEven
4697
+ // / ::= even
4698
+ bool MasmParser::parseDirectiveEven () {
4699
+ if (parseToken (AsmToken::EndOfStatement) || emitAlignTo (2 ))
4700
+ return addErrorSuffix (" in even directive" );
4701
+
4702
+ return false ;
4703
+ }
4704
+
4630
4705
// / parseDirectiveFile
4631
4706
// / ::= .file filename
4632
4707
// / ::= .file number [directory] filename [md5 checksum] [source source-text]
@@ -6520,7 +6595,8 @@ void MasmParser::initializeDirectiveKindMap() {
6520
6595
DirectiveKindMap[" real8" ] = DK_REAL8;
6521
6596
DirectiveKindMap[" real10" ] = DK_REAL10;
6522
6597
DirectiveKindMap[" align" ] = DK_ALIGN;
6523
- // DirectiveKindMap[".org"] = DK_ORG;
6598
+ DirectiveKindMap[" even" ] = DK_EVEN;
6599
+ DirectiveKindMap[" org" ] = DK_ORG;
6524
6600
DirectiveKindMap[" extern" ] = DK_EXTERN;
6525
6601
DirectiveKindMap[" public" ] = DK_PUBLIC;
6526
6602
// DirectiveKindMap[".comm"] = DK_COMM;
0 commit comments