diff options
22 files changed, 235 insertions, 168 deletions
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 93d81e3..569491a 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -178,9 +178,10 @@ public: } mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) { - auto operandTy = mlir::cast<cir::ComplexType>(operand.getType()); - return cir::ComplexImagOp::create(*this, loc, operandTy.getElementType(), - operand); + auto resultType = operand.getType(); + if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType)) + resultType = complexResultType.getElementType(); + return cir::ComplexImagOp::create(*this, loc, resultType, operand); } cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr, diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 7f2e55d..c81f64d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3308,18 +3308,20 @@ def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> { def CIR_ComplexImagOp : CIR_Op<"complex.imag", [Pure]> { let summary = "Extract the imaginary part of a complex value"; let description = [{ - `cir.complex.imag` operation takes an operand of `!cir.complex` type and - yields the imaginary part of it. + `cir.complex.imag` operation takes an operand of `!cir.complex`, `!cir.int` + or `!cir.float`. If the operand is `!cir.complex`, the imag part of it will + be returned, otherwise a zero value will be returned. Example: ```mlir - %1 = cir.complex.imag %0 : !cir.complex<!cir.float> -> !cir.float + %imag = cir.complex.imag %complex : !cir.complex<!cir.float> -> !cir.float + %imag = cir.complex.imag %scalar : !cir.float -> !cir.float ``` }]; let results = (outs CIR_AnyIntOrFloatType:$result); - let arguments = (ins CIR_ComplexType:$operand); + let arguments = (ins CIR_AnyComplexOrIntOrFloatType:$operand); let assemblyFormat = [{ $operand `:` qualified(type($operand)) `->` qualified(type($result)) diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index e943b02..0f4d6d2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -718,10 +718,26 @@ void CIRGenFunction::emitAtomicInit(Expr *init, LValue dest) { return; } - case cir::TEK_Aggregate: - cgm.errorNYI(init->getSourceRange(), "emitAtomicInit: aggregate type"); + case cir::TEK_Aggregate: { + // Fix up the destination if the initializer isn't an expression + // of atomic type. + bool zeroed = false; + if (!init->getType()->isAtomicType()) { + zeroed = atomics.emitMemSetZeroIfNecessary(); + dest = atomics.projectValue(); + } + + // Evaluate the expression directly into the destination. + assert(!cir::MissingFeatures::aggValueSlotGC()); + AggValueSlot slot = AggValueSlot::forLValue( + dest, AggValueSlot::IsNotDestructed, AggValueSlot::IsNotAliased, + AggValueSlot::DoesNotOverlap, + zeroed ? AggValueSlot::IsZeroed : AggValueSlot::IsNotZeroed); + + emitAggExpr(init, slot); return; } + } llvm_unreachable("bad evaluation kind"); } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 500007f..768d75d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -2159,16 +2159,16 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e, // __imag on a scalar returns zero. Emit the subexpr to ensure side // effects are evaluated, but not the actual value. - if (op->isGLValue()) - cgf.emitLValue(op); - else if (!promotionTy.isNull()) - cgf.emitPromotedScalarExpr(op, promotionTy); - else - cgf.emitScalarExpr(op); - - mlir::Type valueTy = - cgf.convertType(promotionTy.isNull() ? e->getType() : promotionTy); - return builder.getNullValue(valueTy, loc); + mlir::Value operand; + if (op->isGLValue()) { + operand = cgf.emitLValue(op).getPointer(); + operand = cir::LoadOp::create(builder, loc, operand); + } else if (!promotionTy.isNull()) { + operand = cgf.emitPromotedScalarExpr(op, promotionTy); + } else { + operand = cgf.emitScalarExpr(op); + } + return builder.createComplexImag(loc, operand); } /// Return the size or alignment of the type of argument of the sizeof diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index fba094f..cdd4e3c 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2402,9 +2402,8 @@ OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) { LogicalResult cir::ComplexRealOp::verify() { mlir::Type operandTy = getOperand().getType(); - if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) { + if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) operandTy = complexOperandTy.getElementType(); - } if (getType() != operandTy) { emitOpError() << ": result type does not match operand type"; @@ -2431,14 +2430,22 @@ OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) { //===----------------------------------------------------------------------===// LogicalResult cir::ComplexImagOp::verify() { - if (getType() != getOperand().getType().getElementType()) { + mlir::Type operandTy = getOperand().getType(); + if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) + operandTy = complexOperandTy.getElementType(); + + if (getType() != operandTy) { emitOpError() << ": result type does not match operand type"; return failure(); } + return success(); } OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) { + if (!mlir::isa<cir::ComplexType>(getOperand().getType())) + return nullptr; + if (auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>()) return complexCreateOp.getOperand(1); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index bfb1262..1ff8cc5 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3061,8 +3061,19 @@ mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite( cir::ComplexImagOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType()); - rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>( - op, resultLLVMTy, adaptor.getOperand(), llvm::ArrayRef<std::int64_t>{1}); + mlir::Value operand = adaptor.getOperand(); + mlir::Location loc = op.getLoc(); + + if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) { + operand = mlir::LLVM::ExtractValueOp::create( + rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1}); + } else { + mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy); + operand = + mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr); + } + + rewriter.replaceOp(op, operand); return mlir::success(); } diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index a9ab87e..3524b8b 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -1160,8 +1160,9 @@ void imag_on_scalar_glvalue() { // CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"] // CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init] -// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float -// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> +// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float +// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.float -> !cir.float +// CIR: cir.store{{.*}} %[[A_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> // LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4 // LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4 @@ -1205,9 +1206,10 @@ void imag_on_scalar_with_type_promotion() { // CIR: %[[A_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["a"] // CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init] -// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float -// CIR: %[[CONST_ZERO_F16:.*]] = cir.cast floating %[[CONST_ZERO]] : !cir.float -> !cir.f16 -// CIR: cir.store{{.*}} %[[CONST_ZERO_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16> +// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.f16>, !cir.f16 +// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.f16 -> !cir.f16 +// CIR: %[[A_IMAG_F16:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.f16 +// CIR: cir.store{{.*}} %[[A_IMAG_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16> // LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 2 // LLVM: %[[B_ADDR:.*]] = alloca half, i64 1, align 2 @@ -1225,8 +1227,8 @@ void imag_on_const_scalar() { // CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"] // CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init] // CIR: %[[CONST_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float -// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float -// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> +// CIR: %[[CONST_IMAG:.*]] = cir.complex.imag %[[CONST_ONE]] : !cir.float -> !cir.float +// CIR: cir.store{{.*}} %[[CONST_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> // LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4 // LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4 diff --git a/clang/test/CIR/CodeGen/struct.cpp b/clang/test/CIR/CodeGen/struct.cpp index 52367bd..c68f742 100644 --- a/clang/test/CIR/CodeGen/struct.cpp +++ b/clang/test/CIR/CodeGen/struct.cpp @@ -184,6 +184,34 @@ void generic_selection() { // OGCG: %[[D_ADDR:.*]] = alloca %struct.CompleteS, align 4 // OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[D_ADDR]], ptr align 4 %[[A_ADDR]], i64 8, i1 false) +void atomic_init() { + _Atomic CompleteS a; + __c11_atomic_init(&a, {}); +} + +// CIR: cir.func{{.*}} @_Z11atomic_initv() +// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a"] +// CIR: %[[ELEM_0_PTR:.*]] = cir.get_member %[[A_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i> +// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i +// CIR: cir.store{{.*}} %[[CONST_0]], %[[ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i> +// CIR: %[[ELEM_1_PTR:.*]] = cir.get_member %[[A_ADDR]][1] {name = "b"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s8i> +// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s8i +// CIR: cir.store{{.*}} %[[CONST_0]], %[[ELEM_1_PTR]] : !s8i, !cir.ptr<!s8i> + +// LLVM: define{{.*}} void @_Z11atomic_initv() +// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 8 +// LLVM: %[[ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0 +// LLVM: store i32 0, ptr %[[ELEM_0_PTR]], align 8 +// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1 +// LLVM: store i8 0, ptr %[[ELEM_1_PTR]], align 4 + +// OGCG: define{{.*}} void @_Z11atomic_initv() +// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 8 +// OGCG: %[[ELEM_0_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: store i32 0, ptr %[[ELEM_0_PTR]], align 8 +// OGCG: %[[ELEM_1_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store i8 0, ptr %[[ELEM_1_PTR]], align 4 + void unary_extension() { CompleteS a = __extension__ CompleteS(); } diff --git a/llvm/include/llvm/TableGen/CodeGenHelpers.h b/llvm/include/llvm/TableGen/CodeGenHelpers.h new file mode 100644 index 0000000..7dca6a0 --- /dev/null +++ b/llvm/include/llvm/TableGen/CodeGenHelpers.h @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines common utilities for generating C++ code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TABLEGEN_CODEGENHELPERS_H +#define LLVM_TABLEGEN_CODEGENHELPERS_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" +#include <string> + +namespace llvm { +// Simple RAII helper for emitting ifdef-undef-endif scope. +class IfDefEmitter { +public: + IfDefEmitter(raw_ostream &OS, StringRef Name) : Name(Name.str()), OS(OS) { + OS << "#ifdef " << Name << "\n" + << "#undef " << Name << "\n\n"; + } + ~IfDefEmitter() { OS << "\n#endif // " << Name << "\n\n"; } + +private: + std::string Name; + raw_ostream &OS; +}; + +// Simple RAII helper for emitting namespace scope. Name can be a single +// namespace (empty for anonymous namespace) or nested namespace. +class NamespaceEmitter { +public: + NamespaceEmitter(raw_ostream &OS, StringRef Name) : OS(OS) { + emitNamespaceStarts(Name); + } + + ~NamespaceEmitter() { close(); } + + // Explicit function to close the namespace scopes. + void close() { + for (StringRef NS : llvm::reverse(Namespaces)) + OS << "} // namespace " << NS << "\n"; + Namespaces.clear(); + } + +private: + void emitNamespaceStarts(StringRef Name) { + llvm::SplitString(Name, Namespaces, "::"); + for (StringRef NS : Namespaces) + OS << "namespace " << NS << " {\n"; + } + + SmallVector<StringRef, 2> Namespaces; + raw_ostream &OS; +}; + +} // end namespace llvm + +#endif // LLVM_TABLEGEN_CODEGENHELPERS_H diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp index cba282c..a2e8c69 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp @@ -15,13 +15,12 @@ using namespace llvm; -namespace { /// Return true if and only if the given instruction does not modify the memory /// location referenced. Note that an idemptent atomicrmw may still have /// ordering effects on nearby instructions, or be volatile. /// TODO: Common w/ the version in AtomicExpandPass, and change the term used. /// Idemptotent is confusing in this context. -bool isIdempotentRMW(AtomicRMWInst& RMWI) { +static bool isIdempotentRMW(AtomicRMWInst &RMWI) { if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand())) switch(RMWI.getOperation()) { case AtomicRMWInst::FAdd: // -0.0 @@ -59,7 +58,7 @@ bool isIdempotentRMW(AtomicRMWInst& RMWI) { /// Return true if the given instruction always produces a value in memory /// equivalent to its value operand. -bool isSaturating(AtomicRMWInst& RMWI) { +static bool isSaturating(AtomicRMWInst &RMWI) { if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand())) switch (RMWI.getOperation()) { case AtomicRMWInst::FMax: @@ -98,7 +97,6 @@ bool isSaturating(AtomicRMWInst& RMWI) { return C->isMaxValue(false); }; } -} // namespace Instruction *InstCombinerImpl::visitAtomicRMWInst(AtomicRMWInst &RMWI) { diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 917004c..048cdf4 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -132,8 +132,6 @@ STATISTIC(NumReassoc , "Number of reassociations"); DEBUG_COUNTER(VisitCounter, "instcombine-visit", "Controls which instructions are visited"); -namespace llvm { - static cl::opt<bool> EnableCodeSinking("instcombine-code-sinking", cl::desc("Enable code sinking"), cl::init(true)); @@ -146,7 +144,9 @@ static cl::opt<unsigned> MaxArraySize("instcombine-maxarray-size", cl::init(1024), cl::desc("Maximum array size considered when doing a combine")); +namespace llvm { extern cl::opt<bool> ProfcheckDisableMetadataFixes; +} // end namespace llvm // FIXME: Remove this flag when it is no longer necessary to convert // llvm.dbg.declare to avoid inaccurate debug info. Setting this to false @@ -158,8 +158,6 @@ extern cl::opt<bool> ProfcheckDisableMetadataFixes; static cl::opt<unsigned> ShouldLowerDbgDeclare("instcombine-lower-dbg-declare", cl::Hidden, cl::init(true)); -} // end namespace llvm - std::optional<Instruction *> InstCombiner::targetInstCombineIntrinsic(IntrinsicInst &II) { // Handle target specific intrinsics diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp index f0e2369..b4d816e 100644 --- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp +++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/TableGen/CodeGenHelpers.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" @@ -30,26 +31,10 @@ using namespace llvm; namespace { -// Simple RAII helper for defining ifdef-undef-endif scopes. -class IfDefScope { -public: - IfDefScope(StringRef Name, raw_ostream &OS) : Name(Name), OS(OS) { - OS << "#ifdef " << Name << "\n" - << "#undef " << Name << "\n"; - } - - ~IfDefScope() { OS << "\n#endif // " << Name << "\n\n"; } - -private: - StringRef Name; - raw_ostream &OS; -}; -} // namespace - -namespace { enum class Frontend { LLVM, Flang, Clang }; +} // namespace -StringRef getFESpelling(Frontend FE) { +static StringRef getFESpelling(Frontend FE) { switch (FE) { case Frontend::LLVM: return "llvm"; @@ -60,7 +45,6 @@ StringRef getFESpelling(Frontend FE) { } llvm_unreachable("unknown FE kind"); } -} // namespace // Get the full namespace qualifier for the directive language. static std::string getQualifier(const DirectiveLanguage &DirLang, @@ -297,13 +281,8 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) { OS << "#include <cstddef>\n"; // for size_t OS << "#include <utility>\n"; // for std::pair OS << "\n"; - OS << "namespace llvm {\n"; - - // Open namespaces defined in the directive language - SmallVector<StringRef, 2> Namespaces; - SplitString(DirLang.getCppNamespace(), Namespaces, "::"); - for (auto Ns : Namespaces) - OS << "namespace " << Ns << " {\n"; + NamespaceEmitter LlvmNS(OS, "llvm"); + NamespaceEmitter DirLangNS(OS, DirLang.getCppNamespace()); if (DirLang.hasEnableBitmaskEnumInNamespace()) OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n"; @@ -380,9 +359,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) { OS << "\n"; } - // Closing namespaces - for (auto Ns : reverse(Namespaces)) - OS << "} // namespace " << Ns << "\n"; + DirLangNS.close(); // These specializations need to be in ::llvm. for (StringRef Enum : {"Association", "Category", "Directive", "Clause"}) { @@ -392,9 +369,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) { OS << " static constexpr bool is_iterable = true;\n"; OS << "};\n"; } - - OS << "} // namespace llvm\n"; - + LlvmNS.close(); OS << "#endif // LLVM_" << Lang << "_INC\n"; } @@ -971,11 +946,10 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang, std::string IfDefName{"GEN_"}; IfDefName += getFESpelling(FE).upper(); IfDefName += "_DIRECTIVE_CLAUSE_SETS"; - IfDefScope Scope(IfDefName, OS); + IfDefEmitter Scope(OS, IfDefName); StringRef Namespace = getFESpelling(FE == Frontend::Flang ? Frontend::LLVM : FE); - OS << "\n"; // The namespace has to be different for clang vs flang, as 2 structs with the // same name but different layout is UB. So just put the 'clang' on in the // clang namespace. @@ -1016,9 +990,8 @@ static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang, std::string IfDefName{"GEN_"}; IfDefName += getFESpelling(FE).upper(); IfDefName += "_DIRECTIVE_CLAUSE_MAP"; - IfDefScope Scope(IfDefName, OS); + IfDefEmitter Scope(OS, IfDefName); - OS << "\n"; OS << "{\n"; // The namespace has to be different for clang vs flang, as 2 structs with the @@ -1062,9 +1035,7 @@ static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang, static void generateFlangClauseParserClass(const DirectiveLanguage &DirLang, raw_ostream &OS) { - IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES", OS); - - OS << "\n"; + IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_PARSER_CLASSES"); for (const Clause Clause : DirLang.getClauses()) { if (!Clause.getFlangClass().empty()) { @@ -1089,9 +1060,8 @@ static void generateFlangClauseParserClass(const DirectiveLanguage &DirLang, static void generateFlangClauseParserClassList(const DirectiveLanguage &DirLang, raw_ostream &OS) { - IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST", OS); + IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST"); - OS << "\n"; interleaveComma(DirLang.getClauses(), OS, [&](const Record *C) { Clause Clause(C); OS << Clause.getFormattedParserClassName() << "\n"; @@ -1102,9 +1072,8 @@ static void generateFlangClauseParserClassList(const DirectiveLanguage &DirLang, static void generateFlangClauseDump(const DirectiveLanguage &DirLang, raw_ostream &OS) { - IfDefScope Scope("GEN_FLANG_DUMP_PARSE_TREE_CLAUSES", OS); + IfDefEmitter Scope(OS, "GEN_FLANG_DUMP_PARSE_TREE_CLAUSES"); - OS << "\n"; for (const Clause Clause : DirLang.getClauses()) { OS << "NODE(" << DirLang.getFlangClauseBaseClass() << ", " << Clause.getFormattedParserClassName() << ")\n"; @@ -1116,10 +1085,9 @@ static void generateFlangClauseDump(const DirectiveLanguage &DirLang, static void generateFlangClauseUnparse(const DirectiveLanguage &DirLang, raw_ostream &OS) { - IfDefScope Scope("GEN_FLANG_CLAUSE_UNPARSE", OS); + IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_UNPARSE"); StringRef Base = DirLang.getFlangClauseBaseClass(); - OS << "\n"; for (const Clause Clause : DirLang.getClauses()) { if (Clause.skipFlangUnparser()) @@ -1172,9 +1140,8 @@ static void generateFlangClauseUnparse(const DirectiveLanguage &DirLang, static void generateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang, raw_ostream &OS) { - IfDefScope Scope("GEN_FLANG_CLAUSE_CHECK_ENTER", OS); + IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_CHECK_ENTER"); - OS << "\n"; for (const Clause Clause : DirLang.getClauses()) { OS << "void Enter(const parser::" << DirLang.getFlangClauseBaseClass() << "::" << Clause.getFormattedParserClassName() << " &);\n"; @@ -1186,12 +1153,11 @@ static void generateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang, static void generateFlangClauseParserKindMap(const DirectiveLanguage &DirLang, raw_ostream &OS) { - IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_KIND_MAP", OS); + IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_PARSER_KIND_MAP"); StringRef Prefix = DirLang.getClausePrefix(); std::string Qual = getQualifier(DirLang); - OS << "\n"; for (const Record *R : DirLang.getClauses()) { Clause C(R); OS << "if constexpr (std::is_same_v<A, parser::" @@ -1216,11 +1182,10 @@ static void generateFlangClausesParser(const DirectiveLanguage &DirLang, llvm::sort(Names, [](const auto &A, const auto &B) { return A.second.Name > B.second.Name; }); - IfDefScope Scope("GEN_FLANG_CLAUSES_PARSER", OS); + IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSES_PARSER"); StringRef Base = DirLang.getFlangClauseBaseClass(); unsigned LastIndex = Names.size() - 1; - OS << "\n"; OS << "TYPE_PARSER(\n"; for (auto [Index, RecSp] : llvm::enumerate(Names)) { auto [R, S] = RecSp; @@ -1313,10 +1278,9 @@ static void emitDirectivesFlangImpl(const DirectiveLanguage &DirLang, static void generateClauseClassMacro(const DirectiveLanguage &DirLang, raw_ostream &OS) { // Generate macros style information for legacy code in clang - IfDefScope Scope("GEN_CLANG_CLAUSE_CLASS", OS); + IfDefEmitter Scope(OS, "GEN_CLANG_CLAUSE_CLASS"); StringRef Prefix = DirLang.getClausePrefix(); - OS << "\n"; OS << "#ifndef CLAUSE\n"; OS << "#define CLAUSE(Enum, Str, Implicit)\n"; @@ -1375,12 +1339,11 @@ static void generateClauseClassMacro(const DirectiveLanguage &DirLang, // language. This code can be included in library. void emitDirectivesBasicImpl(const DirectiveLanguage &DirLang, raw_ostream &OS) { - IfDefScope Scope("GEN_DIRECTIVES_IMPL", OS); + IfDefEmitter Scope(OS, "GEN_DIRECTIVES_IMPL"); StringRef DPrefix = DirLang.getDirectivePrefix(); StringRef CPrefix = DirLang.getClausePrefix(); - OS << "\n"; OS << "#include \"llvm/Frontend/Directive/Spelling.h\"\n"; OS << "#include \"llvm/Support/ErrorHandling.h\"\n"; OS << "#include <utility>\n"; diff --git a/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp index 6b723bc..e2b5241 100644 --- a/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp +++ b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "TargetFeaturesEmitter.h" +#include "llvm/TableGen/CodeGenHelpers.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/TableGenBackend.h" #include "llvm/TargetParser/SubtargetFeature.h" @@ -43,7 +44,7 @@ FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) { PrintFatalError( "Too many subtarget features! Bump MAX_SUBTARGET_FEATURES."); - OS << "namespace " << Target << " {\n"; + NamespaceEmitter NS(OS, Target); OS << "enum {\n"; @@ -58,9 +59,8 @@ FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) { OS << " " << "NumSubtargetFeatures = " << N << "\n"; - // Close enumeration and namespace + // Close enumeration. OS << "};\n"; - OS << "} // end namespace " << Target << "\n"; return FeatureMap; } @@ -149,25 +149,23 @@ void TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS, void TargetFeaturesEmitter::run(raw_ostream &OS) { OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n"; - OS << "\n#ifdef GET_SUBTARGETFEATURES_ENUM\n"; - OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n"; - - OS << "namespace llvm {\n"; - auto FeatureMap = enumeration(OS); - OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n"; + FeatureMapTy FeatureMap; + { + IfDefEmitter IfDef(OS, "GET_SUBTARGETFEATURES_ENUM"); + NamespaceEmitter NS(OS, "llvm"); + FeatureMap = enumeration(OS); + } - OS << "\n#ifdef GET_SUBTARGETFEATURES_KV\n"; - OS << "#undef GET_SUBTARGETFEATURES_KV\n\n"; + { + IfDefEmitter IfDef(OS, "GET_SUBTARGETFEATURES_KV"); + NamespaceEmitter NS(OS, "llvm"); - OS << "namespace llvm {\n"; - printFeatureKeyValues(OS, FeatureMap); - OS << "\n"; + printFeatureKeyValues(OS, FeatureMap); + OS << "\n"; - printCPUKeyValues(OS, FeatureMap); - OS << "\n"; - OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n"; + printCPUKeyValues(OS, FeatureMap); + OS << "\n"; + } } static TableGen::Emitter::OptClass<TargetFeaturesEmitter> diff --git a/llvm/utils/TableGen/CompressInstEmitter.cpp b/llvm/utils/TableGen/CompressInstEmitter.cpp index ccf8385..d8c5ca7 100644 --- a/llvm/utils/TableGen/CompressInstEmitter.cpp +++ b/llvm/utils/TableGen/CompressInstEmitter.cpp @@ -167,7 +167,7 @@ bool CompressInstEmitter::validateRegister(const Record *Reg, assert(RegClass->isSubClassOf("RegisterClass") && "RegClass record should be a RegisterClass"); const CodeGenRegisterClass &RC = Target.getRegisterClass(RegClass); - const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower()); + const CodeGenRegister *R = Target.getRegBank().getReg(Reg); assert(R != nullptr && "Register not defined!!"); return RC.contains(R); } diff --git a/mlir/include/mlir/TableGen/CodeGenHelpers.h b/mlir/include/mlir/TableGen/CodeGenHelpers.h index cf14f65..252da21 100644 --- a/mlir/include/mlir/TableGen/CodeGenHelpers.h +++ b/mlir/include/mlir/TableGen/CodeGenHelpers.h @@ -1,3 +1,4 @@ +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -20,6 +21,8 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/TableGen/CodeGenHelpers.h" +#include <utility> namespace llvm { class RecordKeeper; @@ -36,46 +39,17 @@ std::string strfmt(const char *fmt, Parameters &&...parameters) { return llvm::formatv(fmt, std::forward<Parameters>(parameters)...).str(); } -// Simple RAII helper for defining ifdef-undef-endif scopes. -class IfDefScope { -public: - IfDefScope(llvm::StringRef name, llvm::raw_ostream &os) - : name(name.str()), os(os) { - os << "#ifdef " << name << "\n" - << "#undef " << name << "\n\n"; - } - ~IfDefScope() { os << "\n#endif // " << name << "\n\n"; } - -private: - std::string name; - llvm::raw_ostream &os; -}; - -// A helper RAII class to emit nested namespaces for this op. -class NamespaceEmitter { +// A helper RAII class to emit nested namespaces for a dialect. +class DialectNamespaceEmitter { public: - NamespaceEmitter(raw_ostream &os, const Dialect &dialect) : os(os) { + DialectNamespaceEmitter(raw_ostream &os, const Dialect &dialect) { if (!dialect) return; - emitNamespaceStarts(os, dialect.getCppNamespace()); - } - NamespaceEmitter(raw_ostream &os, StringRef cppNamespace) : os(os) { - emitNamespaceStarts(os, cppNamespace); - } - - ~NamespaceEmitter() { - for (StringRef ns : llvm::reverse(namespaces)) - os << "} // namespace " << ns << "\n"; + nsEmitter.emplace(os, dialect.getCppNamespace()); } private: - void emitNamespaceStarts(raw_ostream &os, StringRef cppNamespace) { - llvm::SplitString(cppNamespace, namespaces, "::"); - for (StringRef ns : namespaces) - os << "namespace " << ns << " {\n"; - } - raw_ostream &os; - SmallVector<StringRef, 2> namespaces; + std::optional<llvm::NamespaceEmitter> nsEmitter; }; /// This class deduplicates shared operation verification code by emitting diff --git a/mlir/include/mlir/TableGen/Dialect.h b/mlir/include/mlir/TableGen/Dialect.h index ea8f405..37c6427a 100644 --- a/mlir/include/mlir/TableGen/Dialect.h +++ b/mlir/include/mlir/TableGen/Dialect.h @@ -107,6 +107,7 @@ public: // Returns whether the dialect is defined. explicit operator bool() const { return def != nullptr; } + bool isDefined() const { return def != nullptr; } private: const llvm::Record *def; diff --git a/mlir/lib/TableGen/CodeGenHelpers.cpp b/mlir/lib/TableGen/CodeGenHelpers.cpp index 2c119fd..cb90ef8 100644 --- a/mlir/lib/TableGen/CodeGenHelpers.cpp +++ b/mlir/lib/TableGen/CodeGenHelpers.cpp @@ -16,6 +16,7 @@ #include "mlir/TableGen/Pattern.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" +#include "llvm/TableGen/CodeGenHelpers.h" #include "llvm/TableGen/Record.h" using namespace llvm; diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp index b911565..06ef396 100644 --- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp +++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp @@ -10,12 +10,12 @@ #include "CppGenUtilities.h" #include "mlir/TableGen/AttrOrTypeDef.h" #include "mlir/TableGen/Class.h" -#include "mlir/TableGen/CodeGenHelpers.h" #include "mlir/TableGen/Format.h" #include "mlir/TableGen/GenInfo.h" #include "mlir/TableGen/Interfaces.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/CommandLine.h" +#include "llvm/TableGen/CodeGenHelpers.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/TableGenBackend.h" @@ -71,14 +71,14 @@ public: void emitDecl(raw_ostream &os) const { if (storageCls && def.genStorageClass()) { - NamespaceEmitter ns(os, def.getStorageNamespace()); + llvm::NamespaceEmitter ns(os, def.getStorageNamespace()); os << "struct " << def.getStorageClassName() << ";\n"; } defCls.writeDeclTo(os); } void emitDef(raw_ostream &os) const { if (storageCls && def.genStorageClass()) { - NamespaceEmitter ns(os, def.getStorageNamespace()); + llvm::NamespaceEmitter ns(os, def.getStorageNamespace()); storageCls->writeDeclTo(os); // everything is inline } defCls.writeDefTo(os); @@ -850,7 +850,7 @@ class AsmPrinter; bool DefGenerator::emitDecls(StringRef selectedDialect) { emitSourceFileHeader((defType + "Def Declarations").str(), os); - IfDefScope scope("GET_" + defType.upper() + "DEF_CLASSES", os); + llvm::IfDefEmitter scope(os, "GET_" + defType.upper() + "DEF_CLASSES"); // Output the common "header". os << typeDefDeclHeader; @@ -860,7 +860,7 @@ bool DefGenerator::emitDecls(StringRef selectedDialect) { if (defs.empty()) return false; { - NamespaceEmitter nsEmitter(os, defs.front().getDialect()); + DialectNamespaceEmitter nsEmitter(os, defs.front().getDialect()); // Declare all the def classes first (in case they reference each other). for (const AttrOrTypeDef &def : defs) { @@ -892,7 +892,7 @@ bool DefGenerator::emitDecls(StringRef selectedDialect) { //===----------------------------------------------------------------------===// void DefGenerator::emitTypeDefList(ArrayRef<AttrOrTypeDef> defs) { - IfDefScope scope("GET_" + defType.upper() + "DEF_LIST", os); + llvm::IfDefEmitter scope(os, "GET_" + defType.upper() + "DEF_LIST"); auto interleaveFn = [&](const AttrOrTypeDef &def) { os << def.getDialect().getCppNamespace() << "::" << def.getCppClassName(); }; @@ -1083,11 +1083,11 @@ bool DefGenerator::emitDefs(StringRef selectedDialect) { return false; emitTypeDefList(defs); - IfDefScope scope("GET_" + defType.upper() + "DEF_CLASSES", os); + llvm::IfDefEmitter scope(os, "GET_" + defType.upper() + "DEF_CLASSES"); emitParsePrintDispatch(defs); for (const AttrOrTypeDef &def : defs) { { - NamespaceEmitter ns(os, def.getDialect()); + DialectNamespaceEmitter ns(os, def.getDialect()); DefGen gen(def); gen.emitDef(os); } @@ -1102,7 +1102,7 @@ bool DefGenerator::emitDefs(StringRef selectedDialect) { // Emit the default parser/printer for Attributes if the dialect asked for it. if (isAttrGenerator && firstDialect.useDefaultAttributePrinterParser()) { - NamespaceEmitter nsEmitter(os, firstDialect); + DialectNamespaceEmitter nsEmitter(os, firstDialect); if (firstDialect.isExtensible()) { os << llvm::formatv(dialectDefaultAttrPrinterParserDispatch, firstDialect.getCppClassName(), @@ -1116,7 +1116,7 @@ bool DefGenerator::emitDefs(StringRef selectedDialect) { // Emit the default parser/printer for Types if the dialect asked for it. if (!isAttrGenerator && firstDialect.useDefaultTypePrinterParser()) { - NamespaceEmitter nsEmitter(os, firstDialect); + DialectNamespaceEmitter nsEmitter(os, firstDialect); if (firstDialect.isExtensible()) { os << llvm::formatv(dialectDefaultTypePrinterParserDispatch, firstDialect.getCppClassName(), diff --git a/mlir/tools/mlir-tblgen/DialectGen.cpp b/mlir/tools/mlir-tblgen/DialectGen.cpp index 02941ec..2e8810d 100644 --- a/mlir/tools/mlir-tblgen/DialectGen.cpp +++ b/mlir/tools/mlir-tblgen/DialectGen.cpp @@ -242,7 +242,7 @@ static const char *const discardableAttrHelperDecl = R"( static void emitDialectDecl(Dialect &dialect, raw_ostream &os) { // Emit all nested namespaces. { - NamespaceEmitter nsEmitter(os, dialect); + DialectNamespaceEmitter nsEmitter(os, dialect); // Emit the start of the decl. std::string cppName = dialect.getCppClassName(); @@ -358,7 +358,7 @@ static void emitDialectDef(Dialect &dialect, const RecordKeeper &records, << "::" << cppClassName << ")\n"; // Emit all nested namespaces. - NamespaceEmitter nsEmitter(os, dialect); + DialectNamespaceEmitter nsEmitter(os, dialect); /// Build the list of dependent dialects. std::string dependentDialectRegistrations; diff --git a/mlir/tools/mlir-tblgen/OmpOpGen.cpp b/mlir/tools/mlir-tblgen/OmpOpGen.cpp index 91bc61b..e1be11a 100644 --- a/mlir/tools/mlir-tblgen/OmpOpGen.cpp +++ b/mlir/tools/mlir-tblgen/OmpOpGen.cpp @@ -342,7 +342,7 @@ static bool verifyDecls(const RecordKeeper &records, raw_ostream &) { /// structures according to the `clauses` argument of each definition deriving /// from `OpenMP_Op`. static bool genClauseOps(const RecordKeeper &records, raw_ostream &os) { - mlir::tblgen::NamespaceEmitter ns(os, "mlir::omp"); + llvm::NamespaceEmitter ns(os, "mlir::omp"); for (const Record *clause : records.getAllDerivedDefinitions("OpenMP_Clause")) genClauseOpsStruct(clause, os); diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp index 7e8e559..c3420d4 100644 --- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/CodeGenHelpers.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" @@ -4855,7 +4856,7 @@ static void emitOpClassDecls(const RecordKeeper &records, } // Emit the op class declarations. - IfDefScope scope("GET_OP_CLASSES", os); + IfDefEmitter scope(os, "GET_OP_CLASSES"); if (defs.empty()) return; StaticVerifierFunctionEmitter staticVerifierEmitter(os, records); @@ -4898,7 +4899,7 @@ static bool emitOpDecls(const RecordKeeper &records, raw_ostream &os) { return false; Dialect dialect = Operator(defs.front()).getDialect(); - NamespaceEmitter ns(os, dialect); + DialectNamespaceEmitter ns(os, dialect); const char *const opRegistrationHook = "void register{0}Operations{1}({2}::{0} *dialect);\n"; @@ -4921,7 +4922,7 @@ static void emitOpDefShard(const RecordKeeper &records, std::string shardGuard = "GET_OP_DEFS_"; std::string indexStr = std::to_string(shardIndex); shardGuard += indexStr; - IfDefScope scope(shardGuard, os); + IfDefEmitter scope(os, shardGuard); // Emit the op registration hook in the first shard. const char *const opRegistrationHook = @@ -4962,14 +4963,14 @@ static bool emitOpDefs(const RecordKeeper &records, raw_ostream &os) { // If no shard was requested, emit the regular op list and class definitions. if (shardedDefs.size() == 1) { { - IfDefScope scope("GET_OP_LIST", os); + IfDefEmitter scope(os, "GET_OP_LIST"); interleave( defs, os, [&](const Record *def) { os << Operator(def).getQualCppClassName(); }, ",\n"); } { - IfDefScope scope("GET_OP_CLASSES", os); + IfDefEmitter scope(os, "GET_OP_CLASSES"); emitOpClassDefs(records, defs, os); } return false; diff --git a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp index 41ffdfc..3ead2f0 100644 --- a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp +++ b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp @@ -50,7 +50,6 @@ using mlir::tblgen::EnumCase; using mlir::tblgen::EnumInfo; using mlir::tblgen::NamedAttribute; using mlir::tblgen::NamedTypeConstraint; -using mlir::tblgen::NamespaceEmitter; using mlir::tblgen::Operator; //===----------------------------------------------------------------------===// @@ -261,7 +260,7 @@ static void emitInterfaceDecl(const Availability &availability, std::string(formatv("{0}Traits", interfaceName)); StringRef cppNamespace = availability.getInterfaceClassNamespace(); - NamespaceEmitter nsEmitter(os, cppNamespace); + llvm::NamespaceEmitter nsEmitter(os, cppNamespace); os << "class " << interfaceName << ";\n\n"; // Emit the traits struct containing the concept and model declarations. |