Skip to content

Commit cb9a963

Browse files
committed
[LLVM][IR] Add support for address space names in DataLayout
1 parent 1054a6e commit cb9a963

File tree

6 files changed

+244
-47
lines changed

6 files changed

+244
-47
lines changed

llvm/include/llvm/IR/DataLayout.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "llvm/ADT/APInt.h"
2323
#include "llvm/ADT/ArrayRef.h"
24+
#include "llvm/ADT/DenseSet.h"
2425
#include "llvm/ADT/STLExtras.h"
2526
#include "llvm/ADT/SmallVector.h"
2627
#include "llvm/ADT/StringRef.h"
@@ -92,6 +93,13 @@ class DataLayout {
9293
/// of this would be CHERI capabilities where the validity bit is stored
9394
/// separately from the pointer address+bounds information.
9495
bool HasExternalState;
96+
// Symbolic name of the address space. We can store a StringRef here
97+
// directly (backed by StringRepresentation) but then the copy construtor
98+
// has to be updated to redirect these StringRefs to the copy of
99+
// StringRepresentation. To avoid that, we store just the offset and size
100+
// of the address space name.
101+
size_t AddrSpaceNameOffset;
102+
size_t AddrSpaceNameSize;
95103
LLVM_ABI bool operator==(const PointerSpec &Other) const;
96104
};
97105

@@ -158,7 +166,8 @@ class DataLayout {
158166
/// Sets or updates the specification for pointer in the given address space.
159167
void setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign,
160168
Align PrefAlign, uint32_t IndexBitWidth,
161-
bool HasUnstableRepr, bool HasExternalState);
169+
bool HasUnstableRepr, bool HasExternalState,
170+
StringRef AddrSpaceName);
162171

163172
/// Internal helper to get alignment for integer of given bitwidth.
164173
LLVM_ABI Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const;
@@ -173,11 +182,13 @@ class DataLayout {
173182
Error parseAggregateSpec(StringRef Spec);
174183

175184
/// Attempts to parse pointer specification ('p').
176-
Error parsePointerSpec(StringRef Spec);
185+
Error parsePointerSpec(StringRef Spec,
186+
SmallDenseSet<StringRef, 8> &AddrSpaceNames);
177187

178188
/// Attempts to parse a single specification.
179189
Error parseSpecification(StringRef Spec,
180-
SmallVectorImpl<unsigned> &NonIntegralAddressSpaces);
190+
SmallVectorImpl<unsigned> &NonIntegralAddressSpaces,
191+
SmallDenseSet<StringRef, 8> &AddrSpaceNames);
181192

182193
/// Attempts to parse a data layout string.
183194
Error parseLayoutString(StringRef LayoutString);
@@ -324,9 +335,13 @@ class DataLayout {
324335
return false;
325336
}
326337

327-
/// Layout pointer alignment
338+
/// Layout pointer alignment.
328339
LLVM_ABI Align getPointerABIAlignment(unsigned AS) const;
329340

