pmatos created this revision.
pmatos added a reviewer: tlively.
Herald added subscribers: llvm-commits, cfe-commits, dexonsmith, jdoerfert, 
hiraditya, dschuff.
Herald added projects: clang, LLVM.
pmatos requested review of this revision.
Herald added a subscriber: aheejin.

Allows for multiple program address spaces to be defined through
multiple Px-Py... in the data layout.
If none is specified, the default program address space is 0.

Unless data layout is modified with multiple Px, this patch shouldn't
have any effect on current code.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D91428

Files:
  clang/lib/CodeGen/CGException.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenTypes.cpp
  llvm/docs/LangRef.rst
  llvm/include/llvm/CodeGen/TargetLowering.h
  llvm/include/llvm/IR/DataLayout.h
  llvm/include/llvm/Target/TargetMachine.h
  llvm/lib/AsmParser/LLParser.cpp
  llvm/lib/AsmParser/LLParser.h
  llvm/lib/Bitcode/Reader/BitcodeReader.cpp
  llvm/lib/IR/AsmWriter.cpp
  llvm/lib/IR/DataLayout.cpp
  llvm/lib/IR/Function.cpp
  llvm/lib/IR/Module.cpp
  llvm/lib/IR/Verifier.cpp
  llvm/lib/Transforms/IPO/LowerTypeTests.cpp
  llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
  llvm/test/Assembler/function-address_spaces.ll

