[flang-commits] [flang] Revert "[flang] add option to generate runtime type info as external" (PR #146064)
via flang-commits
flang-commits at lists.llvm.org
Fri Jun 27 05:06:10 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: None (jeanPerier)
<details>
<summary>Changes</summary>
Reverts llvm/llvm-project#<!-- -->145901
Broke shared library builds because of the usage of `skipExternalRttiDefinition` in Lowering.
---
Patch is 43.97 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/146064.diff
15 Files Affected:
- (modified) flang/include/flang/Evaluate/tools.h (-1)
- (modified) flang/include/flang/Optimizer/CodeGen/CodeGen.h (-3)
- (modified) flang/include/flang/Optimizer/Passes/CommandLineOpts.h (-13)
- (modified) flang/include/flang/Optimizer/Support/Utils.h (+26)
- (modified) flang/include/flang/Semantics/runtime-type-info.h (-4)
- (modified) flang/lib/Evaluate/tools.cpp (-5)
- (modified) flang/lib/Lower/Bridge.cpp (+1-15)
- (modified) flang/lib/Lower/ConvertVariable.cpp (+2-8)
- (modified) flang/lib/Optimizer/CodeGen/CodeGen.cpp (+49-53)
- (modified) flang/lib/Optimizer/Passes/CommandLineOpts.cpp (-6)
- (modified) flang/lib/Optimizer/Passes/Pipelines.cpp (-1)
- (modified) flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp (+35-60)
- (removed) flang/test/Integration/skip-external-rtti-definition.F90 (-47)
- (modified) flang/test/Lower/select-type-2.f90 (+4-4)
- (modified) flang/test/Lower/select-type.f90 (+36-36)
``````````diff
diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index cad1b634f8924..d26a477ddded1 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -1585,7 +1585,6 @@ bool IsExtensibleType(const DerivedTypeSpec *);
bool IsSequenceOrBindCType(const DerivedTypeSpec *);
bool IsBuiltinDerivedType(const DerivedTypeSpec *derived, const char *name);
bool IsBuiltinCPtr(const Symbol &);
-bool IsFromBuiltinModule(const Symbol &);
bool IsEventType(const DerivedTypeSpec *);
bool IsLockType(const DerivedTypeSpec *);
bool IsNotifyType(const DerivedTypeSpec *);
diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
index 93f07d8d5d4d9..0398d0f248e08 100644
--- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h
+++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
@@ -39,9 +39,6 @@ struct FIRToLLVMPassOptions {
// that such programs would crash at runtime if the derived type descriptors
// are required by the runtime, so this is only an option to help debugging.
bool ignoreMissingTypeDescriptors = false;
- // Similar to ignoreMissingTypeDescriptors, but generate external declaration
- // for the missing type descriptor globals instead.
- bool skipExternalRttiDefinition = false;
// Generate TBAA information for FIR types and memory accessing operations.
bool applyTBAA = false;
diff --git a/flang/include/flang/Optimizer/Passes/CommandLineOpts.h b/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
index 76ac9d0622d2b..1cfaf285e75e6 100644
--- a/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
+++ b/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
@@ -32,19 +32,6 @@ extern llvm::cl::opt<std::size_t> arrayStackAllocationThreshold;
/// generated by the frontend.
extern llvm::cl::opt<bool> ignoreMissingTypeDescriptors;
-/// Shared option in tools to only generate rtti static object definitions for
-/// derived types defined in the current compilation unit. Derived type
-/// descriptor object for types defined in other objects will only be declared
-/// as external. This also changes the linkage of rtti objects defined in the
-/// current compilation unit from linkonce_odr to external so that unused rtti
-/// objects are retained and can be accessed from other compilation units. This
-/// is an experimental option to explore compilation speed improvements and is
-/// an ABI breaking change because of the linkage change.
-/// It will also require linking against module file objects of modules defining
-/// only types (even for trivial types without type bound procedures, which
-/// differs from most compilers).
-extern llvm::cl::opt<bool> skipExternalRttiDefinition;
-
/// Default optimization level used to create Flang pass pipeline is O0.
extern llvm::OptimizationLevel defaultOptLevel;
diff --git a/flang/include/flang/Optimizer/Support/Utils.h b/flang/include/flang/Optimizer/Support/Utils.h
index 83c936b7dcada..ec73af6ec72e9 100644
--- a/flang/include/flang/Optimizer/Support/Utils.h
+++ b/flang/include/flang/Optimizer/Support/Utils.h
@@ -35,6 +35,32 @@ inline std::int64_t toInt(mlir::arith::ConstantOp cop) {
.getSExtValue();
}
+// Reconstruct binding tables for dynamic dispatch.
+using BindingTable = llvm::DenseMap<llvm::StringRef, unsigned>;
+using BindingTables = llvm::DenseMap<llvm::StringRef, BindingTable>;
+
+inline void buildBindingTables(BindingTables &bindingTables,
+ mlir::ModuleOp mod) {
+
+ // The binding tables are defined in FIR after lowering inside fir.type_info
+ // operations. Go through each binding tables and store the procedure name and
+ // binding index for later use by the fir.dispatch conversion pattern.
+ for (auto typeInfo : mod.getOps<fir::TypeInfoOp>()) {
+ unsigned bindingIdx = 0;
+ BindingTable bindings;
+ if (typeInfo.getDispatchTable().empty()) {
+ bindingTables[typeInfo.getSymName()] = bindings;
+ continue;
+ }
+ for (auto dtEntry :
+ typeInfo.getDispatchTable().front().getOps<fir::DTEntryOp>()) {
+ bindings[dtEntry.getMethod()] = bindingIdx;
+ ++bindingIdx;
+ }
+ bindingTables[typeInfo.getSymName()] = bindings;
+ }
+}
+
// Translate front-end KINDs for use in the IR and code gen.
inline std::vector<fir::KindTy>
fromDefaultKinds(const Fortran::common::IntrinsicTypeDefaultKinds &defKinds) {
diff --git a/flang/include/flang/Semantics/runtime-type-info.h b/flang/include/flang/Semantics/runtime-type-info.h
index 6c5a061d1c1a2..e90d3ae8baf1e 100644
--- a/flang/include/flang/Semantics/runtime-type-info.h
+++ b/flang/include/flang/Semantics/runtime-type-info.h
@@ -38,10 +38,6 @@ RuntimeDerivedTypeTables BuildRuntimeDerivedTypeTables(SemanticsContext &);
/// to describe other derived types at runtime in flang descriptor.
constexpr char typeInfoBuiltinModule[]{"__fortran_type_info"};
-/// Name of the builtin derived type in __fortran_type_inf that is used for
-/// derived type descriptors.
-constexpr char typeDescriptorTypeName[]{"derivedtype"};
-
/// Name of the bindings descriptor component in the DerivedType type of the
/// __Fortran_type_info module
constexpr char bindingDescCompName[]{"binding"};
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index fcacdb93d662b..68838564f87ba 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -2334,11 +2334,6 @@ bool IsBuiltinCPtr(const Symbol &symbol) {
return false;
}
-bool IsFromBuiltinModule(const Symbol &symbol) {
- const Scope &scope{symbol.GetUltimate().owner()};
- return IsSameModule(&scope, scope.context().GetBuiltinsScope());
-}
-
bool IsIsoCType(const DerivedTypeSpec *derived) {
return IsBuiltinDerivedType(derived, "c_ptr") ||
IsBuiltinDerivedType(derived, "c_funptr");
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 018bed4aacf0d..7b640dd497af3 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -52,7 +52,6 @@
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
-#include "flang/Optimizer/Passes/CommandLineOpts.h"
#include "flang/Optimizer/Support/DataLayout.h"
#include "flang/Optimizer/Support/FatalError.h"
#include "flang/Optimizer/Support/InternalNames.h"
@@ -263,7 +262,6 @@ class TypeInfoConverter {
}
void createTypeInfo(Fortran::lower::AbstractConverter &converter) {
- createTypeInfoForTypeDescriptorBuiltinType(converter);
while (!registeredTypeInfoA.empty()) {
currentTypeInfoStack = ®isteredTypeInfoB;
for (const TypeInfo &info : registeredTypeInfoA)
@@ -279,22 +277,10 @@ class TypeInfoConverter {
private:
void createTypeInfoOpAndGlobal(Fortran::lower::AbstractConverter &converter,
const TypeInfo &info) {
- if (!::skipExternalRttiDefinition)
- Fortran::lower::createRuntimeTypeInfoGlobal(converter, info.symbol.get());
+ Fortran::lower::createRuntimeTypeInfoGlobal(converter, info.symbol.get());
createTypeInfoOp(converter, info);
}
- void createTypeInfoForTypeDescriptorBuiltinType(
- Fortran::lower::AbstractConverter &converter) {
- if (registeredTypeInfoA.empty())
- return;
- auto builtinTypeInfoType = llvm::cast<fir::RecordType>(
- converter.genType(registeredTypeInfoA[0].symbol.get()));
- converter.getFirOpBuilder().createTypeInfoOp(
- registeredTypeInfoA[0].loc, builtinTypeInfoType,
- /*parentType=*/fir::RecordType{});
- }
-
void createTypeInfoOp(Fortran::lower::AbstractConverter &converter,
const TypeInfo &info) {
fir::RecordType parentType{};
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 39599625a42c4..49e6ea02d51a7 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -38,7 +38,6 @@
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
-#include "flang/Optimizer/Passes/CommandLineOpts.h"
#include "flang/Optimizer/Support/FatalError.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Support/Utils.h"
@@ -653,13 +652,8 @@ getLinkageAttribute(fir::FirOpBuilder &builder,
// Runtime type info for a same derived type is identical in each compilation
// unit. It desired to avoid having to link against module that only define a
// type. Therefore the runtime type info is generated everywhere it is needed
- // with `linkonce_odr` LLVM linkage (unless the skipExternalRttiDefinition
- // option is set, in which case one will need to link against objects of
- // modules defining types). Builtin objects rtti is always generated because
- // the builtin module is currently not compiled or part of the runtime.
- if (var.isRuntimeTypeInfoData() &&
- (!::skipExternalRttiDefinition ||
- Fortran::semantics::IsFromBuiltinModule(var.getSymbol())))
+ // with `linkonce_odr` LLVM linkage.
+ if (var.isRuntimeTypeInfoData())
return builder.createLinkOnceODRLinkage();
if (var.isModuleOrSubmoduleVariable())
return {}; // external linkage
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 2b018912b40e4..a3de3ae9d116a 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -1294,51 +1294,6 @@ genCUFAllocDescriptor(mlir::Location loc,
.getResult();
}
-/// Get the address of the type descriptor global variable that was created by
-/// lowering for derived type \p recType.
-template <typename ModOpTy>
-static mlir::Value
-getTypeDescriptor(ModOpTy mod, mlir::ConversionPatternRewriter &rewriter,
- mlir::Location loc, fir::RecordType recType,
- const fir::FIRToLLVMPassOptions &options) {
- std::string name =
- options.typeDescriptorsRenamedForAssembly
- ? fir::NameUniquer::getTypeDescriptorAssemblyName(recType.getName())
- : fir::NameUniquer::getTypeDescriptorName(recType.getName());
- mlir::Type llvmPtrTy = ::getLlvmPtrType(mod.getContext());
- if (auto global = mod.template lookupSymbol<fir::GlobalOp>(name))
- return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
- global.getSymName());
- // The global may have already been translated to LLVM.
- if (auto global = mod.template lookupSymbol<mlir::LLVM::GlobalOp>(name))
- return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
- global.getSymName());
- // Type info derived types do not have type descriptors since they are the
- // types defining type descriptors.
- if (options.ignoreMissingTypeDescriptors ||
- fir::NameUniquer::belongsToModule(
- name, Fortran::semantics::typeInfoBuiltinModule))
- return rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmPtrTy);
-
- if (!options.skipExternalRttiDefinition)
- fir::emitFatalError(loc,
- "runtime derived type info descriptor was not "
- "generated and skipExternalRttiDefinition and "
- "ignoreMissingTypeDescriptors options are not set");
-
- // Rtti for a derived type defined in another compilation unit and for which
- // rtti was not defined in lowering because of the skipExternalRttiDefinition
- // option. Generate the object declaration now.
- auto insertPt = rewriter.saveInsertionPoint();
- rewriter.setInsertionPoint(mod.getBody(), mod.getBody()->end());
- mlir::LLVM::GlobalOp global = rewriter.create<mlir::LLVM::GlobalOp>(
- loc, llvmPtrTy, /*constant=*/true, mlir::LLVM::Linkage::External, name,
- mlir::Attribute());
- rewriter.restoreInsertionPoint(insertPt);
- return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
- global.getSymName());
-}
-
/// Common base class for embox to descriptor conversion.
template <typename OP>
struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
@@ -1451,6 +1406,36 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
stride);
}
+ /// Get the address of the type descriptor global variable that was created by
+ /// lowering for derived type \p recType.
+ template <typename ModOpTy>
+ mlir::Value
+ getTypeDescriptor(ModOpTy mod, mlir::ConversionPatternRewriter &rewriter,
+ mlir::Location loc, fir::RecordType recType) const {
+ std::string name =
+ this->options.typeDescriptorsRenamedForAssembly
+ ? fir::NameUniquer::getTypeDescriptorAssemblyName(recType.getName())
+ : fir::NameUniquer::getTypeDescriptorName(recType.getName());
+ mlir::Type llvmPtrTy = ::getLlvmPtrType(mod.getContext());
+ if (auto global = mod.template lookupSymbol<fir::GlobalOp>(name)) {
+ return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
+ global.getSymName());
+ }
+ if (auto global = mod.template lookupSymbol<mlir::LLVM::GlobalOp>(name)) {
+ // The global may have already been translated to LLVM.
+ return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
+ global.getSymName());
+ }
+ // Type info derived types do not have type descriptors since they are the
+ // types defining type descriptors.
+ if (!this->options.ignoreMissingTypeDescriptors &&
+ !fir::NameUniquer::belongsToModule(
+ name, Fortran::semantics::typeInfoBuiltinModule))
+ fir::emitFatalError(
+ loc, "runtime derived type info descriptor was not generated");
+ return rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmPtrTy);
+ }
+
template <typename ModOpTy>
mlir::Value populateDescriptor(mlir::Location loc, ModOpTy mod,
fir::BaseBoxType boxTy, mlir::Type inputType,
@@ -1515,8 +1500,7 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
mlir::Type innerType = fir::unwrapInnerType(inputType);
if (innerType && mlir::isa<fir::RecordType>(innerType)) {
auto recTy = mlir::dyn_cast<fir::RecordType>(innerType);
- typeDesc =
- getTypeDescriptor(mod, rewriter, loc, recTy, this->options);
+ typeDesc = getTypeDescriptor(mod, rewriter, loc, recTy);
} else {
// Unlimited polymorphic type descriptor with no record type. Set
// type descriptor address to a clean state.
@@ -1524,8 +1508,8 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
loc, ::getLlvmPtrType(mod.getContext()));
}
} else {
- typeDesc = getTypeDescriptor(
- mod, rewriter, loc, fir::unwrapIfDerived(boxTy), this->options);
+ typeDesc = getTypeDescriptor(mod, rewriter, loc,
+ fir::unwrapIfDerived(boxTy));
}
}
if (typeDesc)
@@ -3037,10 +3021,22 @@ struct TypeDescOpConversion : public fir::FIROpConversion<fir::TypeDescOp> {
assert(mlir::isa<fir::RecordType>(inTy) && "expecting fir.type");
auto recordType = mlir::dyn_cast<fir::RecordType>(inTy);
auto module = typeDescOp.getOperation()->getParentOfType<mlir::ModuleOp>();
- mlir::Value typeDesc = getTypeDescriptor(
- module, rewriter, typeDescOp.getLoc(), recordType, this->options);
- rewriter.replaceOp(typeDescOp, typeDesc);
- return mlir::success();
+ std::string typeDescName =
+ this->options.typeDescriptorsRenamedForAssembly
+ ? fir::NameUniquer::getTypeDescriptorAssemblyName(
+ recordType.getName())
+ : fir::NameUniquer::getTypeDescriptorName(recordType.getName());
+ auto llvmPtrTy = ::getLlvmPtrType(typeDescOp.getContext());
+ if (auto global = module.lookupSymbol<mlir::LLVM::GlobalOp>(typeDescName)) {
+ rewriter.replaceOpWithNewOp<mlir::LLVM::AddressOfOp>(
+ typeDescOp, llvmPtrTy, global.getSymName());
+ return mlir::success();
+ } else if (auto global = module.lookupSymbol<fir::GlobalOp>(typeDescName)) {
+ rewriter.replaceOpWithNewOp<mlir::LLVM::AddressOfOp>(
+ typeDescOp, llvmPtrTy, global.getSymName());
+ return mlir::success();
+ }
+ return mlir::failure();
}
};
diff --git a/flang/lib/Optimizer/Passes/CommandLineOpts.cpp b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
index 014237542f24d..f95a280883cba 100644
--- a/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
+++ b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
@@ -39,12 +39,6 @@ cl::opt<bool> ignoreMissingTypeDescriptors(
"translating FIR to LLVM"),
cl::init(false), cl::Hidden);
-cl::opt<bool> skipExternalRttiDefinition(
- "skip-external-rtti-definition", llvm::cl::init(false),
- llvm::cl::desc("do not define rtti static objects for types belonging to "
- "other compilation units"),
- cl::Hidden);
-
OptimizationLevel defaultOptLevel{OptimizationLevel::O0};
codegenoptions::DebugInfoKind noDebugInfo{codegenoptions::NoDebugInfo};
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 42d9e7ba2418f..70f57bdeddd3f 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -108,7 +108,6 @@ void addFIRToLLVMPass(mlir::PassManager &pm,
const MLIRToLLVMPassPipelineConfig &config) {
fir::FIRToLLVMPassOptions options;
options.ignoreMissingTypeDescriptors = ignoreMissingTypeDescriptors;
- options.skipExternalRttiDefinition = skipExternalRttiDefinition;
options.applyTBAA = config.AliasAnalysis;
options.forceUnifiedTBAATree = useOldAliasTags;
options.typeDescriptorsRenamedForAssembly =
diff --git a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
index 57eae1ff052a2..f9a4c4d0283c7 100644
--- a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
+++ b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
@@ -16,6 +16,7 @@
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Support/TypeCode.h"
+#include "flang/Optimizer/Support/Utils.h"
#include "flang/Optimizer/Transforms/Passes.h"
#include "flang/Runtime/derived-api.h"
#include "flang/Semantics/runtime-type-info.h"
@@ -37,45 +38,6 @@ namespace fir {
using namespace fir;
using namespace mlir;
-// Reconstruct binding tables for dynamic dispatch.
-using BindingTable = llvm::DenseMap<llvm::StringRef, unsigned>;
-using BindingTables = llvm::DenseMap<llvm::StringRef, BindingTable>;
-
-static std::string getTypeDescriptorTypeName() {
- llvm::SmallVector<llvm::StringRef, 1> modules = {
- Fortran::semantics::typeInfoBuiltinModule};
- return fir::NameUniquer::doType(modules, /*proc=*/{}, /*blockId=*/0,
- Fortran::semantics::typeDescriptorTypeName,
- /*kinds=*/{});
-}
-
-static std::optional<mlir::Type>
-buildBindingTables(BindingTables &bindingTables, mlir::ModuleOp mod) {
-
- std::optional<mlir::Type> typeDescriptorType;
- std::string typeDescriptorTypeName = getTypeDescriptorTypeName();
- // The binding tables are defined in FIR after lowering inside fir.type_info
- // operations. Go through each binding tables and store the procedure name and
- // binding index for later use by the fir.dispatch conversion pattern.
- for (auto typeInfo : mod.getOps<fir::TypeInfoOp>()) {
- if (!typeDescriptorType && typeInfo.getSymName() == typeDescriptorTypeName)
- typeDescriptorType = typeInfo.getType();
- unsigned bindingIdx = 0;
- BindingTable bindings;
- if (typeInfo.getDispatchTable().empty()) {
- bindingTables[typeInfo.getSymName()] = bindings;
- continue;
- }
- for (auto dtEntry :
- typeInfo.getDispatchTable().front().getOps<fir::DTEntryOp>()) {
- bindings[dtEntry.getMethod()] = bindingIdx;
- ++bindingIdx;
- }
- bindingTables[typeInfo.getS...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/146064
More information about the flang-commits
mailing list