aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Module.cpp
diff options
context:
space:
mode:
authorJeroen Dobbelaere <jeroen.dobbelaere@synopsys.com>2021-03-19 14:34:25 +0100
committerJeroen Dobbelaere <jeroen.dobbelaere@synopsys.com>2021-03-19 14:34:25 +0100
commit04790d9cfba35073d56047544502c387c5657bb1 (patch)
tree159536511b7af6ad5c3f7895d909c6a360b1fadb /llvm/lib/IR/Module.cpp
parenta5f9cda17333530de3d78282d10f53abfaa00906 (diff)
downloadllvm-04790d9cfba35073d56047544502c387c5657bb1.zip
llvm-04790d9cfba35073d56047544502c387c5657bb1.tar.gz
llvm-04790d9cfba35073d56047544502c387c5657bb1.tar.bz2
Support intrinsic overloading on unnamed types
This patch adds support for intrinsic overloading on unnamed types. This fixes PR38117 and PR48340 and will also be needed for the Full Restrict Patches (D68484). The main problem is that the intrinsic overloading name mangling is using 's_s' for unnamed types. This can result in identical intrinsic mangled names for different function prototypes. This patch changes this by adding a '.XXXXX' to the intrinsic mangled name when at least one of the types is based on an unnamed type, ensuring that we get a unique name. Implementation details: - The mapping is created on demand and kept in Module. - It also checks for existing clashes and recycles potentially existing prototypes and declarations. - Because of extra data in Module, Intrinsic::getName needs an extra Module* argument and, for speed, an optional FunctionType* argument. - I still kept the original two-argument 'Intrinsic::getName' around which keeps the original behavior (providing the base name). -- Main reason is that I did not want to change the LLVMIntrinsicGetName version, as I don't know how acceptable such a change is -- The current situation already has a limitation. So that should not get worse with this patch. - Intrinsic::getDeclaration and the verifier are now using the new version. Other notes: - As far as I see, this should not suffer from stability issues. The count is only added for prototypes depending on at least one anonymous struct - The initial count starts from 0 for each intrinsic mangled name. - In case of name clashes, existing prototypes are remembered and reused when that makes sense. Reviewed By: fhahn Differential Revision: https://reviews.llvm.org/D91250
Diffstat (limited to 'llvm/lib/IR/Module.cpp')
-rw-r--r--llvm/lib/IR/Module.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp
index 60056f1..b9c3663 100644
--- a/llvm/lib/IR/Module.cpp
+++ b/llvm/lib/IR/Module.cpp
@@ -473,6 +473,56 @@ std::vector<StructType *> Module::getIdentifiedStructTypes() const {
return Ret;
}
+std::string Module::getUniqueIntrinsicName(StringRef BaseName, Intrinsic::ID Id,
+ const FunctionType *Proto) {
+ auto Encode = [&BaseName](unsigned Suffix) {
+ return (Twine(BaseName) + "." + Twine(Suffix)).str();
+ };
+
+ {
+ // fast path - the prototype is already known
+ auto UinItInserted = UniquedIntrinsicNames.insert({{Id, Proto}, 0});
+ if (!UinItInserted.second)
+ return Encode(UinItInserted.first->second);
+ }
+
+ // Not known yet. A new entry was created with index 0. Check if there already
+ // exists a matching declaration, or select a new entry.
+
+ // Start looking for names with the current known maximum count (or 0).
+ auto NiidItInserted = CurrentIntrinsicIds.insert({BaseName, 0});
+ unsigned Count = NiidItInserted.first->second;
+
+ // This might be slow if a whole population of intrinsics already existed, but
+ // we cache the values for later usage.
+ std::string NewName;
+ while (true) {
+ NewName = Encode(Count);
+ GlobalValue *F = getNamedValue(NewName);
+ if (!F) {
+ // Reserve this entry for the new proto
+ UniquedIntrinsicNames[{Id, Proto}] = Count;
+ break;
+ }
+
+ // A declaration with this name already exists. Remember it.
+ FunctionType *FT = dyn_cast<FunctionType>(F->getType()->getElementType());
+ auto UinItInserted = UniquedIntrinsicNames.insert({{Id, FT}, Count});
+ if (FT == Proto) {
+ // It was a declaration for our prototype. This entry was allocated in the
+ // beginning. Update the count to match the existing declaration.
+ UinItInserted.first->second = Count;
+ break;
+ }
+
+ ++Count;
+ }
+
+ NiidItInserted.first->second = Count + 1;
+
+ return NewName;
+}
+
// dropAllReferences() - This function causes all the subelements to "let go"
// of all references that they are maintaining. This allows one to 'delete' a
// whole module at a time, even though there may be circular references... first