Index: llvm/test/Assembler/function-address_spaces.ll
===================================================================
--- /dev/null
+++ llvm/test/Assembler/function-address_spaces.ll
@@ -0,0 +1,30 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck  %s
+
+; specifying explicitly P:0 (although it's the default)
+; P:1 specifies an extra address space for code where funcrefs live
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1-P0-P1"
+
+; square and double_square are in addrspace(0)
+define i32 @square(i32 %0) {
+; CHECK: define i32 @square(i32 %0) addrspace(0) {
+       %2 = mul nsw i32 %0, %0
+       ret i32 %2
+}
+
+define i32 @double_square(i32 %0) {
+; CHECK: define i32 @double_square(i32 %0) addrspace(0) {
+       %2 = shl i32 %0, 1
+       %3 = mul i32 %2, %0
+       ret i32 %3
+}
+
+; funcref is a pointer to a function in addrspace(1)
+; called in call_funcref
+%func = type void ()
+%funcref = type %func addrspace(1)*
+
+define void @call_funcref(%funcref %ref) {
+; CHECK: define void @call_funcref(void () addrspace(1)* %ref) addrspace(0) {
+       call void %ref()
+       ret void
+}
Index: llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
===================================================================
--- llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -1220,12 +1220,12 @@
   Function *JT;
   if (isa<MDString>(Slot.TypeID)) {
     JT = Function::Create(FT, Function::ExternalLinkage,
-                          M.getDataLayout().getProgramAddressSpace(),
+                          M.getDataLayout().getDefaultProgramAddressSpace(),
                           getGlobalName(Slot, {}, "branch_funnel"), &M);
     JT->setVisibility(GlobalValue::HiddenVisibility);
   } else {
     JT = Function::Create(FT, Function::InternalLinkage,
-                          M.getDataLayout().getProgramAddressSpace(),
+                          M.getDataLayout().getDefaultProgramAddressSpace(),
                           "branch_funnel", &M);
   }
   JT->addAttribute(1, Attribute::Nest);
Index: llvm/lib/Transforms/IPO/LowerTypeTests.cpp
===================================================================
--- llvm/lib/Transforms/IPO/LowerTypeTests.cpp
+++ llvm/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -1276,12 +1276,12 @@
 void LowerTypeTestsModule::moveInitializerToModuleConstructor(
     GlobalVariable *GV) {
   if (WeakInitializerFn == nullptr) {
-    WeakInitializerFn = Function::Create(
-        FunctionType::get(Type::getVoidTy(M.getContext()),
-                          /* IsVarArg */ false),
-        GlobalValue::InternalLinkage,
-        M.getDataLayout().getProgramAddressSpace(),
-        "__cfi_global_var_init", &M);
+    WeakInitializerFn =
+        Function::Create(FunctionType::get(Type::getVoidTy(M.getContext()),
+                                           /* IsVarArg */ false),
+                         GlobalValue::InternalLinkage,
+                         M.getDataLayout().getDefaultProgramAddressSpace(),
+                         "__cfi_global_var_init", &M);
     BasicBlock *BB =
         BasicBlock::Create(M.getContext(), "entry", WeakInitializerFn);
     ReturnInst::Create(M.getContext(), BB);
@@ -1517,12 +1517,11 @@
   for (unsigned I = 0; I != Functions.size(); ++I)
     GlobalLayout[Functions[I]] = I * EntrySize;
 
-  Function *JumpTableFn =
-      Function::Create(FunctionType::get(Type::getVoidTy(M.getContext()),
-                                         /* IsVarArg */ false),
-                       GlobalValue::PrivateLinkage,
-                       M.getDataLayout().getProgramAddressSpace(),
-                       ".cfi.jumptable", &M);
+  Function *JumpTableFn = Function::Create(
+      FunctionType::get(Type::getVoidTy(M.getContext()),
+                        /* IsVarArg */ false),
+      GlobalValue::PrivateLinkage,
+      M.getDataLayout().getDefaultProgramAddressSpace(), ".cfi.jumptable", &M);
   ArrayType *JumpTableType =
       ArrayType::get(getJumpTableEntryType(), Functions.size());
   auto JumpTable =
@@ -1962,7 +1961,8 @@
           F = Function::Create(
               FunctionType::get(Type::getVoidTy(M.getContext()), false),
               GlobalVariable::ExternalLinkage,
-              M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
+              M.getDataLayout().getDefaultProgramAddressSpace(), FunctionName,
+              &M);
 
         // If the function is available_externally, remove its definition so
         // that it is handled the same way as a declaration. Later we will try
Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ llvm/lib/IR/Verifier.cpp
@@ -650,8 +650,8 @@
     if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) {
       StructType *STy = dyn_cast<StructType>(ATy->getElementType());
       PointerType *FuncPtrTy =
-          FunctionType::get(Type::getVoidTy(Context), false)->
-          getPointerTo(DL.getProgramAddressSpace());
+          FunctionType::get(Type::getVoidTy(Context), false)
+              ->getPointerTo(DL.getDefaultProgramAddressSpace());
       Assert(STy &&
                  (STy->getNumElements() == 2 || STy->getNumElements() == 3) &&
                  STy->getTypeAtIndex(0u)->isIntegerTy(32) &&
Index: llvm/lib/IR/Module.cpp
===================================================================
--- llvm/lib/IR/Module.cpp
+++ llvm/lib/IR/Module.cpp
@@ -147,7 +147,7 @@
   if (!F) {
     // Nope, add it
     Function *New = Function::Create(Ty, GlobalVariable::ExternalLinkage,
-                                     DL.getProgramAddressSpace(), Name);
+                                     DL.getDefaultProgramAddressSpace(), Name);
     if (!New->isIntrinsic())       // Intrinsics get attrs set on construction
       New->setAttributes(AttributeList);
     FunctionList.push_back(New);
Index: llvm/lib/IR/Function.cpp
===================================================================
--- llvm/lib/IR/Function.cpp
+++ llvm/lib/IR/Function.cpp
@@ -306,7 +306,8 @@
 
 Function *Function::Create(FunctionType *Ty, LinkageTypes Linkage,
                            const Twine &N, Module &M) {
-  return Create(Ty, Linkage, M.getDataLayout().getProgramAddressSpace(), N, &M);
+  return Create(Ty, Linkage, M.getDataLayout().getDefaultProgramAddressSpace(),
+                N, &M);
 }
 
 void Function::removeFromParent() {
@@ -325,7 +326,7 @@
   // If AS == -1 and we are passed a valid module pointer we place the function
   // in the program address space. Otherwise we default to AS0.
   if (AddrSpace == static_cast<unsigned>(-1))
-    return M ? M->getDataLayout().getProgramAddressSpace() : 0;
+    return M ? M->getDataLayout().getDefaultProgramAddressSpace() : 0;
   return AddrSpace;
 }
 
Index: llvm/lib/IR/DataLayout.cpp
===================================================================
--- llvm/lib/IR/DataLayout.cpp
+++ llvm/lib/IR/DataLayout.cpp
@@ -181,7 +181,7 @@
   BigEndian = false;
   AllocaAddrSpace = 0;
   StackNaturalAlign.reset();
-  ProgramAddrSpace = 0;
+  ProgramAddrSpaces.clear();
   FunctionPtrAlign.reset();
   TheFunctionPtrAlignType = FunctionPtrAlignType::Independent;
   ManglingMode = MM_None;
@@ -470,8 +470,10 @@
       break;
     }
     case 'P': { // Function address space.
-      if (Error Err = getAddrSpace(Tok, ProgramAddrSpace))
+      unsigned pa;
+      if (Error Err = getAddrSpace(Tok, pa))
         return Err;
+      ProgramAddrSpaces.push_back(pa);
       break;
     }
     case 'A': { // Default stack/alloca address space.
@@ -516,6 +518,10 @@
     }
   }
 
+  // If Program address spaces is empty, add the default address space (0)
+  if (ProgramAddrSpaces.empty())
+    ProgramAddrSpaces.push_back(0);
+
   return Error::success();
 }
 
@@ -529,7 +535,7 @@
   bool Ret = BigEndian == Other.BigEndian &&
              AllocaAddrSpace == Other.AllocaAddrSpace &&
              StackNaturalAlign == Other.StackNaturalAlign &&
-             ProgramAddrSpace == Other.ProgramAddrSpace &&
+             ProgramAddrSpaces == Other.ProgramAddrSpaces &&
              FunctionPtrAlign == Other.FunctionPtrAlign &&
              TheFunctionPtrAlignType == Other.TheFunctionPtrAlignType &&
              ManglingMode == Other.ManglingMode &&
Index: llvm/lib/IR/AsmWriter.cpp
===================================================================
--- llvm/lib/IR/AsmWriter.cpp
+++ llvm/lib/IR/AsmWriter.cpp
@@ -3718,7 +3718,7 @@
   // Module* so that the file can be parsed without the datalayout string.
   const Module *Mod = F->getParent();
   if (F->getAddressSpace() != 0 || !Mod ||
-      Mod->getDataLayout().getProgramAddressSpace() != 0)
+      Mod->getDataLayout().hasNonZeroProgramAddressSpace())
     Out << " addrspace(" << F->getAddressSpace() << ")";
   if (Attrs.hasAttributes(AttributeList::FunctionIndex))
     Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttributes());
@@ -3877,7 +3877,7 @@
     // We also print it if it is zero but not equal to the program address space
     // or if we can't find a valid Module* to make it possible to parse
     // the resulting file even without a datalayout string.
-    if (!Mod || Mod->getDataLayout().getProgramAddressSpace() != 0)
+    if (!Mod || Mod->getDataLayout().hasNonZeroProgramAddressSpace())
       PrintAddrSpace = true;
   }
   if (PrintAddrSpace)
Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp
===================================================================
--- llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -3276,7 +3276,8 @@
   if (CC & ~CallingConv::MaxID)
     return error("Invalid calling convention ID");
 
-  unsigned AddrSpace = TheModule->getDataLayout().getProgramAddressSpace();
+  unsigned AddrSpace =
+      TheModule->getDataLayout().getDefaultProgramAddressSpace();
   if (Record.size() > 16)
     AddrSpace = Record[16];
 
Index: llvm/lib/AsmParser/LLParser.h
===================================================================
--- llvm/lib/AsmParser/LLParser.h
+++ llvm/lib/AsmParser/LLParser.h
@@ -256,7 +256,7 @@
     bool parseOptionalAddrSpace(unsigned &AddrSpace, unsigned DefaultAS = 0);
     bool parseOptionalProgramAddrSpace(unsigned &AddrSpace) {
       return parseOptionalAddrSpace(
-          AddrSpace, M->getDataLayout().getProgramAddressSpace());
+          AddrSpace, M->getDataLayout().getDefaultProgramAddressSpace());
     };
     bool parseOptionalParamAttrs(AttrBuilder &B);
     bool parseOptionalReturnAttrs(AttrBuilder &B);