341+
LLVM_ABI StringRef getAddressSpaceName(unsigned AS) const;
342+
343+
LLVM_ABI std::optional<unsigned> getNamedAddressSpace(StringRef Name) const;
344+
330345
/// Return target's alignment for stack-based pointers
331346
/// FIXME: The defaults need to be removed once all of
332347
/// the backends/clients are updated.

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1958,13 +1958,16 @@ bool LLParser::parseOptionalAddrSpace(unsigned &AddrSpace, unsigned DefaultAS) {
19581958

19591959
auto ParseAddrspaceValue = [&](unsigned &AddrSpace) -> bool {
19601960
if (Lex.getKind() == lltok::StringConstant) {
1961-
auto AddrSpaceStr = Lex.getStrVal();
1961+
const std::string &AddrSpaceStr = Lex.getStrVal();
19621962
if (AddrSpaceStr == "A") {
19631963
AddrSpace = M->getDataLayout().getAllocaAddrSpace();
19641964
} else if (AddrSpaceStr == "G") {
19651965
AddrSpace = M->getDataLayout().getDefaultGlobalsAddressSpace();
19661966
} else if (AddrSpaceStr == "P") {
19671967
AddrSpace = M->getDataLayout().getProgramAddressSpace();
1968+
} else if (std::optional<unsigned> AS =
1969+
M->getDataLayout().getNamedAddressSpace(AddrSpaceStr)) {
1970+
AddrSpace = *AS;
19681971
} else {
19691972
return tokError("invalid symbolic addrspace '" + AddrSpaceStr + "'");
19701973
}

llvm/lib/IR/AsmWriter.cpp

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,8 @@ namespace {
543543

544544
class TypePrinting {
545545
public:
546-
TypePrinting(const Module *M = nullptr) : DeferredM(M) {}
546+
TypePrinting(const Module *M = nullptr)
547+
: M(M), TypesIncorporated(M == nullptr) {}
547548

548549
TypePrinting(const TypePrinting &) = delete;
549550
TypePrinting &operator=(const TypePrinting &) = delete;
@@ -563,8 +564,9 @@ class TypePrinting {
563564
private:
564565
void incorporateTypes();
565566

566-
/// A module to process lazily when needed. Set to nullptr as soon as used.
567-
const Module *DeferredM;
567+
/// A module to process lazily.
568+
const Module *M;
569+
bool TypesIncorporated;
568570

569571
TypeFinder NamedTypes;
570572

@@ -605,11 +607,11 @@ bool TypePrinting::empty() {
605607
}
606608

607609
void TypePrinting::incorporateTypes() {
608-
if (!DeferredM)
610+
if (TypesIncorporated)
609611
return;
610612

611-
NamedTypes.run(*DeferredM, false);
612-
DeferredM = nullptr;
613+
NamedTypes.run(*M, false);
614+
TypesIncorporated = true;
613615

614616
// The list of struct types we got back includes all the struct types, split
615617
// the unnamed ones out to a numbering and remove the anonymous structs.
@@ -630,6 +632,20 @@ void TypePrinting::incorporateTypes() {
630632
NamedTypes.erase(NextToUse, NamedTypes.end());
631633
}
632634

635+
static void printAddressSpace(const Module *M, unsigned AS, raw_ostream &OS,
636+
StringRef Prefix = " ", StringRef Suffix = "",
637+
bool ForcePrint = false) {
638+
if (AS == 0 && !ForcePrint)
639+
return;
640+
OS << Prefix << "addrspace(";
641+
StringRef ASName = M ? M->getDataLayout().getAddressSpaceName(AS) : "";
642+
if (!ASName.empty())
643+
OS << "\"" << ASName << "\"";
644+
else
645+
OS << AS;
646+
OS << ")" << Suffix;
647+
}
648+
633649
/// Write the specified type to the specified raw_ostream, making use of type
634650
/// names or up references to shorten the type name where possible.
635651
void TypePrinting::print(Type *Ty, raw_ostream &OS) {
@@ -686,8 +702,7 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
686702
case Type::PointerTyID: {
687703
PointerType *PTy = cast<PointerType>(Ty);
688704
OS << "ptr";
689-
if (unsigned AddressSpace = PTy->getAddressSpace())
690-
OS << " addrspace(" << AddressSpace << ')';
705+
printAddressSpace(M, PTy->getAddressSpace(), OS);
691706
return;
692707
}
693708
case Type::ArrayTyID: {
@@ -3896,10 +3911,10 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
38963911
printThreadLocalModel(GV->getThreadLocalMode(), Out);
38973912
StringRef UA = getUnnamedAddrEncoding(GV->getUnnamedAddr());
38983913
if (!UA.empty())
3899-
Out << UA << ' ';
3914+
Out << UA << ' ';
39003915

3901-
if (unsigned AddressSpace = GV->getType()->getAddressSpace())
3902-
Out << "addrspace(" << AddressSpace << ") ";
3916+
printAddressSpace(GV->getParent(), GV->getType()->getAddressSpace(), Out,
3917+
/*Prefix=*/"", /*Suffix=*/" ");
39033918
if (GV->isExternallyInitialized()) Out << "externally_initialized ";
39043919
Out << (GV->isConstant() ? "constant " : "global ");
39053920
TypePrinter.print(GV->getValueType(), Out);
@@ -4174,9 +4189,10 @@ void AssemblyWriter::printFunction(const Function *F) {
41744189
// a module with a non-zero program address space or if there is no valid
41754190
// Module* so that the file can be parsed without the datalayout string.
41764191
const Module *Mod = F->getParent();
4177-
if (F->getAddressSpace() != 0 || !Mod ||
4178-
Mod->getDataLayout().getProgramAddressSpace() != 0)
4179-
Out << " addrspace(" << F->getAddressSpace() << ")";
4192+
bool ForcePrintAddressSpace =
4193+
!Mod || Mod->getDataLayout().getProgramAddressSpace() != 0;
4194+
printAddressSpace(Mod, F->getAddressSpace(), Out, /*Prefix=*/" ",
4195+
/*Suffix=*/"", ForcePrintAddressSpace);
41804196
if (Attrs.hasFnAttrs())
41814197
Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttrs());
41824198
if (F->hasSection()) {
@@ -4352,23 +4368,21 @@ void AssemblyWriter::printInfoComment(const Value &V, bool isMaterializable) {
43524368

43534369
static void maybePrintCallAddrSpace(const Value *Operand, const Instruction *I,
43544370
raw_ostream &Out) {
4355-
// We print the address space of the call if it is non-zero.
43564371
if (Operand == nullptr) {
43574372
Out << " <cannot get addrspace!>";
43584373
return;
43594374
}
4375+
4376+
// We print the address space of the call if it is non-zero.
4377+
// We also print it if it is zero but not equal to the program address space
4378+
// or if we can't find a valid Module* to make it possible to parse
4379+
// the resulting file even without a datalayout string.
43604380
unsigned CallAddrSpace = Operand->getType()->getPointerAddressSpace();
4361-
bool PrintAddrSpace = CallAddrSpace != 0;
4362-
if (!PrintAddrSpace) {
4363-
const Module *Mod = getModuleFromVal(I);
4364-
// We also print it if it is zero but not equal to the program address space
4365-
// or if we can't find a valid Module* to make it possible to parse
4366-
// the resulting file even without a datalayout string.
4367-
if (!Mod || Mod->getDataLayout().getProgramAddressSpace() != 0)
4368-
PrintAddrSpace = true;
4369-
}
4370-
if (PrintAddrSpace)
4371-
Out << " addrspace(" << CallAddrSpace << ")";
4381+
const Module *Mod = getModuleFromVal(I);
4382+
bool ForcePrintAddrSpace =
4383+
!Mod || Mod->getDataLayout().getProgramAddressSpace() != 0;
4384+
printAddressSpace(Mod, CallAddrSpace, Out, /*Prefix=*/" ", /*Suffix=*/"",
4385+
ForcePrintAddrSpace);
43724386
}
43734387

43744388
// This member is called for each Instruction in a function..
@@ -4735,9 +4749,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
47354749
Out << ", align " << A->value();
47364750
}
47374751

4738-
unsigned AddrSpace = AI->getAddressSpace();
4739-
if (AddrSpace != 0)
4740-
Out << ", addrspace(" << AddrSpace << ')';
4752+
printAddressSpace(AI->getModule(), AI->getAddressSpace(), Out,
4753+
/*Prefix=*/", ");
47414754
} else if (isa<CastInst>(I)) {
47424755
if (Operand) {
47434756
Out << ' ';

0 commit comments

Comments
 (0)