Skip to content

Commit 50daa23

Browse files
authored
[DataLayout] Refactor parsing of i/f/v/a specifications (#104699)
Split off of #104545 to reduce patch size.
1 parent b05c554 commit 50daa23

File tree

6 files changed

+262
-151
lines changed

6 files changed

+262
-151
lines changed

llvm/include/llvm/IR/DataLayout.h

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,6 @@ class DataLayout {
115115
// FIXME: `unsigned char` truncates the value parsed by `parseSpecifier`.
116116
SmallVector<unsigned char, 8> LegalIntWidths;
117117

118-
/// Type specifier used by some internal functions.
119-
enum class TypeSpecifier {
120-
Integer = 'i',
121-
Float = 'f',
122-
Vector = 'v',
123-
Aggregate = 'a'
124-
};
125-
126118
/// Primitive type specifications. Sorted and uniqued by type bit width.
127119
SmallVector<PrimitiveSpec, 6> IntSpecs;
128120
SmallVector<PrimitiveSpec, 4> FloatSpecs;
@@ -145,10 +137,9 @@ class DataLayout {
145137
/// well-defined bitwise representation.
146138
SmallVector<unsigned, 8> NonIntegralAddressSpaces;
147139

148-
/// Attempts to set the specification for the given type.
149-
/// Returns an error description on failure.
150-
Error setPrimitiveSpec(TypeSpecifier Specifier, uint32_t BitWidth,
151-
Align ABIAlign, Align PrefAlign);
140+
/// Sets or updates the specification for the given primitive type.
141+
void setPrimitiveSpec(char Specifier, uint32_t BitWidth, Align ABIAlign,
142+
Align PrefAlign);
152143

153144
/// Searches for a pointer specification that matches the given address space.
154145
/// Returns the default address space specification if not found.
@@ -164,7 +155,13 @@ class DataLayout {
164155
/// Internal helper method that returns requested alignment for type.
165156
Align getAlignment(Type *Ty, bool abi_or_pref) const;
166157

167-
/// Attempts to parse a pointer specification ('p').
158+
/// Attempts to parse primitive specification ('i', 'f', or 'v').
159+
Error parsePrimitiveSpec(StringRef Spec);
160+
161+
/// Attempts to parse aggregate specification ('a').
162+
Error parseAggregateSpec(StringRef Spec);
163+
164+
/// Attempts to parse pointer specification ('p').
168165
Error parsePointerSpec(StringRef Spec);
169166

170167
/// Attempts to parse a single specification.

llvm/lib/IR/DataLayout.cpp

Lines changed: 89 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,82 @@ static Error getAddrSpace(StringRef R, unsigned &AddrSpace) {
376376
return Error::success();
377377
}
378378

379+
Error DataLayout::parsePrimitiveSpec(StringRef Spec) {
380+
// [ifv]<size>:<abi>[:<pref>]
381+
SmallVector<StringRef, 3> Components;
382+
char Specifier = Spec.front();
383+
assert(Specifier == 'i' || Specifier == 'f' || Specifier == 'v');
384+
Spec.drop_front().split(Components, ':');
385+
386+
if (Components.size() < 2 || Components.size() > 3)
387+
return createSpecFormatError(Twine(Specifier) + "<size>:<abi>[:<pref>]");
388+
389+
// Size. Required, cannot be zero.
390+
unsigned BitWidth;
391+
if (Error Err = parseSize(Components[0], BitWidth))
392+
return Err;
393+
394+
// ABI alignment.
395+
Align ABIAlign;
396+
if (Error Err = parseAlignment(Components[1], ABIAlign, "ABI"))
397+
return Err;
398+
399+
if (Specifier == 'i' && BitWidth == 8 && ABIAlign != 1)
400+
return createStringError("i8 must be 8-bit aligned");
401+
402+
// Preferred alignment. Optional, defaults to the ABI alignment.
403+
Align PrefAlign = ABIAlign;
404+
if (Components.size() > 2)
405+
if (Error Err = parseAlignment(Components[2], PrefAlign, "preferred"))
406+
return Err;
407+
408+
if (PrefAlign < ABIAlign)
409+
return createStringError(
410+
"preferred alignment cannot be less than the ABI alignment");
411+
412+
setPrimitiveSpec(Specifier, BitWidth, ABIAlign, PrefAlign);
413+
return Error::success();
414+
}
415+
416+
Error DataLayout::parseAggregateSpec(StringRef Spec) {
417+
// a<size>:<abi>[:<pref>]
418+
SmallVector<StringRef, 3> Components;
419+
assert(Spec.front() == 'a');
420+
Spec.drop_front().split(Components, ':');
421+
422+
if (Components.size() < 2 || Components.size() > 3)
423+
return createSpecFormatError("a:<abi>[:<pref>]");
424+
425+
// According to LangRef, <size> component must be absent altogether.
426+
// For backward compatibility, allow it to be specified, but require
427+
// it to be zero.
428+
if (!Components[0].empty()) {
429+
unsigned BitWidth;
430+
if (!to_integer(Components[0], BitWidth, 10) || BitWidth != 0)
431+
return createStringError("size must be zero");
432+
}
433+
434+
// ABI alignment. Required. Can be zero, meaning use one byte alignment.
435+
Align ABIAlign;
436+
if (Error Err =
437+
parseAlignment(Components[1], ABIAlign, "ABI", /*AllowZero=*/true))
438+
return Err;
439+
440+
// Preferred alignment. Optional, defaults to the ABI alignment.
441+
Align PrefAlign = ABIAlign;
442+
if (Components.size() > 2)
443+
if (Error Err = parseAlignment(Components[2], PrefAlign, "preferred"))
444+
return Err;
445+
446+
if (PrefAlign < ABIAlign)
447+
return createStringError(
448+
"preferred alignment cannot be less than the ABI alignment");
449+
450+
StructABIAlignment = ABIAlign;
451+
StructPrefAlignment = PrefAlign;
452+
return Error::success();
453+
}
454+
379455
Error DataLayout::parsePointerSpec(StringRef Spec) {
380456
// p[<n>]:<size>:<abi>[:<pref>[:<idx>]]
381457
SmallVector<StringRef, 5> Components;
@@ -451,6 +527,12 @@ Error DataLayout::parseSpecification(StringRef Spec) {
451527
assert(!Spec.empty() && "Empty specification is handled by the caller");
452528
char Specifier = Spec.front();
453529

530+
if (Specifier == 'i' || Specifier == 'f' || Specifier == 'v')
531+
return parsePrimitiveSpec(Spec);
532+
533+
if (Specifier == 'a')
534+
return parseAggregateSpec(Spec);
535+
454536
if (Specifier == 'p')
455537
return parsePointerSpec(Spec);
456538

@@ -477,78 +559,6 @@ Error DataLayout::parseSpecification(StringRef Spec) {
477559
case 'e':
478560
BigEndian = false;
479561
break;
480-
case 'i':
481-
case 'v':
482-
case 'f':
483-
case 'a': {
484-
TypeSpecifier Specifier;
485-
switch (SpecifierChar) {
486-
default:
487-
llvm_unreachable("Unexpected specifier!");
488-
case 'i':
489-
Specifier = TypeSpecifier::Integer;
490-
break;
491-
case 'v':
492-
Specifier = TypeSpecifier::Vector;
493-
break;
494-
case 'f':
495-
Specifier = TypeSpecifier::Float;
496-
break;
497-
case 'a':
498-
Specifier = TypeSpecifier::Aggregate;
499-
break;
500-
}
501-
502-
// Bit size.
503-
unsigned Size = 0;
504-
if (!Tok.empty())
505-
if (Error Err = getInt(Tok, Size))
506-
return Err;
507-
508-
if (Specifier == TypeSpecifier::Aggregate && Size != 0)
509-
return reportError("Sized aggregate specification in datalayout string");
510-
511-
// ABI alignment.
512-
if (Rest.empty())
513-
return reportError(
514-
"Missing alignment specification in datalayout string");
515-
if (Error Err = ::split(Rest, ':', Split))
516-
return Err;
517-
unsigned ABIAlign;
518-
if (Error Err = getIntInBytes(Tok, ABIAlign))
519-
return Err;
520-
if (Specifier != TypeSpecifier::Aggregate && !ABIAlign)
521-
return reportError(
522-
"ABI alignment specification must be >0 for non-aggregate types");
523-
524-
if (!isUInt<16>(ABIAlign))
525-
return reportError("Invalid ABI alignment, must be a 16bit integer");
526-
if (ABIAlign != 0 && !isPowerOf2_64(ABIAlign))
527-
return reportError("Invalid ABI alignment, must be a power of 2");
528-
if (Specifier == TypeSpecifier::Integer && Size == 8 && ABIAlign != 1)
529-
return reportError("Invalid ABI alignment, i8 must be naturally aligned");
530-
531-
// Preferred alignment.
532-
unsigned PrefAlign = ABIAlign;
533-
if (!Rest.empty()) {
534-
if (Error Err = ::split(Rest, ':', Split))
535-
return Err;
536-
if (Error Err = getIntInBytes(Tok, PrefAlign))
537-
return Err;
538-
}
539-
540-
if (!isUInt<16>(PrefAlign))
541-
return reportError(
542-
"Invalid preferred alignment, must be a 16bit integer");
543-
if (PrefAlign != 0 && !isPowerOf2_64(PrefAlign))
544-
return reportError("Invalid preferred alignment, must be a power of 2");
545-
546-
if (Error Err = setPrimitiveSpec(Specifier, Size, assumeAligned(ABIAlign),
547-
assumeAligned(PrefAlign)))
548-
return Err;
549-
550-
break;
551-
}
552562
case 'n': // Native integer types.
553563
while (true) {
554564
unsigned Width;
@@ -668,32 +678,19 @@ Error DataLayout::parseLayoutString(StringRef LayoutString) {
668678
return Error::success();
669679
}
670680

671-
Error DataLayout::setPrimitiveSpec(TypeSpecifier Specifier, uint32_t BitWidth,
672-
Align ABIAlign, Align PrefAlign) {
673-
// AlignmentsTy::ABIAlign and AlignmentsTy::PrefAlign were once stored as
674-
// uint16_t, it is unclear if there are requirements for alignment to be less
675-
// than 2^16 other than storage. In the meantime we leave the restriction as
676-
// an assert. See D67400 for context.
677-
assert(Log2(ABIAlign) < 16 && Log2(PrefAlign) < 16 && "Alignment too big");
678-
if (!isUInt<24>(BitWidth))
679-
return reportError("Invalid bit width, must be a 24-bit integer");
680-
if (PrefAlign < ABIAlign)
681-
return reportError(
682-
"Preferred alignment cannot be less than the ABI alignment");
683-
681+
void DataLayout::setPrimitiveSpec(char Specifier, uint32_t BitWidth,
682+
Align ABIAlign, Align PrefAlign) {
684683
SmallVectorImpl<PrimitiveSpec> *Specs;
685684
switch (Specifier) {
686-
case TypeSpecifier::Aggregate:
687-
StructABIAlignment = ABIAlign;
688-
StructPrefAlignment = PrefAlign;
689-
return Error::success();
690-
case TypeSpecifier::Integer:
685+
default:
686+
llvm_unreachable("Unexpected specifier");
687+
case 'i':
691688
Specs = &IntSpecs;
692689
break;
693-
case TypeSpecifier::Float:
690+
case 'f':
694691
Specs = &FloatSpecs;
695692
break;
696-
case TypeSpecifier::Vector:
693+
case 'v':
697694
Specs = &VectorSpecs;
698695
break;
699696
}
@@ -707,7 +704,6 @@ Error DataLayout::setPrimitiveSpec(TypeSpecifier Specifier, uint32_t BitWidth,
707704
// Insert before I to keep the vector sorted.
708705
Specs->insert(I, PrimitiveSpec{BitWidth, ABIAlign, PrefAlign});
709706
}
710-
return Error::success();
711707
}
712708

713709
const DataLayout::PointerSpec &

llvm/test/Transforms/InstCombine/crash.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: opt < %s -passes=instcombine -S
2-
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128:n8:16:32"
2+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
33
target triple = "i386-apple-darwin10.0"
44

55
define i32 @test0(i8 %tmp2) ssp {

llvm/test/Transforms/InstCombine/phi.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
22
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
33

4-
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128:n8:16:32:64"
4+
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
55

66
define i32 @test1(i32 %A, i1 %b) {
77
; CHECK-LABEL: @test1(

0 commit comments

Comments
 (0)