Index: llvm/lib/AsmParser/LLParser.cpp
===================================================================
--- llvm/lib/AsmParser/LLParser.cpp
+++ llvm/lib/AsmParser/LLParser.cpp
@@ -1466,21 +1466,29 @@
                                         Value *Val, bool IsCall) {
   if (Val->getType() == Ty)
     return Val;
+
   // For calls we also accept variables in the program address space.
-  Type *SuggestedTy = Ty;
   if (IsCall && isa<PointerType>(Ty)) {
-    Type *TyInProgAS = cast<PointerType>(Ty)->getElementType()->getPointerTo(
-        M->getDataLayout().getProgramAddressSpace());
-    SuggestedTy = TyInProgAS;
-    if (Val->getType() == TyInProgAS)
-      return Val;
+    // Call through a function pointer
+    // The type can live in any of the program address spaces
+
+    // We check if the address space of the pointer type of Val is one
+    // of the defined program address spaces and if with that AS, Ty matches
+    // Val's type.
+    if (M->getDataLayout().isPointerTypeInProgramAddressSpace(Ty)) {
+      Type *TyInProgAS = cast<PointerType>(Ty)->getElementType()->getPointerTo(
+          cast<PointerType>(Val->getType())->getAddressSpace());
+
+      if (Val->getType() == TyInProgAS)
+        return Val;
+    }
   }
   if (Ty->isLabelTy())
     error(Loc, "'" + Name + "' is not a basic block");
   else
     error(Loc, "'" + Name + "' defined with type '" +
                    getTypeString(Val->getType()) + "' but expected '" +
-                   getTypeString(SuggestedTy) + "'");
+                   getTypeString(Ty) + "'");
   return nullptr;
 }
 
