Skip to content

Commit 308a0d7

Browse files
committed
Workaround for bfloat16 parameter type demangling
LLVM releases before 20 don't recognise the Itanium mangling `DF16b` for `bfloat16`. Replace it to the vendor-extended encoding `u6__bf16` before demangling, which all known demangler versions parse correctly as `NameType("__bf16")`. AI-assisted: Claude Sonnet 4.6 (commercial SaaS)
1 parent 33ce346 commit 308a0d7

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

lib/SPIRV/SPIRVUtil.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ static Type *parsePrimitiveType(LLVMContext &Ctx, StringRef Name) {
696696
.Cases("long", "unsigned long", Type::getInt64Ty(Ctx))
697697
.Cases("long long", "unsigned long long", Type::getInt64Ty(Ctx))
698698
.Case("half", Type::getHalfTy(Ctx))
699-
.Case("std::bfloat16_t", Type::getBFloatTy(Ctx))
699+
.Cases("std::bfloat16_t", "__bf16", Type::getBFloatTy(Ctx))
700700
.Case("float", Type::getFloatTy(Ctx))
701701
.Case("double", Type::getDoubleTy(Ctx))
702702
.Case("void", Type::getInt8Ty(Ctx))
@@ -878,7 +878,8 @@ parseNode(Module *M, const llvm::itanium_demangle::Node *ParamType,
878878
}
879879
} else if (auto *VendorTy = dyn_cast<VendorExtQualType>(ParamType)) {
880880
if (auto *NameTy = dyn_cast<NameType>(VendorTy->getTy())) {
881-
if (NameTy->getName() == "std::bfloat16_t")
881+
if (NameTy->getName() == "std::bfloat16_t" ||
882+
NameTy->getName() == "__bf16")
882883
PointeeTy = llvm::Type::getBFloatTy(M->getContext());
883884
}
884885
// This is a block parameter. Decode the pointee type as if it were a
@@ -938,13 +939,32 @@ bool getParameterTypes(Function *F, SmallVectorImpl<Type *> &ArgTys,
938939
if (HasSret)
939940
++ArgIter;
940941

942+
// "DF<N>b" mangling for bfloat<N> types (e.g. DF16b for bfloat16) is
943+
// recognized by the demangler only starting from LLVM 20. Replace "DF16b"
944+
// in the parameter section with the vendor-extended-type encoding "u6__bf16",
945+
// which all known demangler versions parse correctly as NameType("__bf16").
946+
std::string PatchedName;
947+
StringRef MangledName(F->getName());
948+
if (MangledName.contains("DF16b")) {
949+
PatchedName = MangledName.str();
950+
// Skip "_Z<N><name>" to search only in the parameter section.
951+
size_t Start = PatchedName.find_first_not_of("0123456789", 2);
952+
size_t Len = 0;
953+
StringRef(PatchedName).substr(2, Start - 2).getAsInteger(10, Len);
954+
size_t Pos = Start + Len;
955+
while ((Pos = PatchedName.find("DF16b", Pos)) != std::string::npos) {
956+
PatchedName.replace(Pos, 5, "u6__bf16");
957+
Pos += 8;
958+
}
959+
MangledName = PatchedName;
960+
}
961+
941962
// Demangle the function arguments. If we get an input name of
942963
// "_Z12write_imagei20ocl_image1d_array_woDv2_iiDv4_i", then we expect
943964
// that Demangler.getFunctionParameters will return
944965
// "(ocl_image1d_array_wo, int __vector(2), int, int __vector(4))" (in other
945966
// words, the stuff between the parentheses if you ran C++ filt, including
946967
// the parentheses itself).
947-
const StringRef MangledName(F->getName());
948968
ManglingParser<DefaultAllocator> Demangler(MangledName.begin(),
949969
MangledName.end());
950970
// We expect to see only function name encodings here. If it's not a function

0 commit comments

Comments
 (0)