2424#include " mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
2525#include " mlir/Target/LLVMIR/Export.h"
2626#include " mlir/Transforms/DialectConversion.h"
27- #include " clang/CIR/Dialect/IR/CIRAttrVisitor.h"
2827#include " clang/CIR/Dialect/IR/CIRDialect.h"
2928#include " clang/CIR/MissingFeatures.h"
3029#include " llvm/IR/Module.h"
@@ -36,71 +35,6 @@ using namespace llvm;
3635namespace cir {
3736namespace direct {
3837
39- class CIRAttrToValue : public CirAttrVisitor <CIRAttrToValue, mlir::Value> {
40- public:
41- CIRAttrToValue (mlir::Operation *parentOp,
42- mlir::ConversionPatternRewriter &rewriter,
43- const mlir::TypeConverter *converter)
44- : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
45-
46- mlir::Value lowerCirAttrAsValue (mlir::Attribute attr) { return visit (attr); }
47-
48- mlir::Value visitCirIntAttr (cir::IntAttr intAttr) {
49- mlir::Location loc = parentOp->getLoc ();
50- return rewriter.create <mlir::LLVM::ConstantOp>(
51- loc, converter->convertType (intAttr.getType ()), intAttr.getValue ());
52- }
53-
54- mlir::Value visitCirFPAttr (cir::FPAttr fltAttr) {
55- mlir::Location loc = parentOp->getLoc ();
56- return rewriter.create <mlir::LLVM::ConstantOp>(
57- loc, converter->convertType (fltAttr.getType ()), fltAttr.getValue ());
58- }
59-
60- mlir::Value visitCirConstPtrAttr (cir::ConstPtrAttr ptrAttr) {
61- mlir::Location loc = parentOp->getLoc ();
62- if (ptrAttr.isNullValue ()) {
63- return rewriter.create <mlir::LLVM::ZeroOp>(
64- loc, converter->convertType (ptrAttr.getType ()));
65- }
66- mlir::DataLayout layout (parentOp->getParentOfType <mlir::ModuleOp>());
67- mlir::Value ptrVal = rewriter.create <mlir::LLVM::ConstantOp>(
68- loc,
69- rewriter.getIntegerType (layout.getTypeSizeInBits (ptrAttr.getType ())),
70- ptrAttr.getValue ().getInt ());
71- return rewriter.create <mlir::LLVM::IntToPtrOp>(
72- loc, converter->convertType (ptrAttr.getType ()), ptrVal);
73- }
74-
75- private:
76- mlir::Operation *parentOp;
77- mlir::ConversionPatternRewriter &rewriter;
78- const mlir::TypeConverter *converter;
79- };
80-
81- // This class handles rewriting initializer attributes for types that do not
82- // require region initialization.
83- class GlobalInitAttrRewriter
84- : public CirAttrVisitor<GlobalInitAttrRewriter, mlir::Attribute> {
85- public:
86- GlobalInitAttrRewriter (mlir::Type type,
87- mlir::ConversionPatternRewriter &rewriter)
88- : llvmType(type), rewriter(rewriter) {}
89-
90- mlir::Attribute rewriteInitAttr (mlir::Attribute attr) { return visit (attr); }
91-
92- mlir::Attribute visitCirIntAttr (cir::IntAttr attr) {
93- return rewriter.getIntegerAttr (llvmType, attr.getValue ());
94- }
95- mlir::Attribute visitCirFPAttr (cir::FPAttr attr) {
96- return rewriter.getFloatAttr (llvmType, attr.getValue ());
97- }
98-
99- private:
100- mlir::Type llvmType;
101- mlir::ConversionPatternRewriter &rewriter;
102- };
103-
10438// This pass requires the CIR to be in a "flat" state. All blocks in each
10539// function must belong to the parent region. Once scopes and control flow
10640// are implemented in CIR, a pass will be run before this one to flatten
@@ -121,81 +55,14 @@ struct ConvertCIRToLLVMPass
12155 StringRef getArgument () const override { return " cir-flat-to-llvm" ; }
12256};
12357
124- bool CIRToLLVMGlobalOpLowering::attrRequiresRegionInitialization (
125- mlir::Attribute attr) const {
126- // There will be more cases added later.
127- return isa<cir::ConstPtrAttr>(attr);
128- }
129-
130- // / Replace CIR global with a region initialized LLVM global and update
131- // / insertion point to the end of the initializer block.
132- void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp (
133- cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter) const {
134- assert (!cir::MissingFeatures::convertTypeForMemory ());
135- const mlir::Type llvmType = getTypeConverter ()->convertType (op.getSymType ());
136-
137- // FIXME: These default values are placeholders until the the equivalent
138- // attributes are available on cir.global ops. This duplicates code
139- // in CIRToLLVMGlobalOpLowering::matchAndRewrite() but that will go
140- // away when the placeholders are no longer needed.
141- assert (!cir::MissingFeatures::opGlobalConstant ());
142- const bool isConst = false ;
143- assert (!cir::MissingFeatures::addressSpace ());
144- const unsigned addrSpace = 0 ;
145- assert (!cir::MissingFeatures::opGlobalDSOLocal ());
146- const bool isDsoLocal = true ;
147- assert (!cir::MissingFeatures::opGlobalThreadLocal ());
148- const bool isThreadLocal = false ;
149- assert (!cir::MissingFeatures::opGlobalAlignment ());
150- const uint64_t alignment = 0 ;
151- assert (!cir::MissingFeatures::opGlobalLinkage ());
152- const mlir::LLVM::Linkage linkage = mlir::LLVM::Linkage::External;
153- const StringRef symbol = op.getSymName ();
154-
155- SmallVector<mlir::NamedAttribute> attributes;
156- auto newGlobalOp = rewriter.replaceOpWithNewOp <mlir::LLVM::GlobalOp>(
157- op, llvmType, isConst, linkage, symbol, nullptr , alignment, addrSpace,
158- isDsoLocal, isThreadLocal,
159- /* comdat=*/ mlir::SymbolRefAttr (), attributes);
160- newGlobalOp.getRegion ().push_back (new mlir::Block ());
161- rewriter.setInsertionPointToEnd (newGlobalOp.getInitializerBlock ());
162- };
163-
164- mlir::LogicalResult
165- CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal (
166- cir::GlobalOp op, mlir::Attribute init,
167- mlir::ConversionPatternRewriter &rewriter) const {
168- // TODO: Generalize this handling when more types are needed here.
169- assert (isa<cir::ConstPtrAttr>(init));
170-
171- // TODO(cir): once LLVM's dialect has proper equivalent attributes this
172- // should be updated. For now, we use a custom op to initialize globals
173- // to the appropriate value.
174- const mlir::Location loc = op.getLoc ();
175- setupRegionInitializedLLVMGlobalOp (op, rewriter);
176- CIRAttrToValue attrVisitor (op, rewriter, typeConverter);
177- mlir::Value value = attrVisitor.lowerCirAttrAsValue (init);
178- rewriter.create <mlir::LLVM::ReturnOp>(loc, value);
179- return mlir::success ();
180- }
181-
18258mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite (
18359 cir::GlobalOp op, OpAdaptor adaptor,
18460 mlir::ConversionPatternRewriter &rewriter) const {
18561
186- std::optional<mlir::Attribute> init = op.getInitialValue ();
187-
188- // If we have an initializer and it requires region initialization, handle
189- // that separately
190- if (init.has_value () && attrRequiresRegionInitialization (init.value ())) {
191- return matchAndRewriteRegionInitializedGlobal (op, init.value (), rewriter);
192- }
193-
19462 // Fetch required values to create LLVM op.
19563 const mlir::Type cirSymType = op.getSymType ();
19664
19765 // This is the LLVM dialect type.
198- assert (!cir::MissingFeatures::convertTypeForMemory ());
19966 const mlir::Type llvmType = getTypeConverter ()->convertType (cirSymType);
20067 // FIXME: These default values are placeholders until the the equivalent
20168 // attributes are available on cir.global ops.
@@ -212,15 +79,20 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
21279 assert (!cir::MissingFeatures::opGlobalLinkage ());
21380 const mlir::LLVM::Linkage linkage = mlir::LLVM::Linkage::External;
21481 const StringRef symbol = op.getSymName ();
82+ std::optional<mlir::Attribute> init = op.getInitialValue ();
83+
21584 SmallVector<mlir::NamedAttribute> attributes;
21685
21786 if (init.has_value ()) {
218- GlobalInitAttrRewriter initRewriter (llvmType, rewriter);
219- init = initRewriter.rewriteInitAttr (init.value ());
220- // If initRewriter returned a null attribute, init will have a value but
221- // the value will be null. If that happens, initRewriter didn't handle the
222- // attribute type. It probably needs to be added to GlobalInitAttrRewriter.
223- if (!init.value ()) {
87+ if (const auto fltAttr = mlir::dyn_cast<cir::FPAttr>(init.value ())) {
88+ // Initializer is a constant floating-point number: convert to MLIR
89+ // builtin constant.
90+ init = rewriter.getFloatAttr (llvmType, fltAttr.getValue ());
91+ } else if (const auto intAttr =
92+ mlir::dyn_cast<cir::IntAttr>(init.value ())) {
93+ // Initializer is a constant array: convert it to a compatible llvm init.
94+ init = rewriter.getIntegerAttr (llvmType, intAttr.getValue ());
95+ } else {
22496 op.emitError () << " unsupported initializer '" << init.value () << " '" ;
22597 return mlir::failure ();
22698 }
@@ -237,13 +109,6 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
237109
238110static void prepareTypeConverter (mlir::LLVMTypeConverter &converter,
239111 mlir::DataLayout &dataLayout) {
240- converter.addConversion ([&](cir::PointerType type) -> mlir::Type {
241- // Drop pointee type since LLVM dialect only allows opaque pointers.
242- assert (!cir::MissingFeatures::addressSpace ());
243- unsigned targetAS = 0 ;
244-
245- return mlir::LLVM::LLVMPointerType::get (type.getContext (), targetAS);
246- });
247112 converter.addConversion ([&](cir::IntType type) -> mlir::Type {
248113 // LLVM doesn't work with signed types, so we drop the CIR signs here.
249114 return mlir::IntegerType::get (type.getContext (), type.getWidth ());
0 commit comments