Index: llvm/include/llvm/Target/TargetMachine.h
===================================================================
--- llvm/include/llvm/Target/TargetMachine.h
+++ llvm/include/llvm/Target/TargetMachine.h
@@ -175,7 +175,7 @@
   }
 
   unsigned getProgramPointerSize() const {
-    return DL.getPointerSize(DL.getProgramAddressSpace());
+    return DL.getPointerSize(DL.getDefaultProgramAddressSpace());
   }
 
   unsigned getAllocaPointerSize() const {
Index: llvm/include/llvm/IR/DataLayout.h
===================================================================
--- llvm/include/llvm/IR/DataLayout.h
+++ llvm/include/llvm/IR/DataLayout.h
@@ -122,7 +122,11 @@
 
   unsigned AllocaAddrSpace;
   MaybeAlign StackNaturalAlign;
-  unsigned ProgramAddrSpace;
+  /// Vector of address spaces that can contain code
+  /// Always non-empty, contains the default address space by default.
+  /// Harvard architectures can specify a different address space.
+  /// WebAssembly might specify more than one address space.
+  SmallVector<unsigned, 8> ProgramAddrSpaces;
 
   MaybeAlign FunctionPtrAlign;
   FunctionPtrAlignType TheFunctionPtrAlignType;
@@ -218,7 +222,7 @@
     StackNaturalAlign = DL.StackNaturalAlign;
     FunctionPtrAlign = DL.FunctionPtrAlign;
     TheFunctionPtrAlignType = DL.TheFunctionPtrAlignType;
-    ProgramAddrSpace = DL.ProgramAddrSpace;
+    ProgramAddrSpaces = DL.ProgramAddrSpaces;
     ManglingMode = DL.ManglingMode;
     LegalIntWidths = DL.LegalIntWidths;
     Alignments = DL.Alignments;
@@ -294,7 +298,33 @@
     return TheFunctionPtrAlignType;
   }
 
