From 97f4083fe00b78d43a168816f2fecad1dedac944 Mon Sep 17 00:00:00 2001 From: ghehg Date: Thu, 30 May 2024 11:51:20 -0700 Subject: [PATCH] introduce CIRGlobalValueInterface --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 23 +++++------- .../clang/CIR/Interfaces/CIROpInterfaces.td | 35 ++++++++++++++++--- clang/lib/CIR/CodeGen/CIRGenCXX.cpp | 11 +++--- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 17 ++++++--- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 26 +++++++------- 5 files changed, 69 insertions(+), 43 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 1c4624ef35b5..769256896926 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1872,7 +1872,10 @@ def TLSModel : I32EnumAttr< let cppNamespace = "::mlir::cir"; } -def GlobalOp : CIR_Op<"global", [Symbol, DeclareOpInterfaceMethods, NoRegionArguments]> { +def GlobalOp : CIR_Op<"global", + [DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods, + NoRegionArguments]> { let summary = "Declares or defines a global variable"; let description = [{ The `cir.global` operation declares or defines a named global variable. @@ -1933,13 +1936,6 @@ def GlobalOp : CIR_Op<"global", [Symbol, DeclareOpInterfaceMethods { def FuncOp : CIR_Op<"func", [ AutomaticAllocationScope, CallableOpInterface, FunctionOpInterface, - IsolatedFromAbove, Symbol + DeclareOpInterfaceMethods, + IsolatedFromAbove ]> { let summary = "Declare or define a function"; let description = [{ @@ -2727,12 +2724,8 @@ def FuncOp : CIR_Op<"func", [ bool isDeclaration(); - // FIXME: should be shared with GlobalOp extra declaration. - bool isDeclarationForLinker() { - if (mlir::cir::isAvailableExternallyLinkage(getLinkage())) - return true; - - return isDeclaration(); + bool hasAvailableExternallyLinkage() { + return mlir::cir::isAvailableExternallyLinkage(getLinkage()); } }]; diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td index b08e07a63d67..8f1c63e1b024 100644 --- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td +++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td @@ -10,24 +10,49 @@ #define MLIR_CIR_OP_INTERFACES include "mlir/IR/OpBase.td" +include "mlir/IR/SymbolInterfaces.td" include "mlir/Interfaces/CallInterfaces.td" let cppNamespace = "::mlir::cir" in { // The CIRCallOpInterface must be used instead of CallOpInterface when looking // at arguments and other bits of CallOp. This creates a level of abstraction // that's useful for handling indirect calls and other details. - def CIRCallOpInterface : OpInterface<"CIRCallOpInterface", [CallOpInterface]> { + def CIRCallOpInterface + : OpInterface<"CIRCallOpInterface", [CallOpInterface]> { let methods = [ InterfaceMethod<"", "mlir::Operation::operand_iterator", "arg_operand_begin", (ins)>, InterfaceMethod<"", "mlir::Operation::operand_iterator", "arg_operand_end", (ins)>, InterfaceMethod< - "Return the operand at index 'i', accounts for indirect call or " - "exception info", "mlir::Value", "getArgOperand", (ins "unsigned":$i)>, + "Return the operand at index 'i', accounts for indirect call or " + "exception info", + "mlir::Value", "getArgOperand", + (ins "unsigned" + : $i)>, InterfaceMethod< - "Return the number of operands, accounts for indirect call or " - "exception info", "unsigned", "getNumArgOperands", (ins)>, + "Return the number of operands, accounts for indirect call or " + "exception info", + "unsigned", "getNumArgOperands", (ins)>, + ]; + } + + def CIRGlobalValueInterface + : OpInterface<"CIRGlobalValueInterface", [Symbol]> { + + let methods = [ + InterfaceMethod<"", + "bool", "hasAvailableExternallyLinkage", (ins), [{}], + /*defaultImplementation=*/[{ return false; }] + >, + InterfaceMethod<"", + "bool", "isDeclarationForLinker", (ins), [{}], + /*defaultImplementation=*/[{ + if ($_op.hasAvailableExternallyLinkage()) + return true; + return $_op.isDeclaration(); + }] + >, ]; } diff --git a/clang/lib/CIR/CodeGen/CIRGenCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp index 31dba6be75eb..568628c5bc9e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp @@ -122,18 +122,19 @@ bool CIRGenModule::tryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { // Check if we have it already. StringRef MangledName = getMangledName(AliasDecl); auto Entry = getGlobalValue(MangledName); - auto fnOp = dyn_cast_or_null(Entry); - if (Entry && fnOp && !fnOp.isDeclaration()) + auto globalValue = dyn_cast(Entry); + if (Entry && globalValue && !globalValue.isDeclaration()) return false; if (Replacements.count(MangledName)) return false; - assert(fnOp && "only knows how to handle FuncOp"); + assert(globalValue && "only knows how to handle GlobalValue"); [[maybe_unused]] auto AliasValueType = getTypes().GetFunctionType(AliasDecl); // Find the referent. auto Aliasee = cast(GetAddrOfGlobal(TargetDecl)); - + auto AliaseeGV = dyn_cast_or_null( + GetAddrOfGlobal(TargetDecl)); // Instead of creating as alias to a linkonce_odr, replace all of the uses // of the aliasee. if (mlir::cir::isDiscardableIfUnused(Linkage) && @@ -161,7 +162,7 @@ bool CIRGenModule::tryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { // is // avaialable_externally, don't emit an alias. We can't emit aliases to // declarations; that's just not how aliases work. - if (Aliasee.isDeclarationForLinker()) + if (AliaseeGV && AliaseeGV.isDeclarationForLinker()) return true; // Don't create an alias to a linker weak symbol. This avoids producing diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 8f300532454a..35b20d5143ec 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -448,10 +448,14 @@ static void emitConstructorDestructorAlias(CIRGenModule &CGM, // Does this function alias already exists? StringRef MangledName = CGM.getMangledName(AliasDecl); + auto globalValue = dyn_cast_or_null( + CGM.getGlobalValue(MangledName)); + if (globalValue && !globalValue.isDeclaration()) { + return; + } + auto Entry = dyn_cast_or_null(CGM.getGlobalValue(MangledName)); - if (Entry && !Entry.isDeclaration()) - return; // Retrieve aliasee info. auto Aliasee = @@ -2051,19 +2055,22 @@ void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &CGVT, // EmitFundamentalRTTIDescriptors(RD); } + auto VTableAsGlobalValue = + dyn_cast(*VTable); + assert(VTableAsGlobalValue && "VTable must support CIRGlobalValueInterface"); + bool isDeclarationForLinker = VTableAsGlobalValue.isDeclarationForLinker(); // Always emit type metadata on non-available_externally definitions, and on // available_externally definitions if we are performing whole program // devirtualization. For WPD we need the type metadata on all vtable // definitions to ensure we associate derived classes with base classes // defined in headers but with a strong definition only in a shared // library. - if (!VTable.isDeclarationForLinker() || - CGM.getCodeGenOpts().WholeProgramVTables) { + if (!isDeclarationForLinker || CGM.getCodeGenOpts().WholeProgramVTables) { CGM.buildVTableTypeMetadata(RD, VTable, VTLayout); // For available_externally definitions, add the vtable to // @llvm.compiler.used so that it isn't deleted before whole program // analysis. - if (VTable.isDeclarationForLinker()) { + if (isDeclarationForLinker) { llvm_unreachable("NYI"); assert(CGM.getCodeGenOpts().WholeProgramVTables); assert(!UnimplementedFeature::addCompilerUsedGlobal()); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 409511ecf247..fd98bcbcce12 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -469,11 +469,12 @@ void CIRGenModule::buildGlobalFunctionDefinition(GlobalDecl GD, Op = GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/true, ForDefinition); - auto Fn = cast(Op); - // Already emitted. - if (!Fn.isDeclaration()) + auto globalVal = dyn_cast_or_null(Op); + if (globalVal && !globalVal.isDeclaration()) { + // Already emitted. return; - + } + auto Fn = cast(Op); setFunctionLinkage(GD, Fn); setGVProperties(Op, D); // TODO(cir): MaubeHandleStaticInExternC @@ -2434,18 +2435,17 @@ void CIRGenModule::buildGlobalDecl(clang::GlobalDecl &D) { // ways (e.g. by an extern inline function acquiring a strong function // redefinition). Just ignore those cases. // TODO: Not sure what to map this to for MLIR - if (auto Fn = dyn_cast(Op)) - if (!Fn.isDeclaration()) - return; - - // TODO(cir): create a global value trait that allow us to uniformly handle - // global variables and functions. + auto globalValueOp = Op; if (auto Gv = dyn_cast(Op)) { auto *result = mlir::SymbolTable::lookupSymbolIn(getModule(), Gv.getNameAttr()); - if (auto globalOp = dyn_cast(result)) - if (!globalOp.isDeclaration()) - return; + globalValueOp = result; + } + + if (auto cirGlobalValue = + dyn_cast(globalValueOp)) { + if (!cirGlobalValue.isDeclaration()) + return; } // If this is OpenMP, check if it is legal to emit this global normally.