diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -13,8 +13,10 @@ #include "flang/Optimizer/CodeGen/CodeGen.h" #include "PassDetail.h" #include "flang/ISO_Fortran_binding.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIROps.h" +#include "flang/Optimizer/Support/InternalNames.h" #include "mlir/Conversion/ArithmeticToLLVM/ArithmeticToLLVM.h" #include "mlir/Conversion/LLVMCommon/Pattern.h" #include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h" @@ -48,6 +50,18 @@ mlir::Region::iterator(insertBefore)); } +/// Create an LLVM dialect global +static void createGlobal(mlir::Location loc, mlir::ModuleOp mod, StringRef name, + mlir::Type type, + mlir::ConversionPatternRewriter &rewriter) { + if (mod.lookupSymbol(name)) + return; + mlir::OpBuilder modBuilder(mod.getBodyRegion()); + modBuilder.create(loc, type, /*isConstant=*/true, + mlir::LLVM::Linkage::Weak, name, + mlir::Attribute{}); +} + namespace { /// FIR conversion pattern template template @@ -636,6 +650,39 @@ } }; +/// Lower `fir.gentypedesc` to a global constant. +struct GenTypeDescOpConversion : public FIROpConversion { + using FIROpConversion::FIROpConversion; + + mlir::LogicalResult + matchAndRewrite(fir::GenTypeDescOp gentypedesc, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto loc = gentypedesc.getLoc(); + mlir::Type inTy = gentypedesc.getInType(); + std::string name = getUniqueName(rewriter, inTy); + mlir::Type gty = convertType(inTy); + auto pty = mlir::LLVM::LLVMPointerType::get(gty); + auto module = gentypedesc->getParentOfType(); + createGlobal(loc, module, name, gty, rewriter); + rewriter.replaceOpWithNewOp(gentypedesc, pty, + name); + return success(); + } + + // Make a unique name from the RecordType. + std::string getUniqueName(mlir::ConversionPatternRewriter &rewriter, + mlir::Type type) const { + if (auto d = type.dyn_cast()) { + auto name = d.getName(); + auto pair = fir::NameUniquer::deconstruct(name); + return fir::NameUniquer::doTypeDescriptor( + pair.second.modules, pair.second.host, pair.second.name, + pair.second.kinds); + } + llvm_unreachable("can't make unique name from type"); + } +}; + /// Lower `fir.has_value` operation to `llvm.return` operation. struct HasValueOpConversion : public FIROpConversion { using FIROpConversion::FIROpConversion; @@ -1417,12 +1464,13 @@ BoxIsPtrOpConversion, BoxRankOpConversion, CallOpConversion, ConvertOpConversion, DispatchOpConversion, DispatchTableOpConversion, DTEntryOpConversion, DivcOpConversion, ExtractValueOpConversion, - HasValueOpConversion, GlobalOpConversion, InsertOnRangeOpConversion, - InsertValueOpConversion, IsPresentOpConversion, LoadOpConversion, - NegcOpConversion, MulcOpConversion, SelectCaseOpConversion, - SelectOpConversion, SelectRankOpConversion, StoreOpConversion, - SubcOpConversion, UndefOpConversion, UnreachableOpConversion, - ZeroOpConversion>(typeConverter); + HasValueOpConversion, GenTypeDescOpConversion, GlobalOpConversion, + InsertOnRangeOpConversion, InsertValueOpConversion, + IsPresentOpConversion, LoadOpConversion, NegcOpConversion, + MulcOpConversion, SelectCaseOpConversion, SelectOpConversion, + SelectRankOpConversion, StoreOpConversion, SubcOpConversion, + UndefOpConversion, UnreachableOpConversion, ZeroOpConversion>( + typeConverter); mlir::populateStdToLLVMConversionPatterns(typeConverter, pattern); mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter, pattern); diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -1197,3 +1197,16 @@ // CHECK-NEXT: %[[ptr:.*]] = llvm.mlir.null : !llvm.ptr // CHECK-NEXT: %[[ret_val:.*]] = llvm.call @is_present(%[[ptr]]) : (!llvm.ptr) -> i1 // CHECK-NEXT: llvm.return %[[ret_val]] : i1 + +// ----- + +// Test `fir.gentypedesc` conversion. + +func @gentypedesc() { + %0 = fir.gentypedesc !fir.type + return +} + +// CHECK: llvm.mlir.global weak constant @_QCTderived3() : !llvm.struct<"derived3", ()> +// CHECK-LABEL: llvm.func @gentypedesc() { +// CHECK: %0 = llvm.mlir.addressof @_QCTderived3 : !llvm.ptr>