-  unsigned getProgramAddressSpace() const { return ProgramAddrSpace; }
+  ArrayRef<unsigned> getProgramAddressSpaces() const {
+    assert(!ProgramAddrSpaces.empty());
+    return ProgramAddrSpaces;
+  }
+
+  unsigned getDefaultProgramAddressSpace() const {
+    assert(!ProgramAddrSpaces.empty());
+    return ProgramAddrSpaces[0];
+  }
+
+  bool isProgramAddressSpace(unsigned AddrSpace) const {
+    ArrayRef<unsigned> ProgramAddressSpaces = getProgramAddressSpaces();
+    return find(ProgramAddressSpaces, AddrSpace) != ProgramAddressSpaces.end();
+  }
+
+  bool isPointerTypeInProgramAddressSpace(PointerType *PT) const {
+    return isProgramAddressSpace(PT->getAddressSpace());
+  }
+
+  bool isPointerTypeInProgramAddressSpace(Type *Ty) const {
+    auto *PTy = dyn_cast<PointerType>(Ty);
+    return PTy && isPointerTypeInProgramAddressSpace(PTy);
+  }
+
+  bool hasNonZeroProgramAddressSpace() const {
+    return ProgramAddrSpaces.size() > 1 || ProgramAddrSpaces[0] != 0;
+  }
 
   bool hasMicrosoftFastStdCallMangling() const {
     return ManglingMode == MM_WinCOFFX86;
Index: llvm/include/llvm/CodeGen/TargetLowering.h
===================================================================
--- llvm/include/llvm/CodeGen/TargetLowering.h
+++ llvm/include/llvm/CodeGen/TargetLowering.h
@@ -359,7 +359,7 @@
   /// Return the type for code pointers, which is determined by the program
   /// address space specified through the data layout.
   MVT getProgramPointerTy(const DataLayout &DL) const {
-    return getPointerTy(DL, DL.getProgramAddressSpace());
+    return getPointerTy(DL, DL.getDefaultProgramAddressSpace());
   }
 
   /// Return the type for operands of fence.
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -2380,7 +2380,7 @@
     alignment defaults to "unspecified", which does not prevent any
     alignment promotions.
 ``P<address space>``
-    Specifies the address space that corresponds to program memory.
+    Specifies an address space that corresponds to program memory.
     Harvard architectures can use this to specify what space LLVM
     should place things such as functions into. If omitted, the
     program memory space defaults to the default address space of 0,
Index: clang/lib/CodeGen/CodeGenTypes.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenTypes.cpp
+++ clang/lib/CodeGen/CodeGenTypes.cpp
@@ -629,7 +629,7 @@
       PointeeType = llvm::Type::getInt8Ty(getLLVMContext());
 
     unsigned AS = PointeeType->isFunctionTy()
-                      ? getDataLayout().getProgramAddressSpace()
+                      ? getDataLayout().getDefaultProgramAddressSpace()
                       : Context.getTargetAddressSpace(ETy);
 
     ResultType = llvm::PointerType::get(PointeeType, AS);
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1296,8 +1296,8 @@
 
   // Ctor function type is void()*.
   llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false);
-  llvm::Type *CtorPFTy = llvm::PointerType::get(CtorFTy,
-      TheModule.getDataLayout().getProgramAddressSpace());
+  llvm::Type *CtorPFTy = llvm::PointerType::get(
+      CtorFTy, TheModule.getDataLayout().getDefaultProgramAddressSpace());
 
   // Get the type of a ctor entry, { i32, void ()*, i8* }.
   llvm::StructType *CtorStructTy = llvm::StructType::get(
Index: clang/lib/CodeGen/CGException.cpp
===================================================================
--- clang/lib/CodeGen/CGException.cpp
+++ clang/lib/CodeGen/CGException.cpp
@@ -247,9 +247,9 @@
 static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,
                                         const EHPersonality &Personality) {
   llvm::FunctionCallee Fn = getPersonalityFn(CGM, Personality);
-  llvm::PointerType* Int8PtrTy = llvm::PointerType::get(
+  llvm::PointerType *Int8PtrTy = llvm::PointerType::get(
       llvm::Type::getInt8Ty(CGM.getLLVMContext()),
-      CGM.getDataLayout().getProgramAddressSpace());
+      CGM.getDataLayout().getDefaultProgramAddressSpace());
 
   return llvm::ConstantExpr::getBitCast(cast<llvm::Constant>(Fn.getCallee()),
                                         Int8PtrTy);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to