@@ -18,6 +18,8 @@ include "clang/CIR/Dialect/IR/CIRDialect.td"
1818include "clang/CIR/Dialect/IR/CIRTypes.td"
1919include "clang/CIR/Dialect/IR/CIRAttrs.td"
2020
21+ include "clang/CIR/Interfaces/CIROpInterfaces.td"
22+
2123include "mlir/IR/BuiltinAttributeInterfaces.td"
2224include "mlir/IR/EnumAttr.td"
2325include "mlir/IR/SymbolInterfaces.td"
@@ -430,6 +432,59 @@ def ScopeOp : CIR_Op<"scope", [
430432// GlobalOp
431433//===----------------------------------------------------------------------===//
432434
435+ // Linkage types. This is currently a replay of llvm/IR/GlobalValue.h, this is
436+ // currently handy as part of forwarding appropriate linkage types for LLVM
437+ // lowering, specially useful for C++ support.
438+
439+ // Externally visible function
440+ def Global_ExternalLinkage :
441+ I32EnumAttrCase<"ExternalLinkage", 0, "external">;
442+ // Available for inspection, not emission.
443+ def Global_AvailableExternallyLinkage :
444+ I32EnumAttrCase<"AvailableExternallyLinkage", 1, "available_externally">;
445+ // Keep one copy of function when linking (inline)
446+ def Global_LinkOnceAnyLinkage :
447+ I32EnumAttrCase<"LinkOnceAnyLinkage", 2, "linkonce">;
448+ // Same, but only replaced by something equivalent.
449+ def Global_LinkOnceODRLinkage :
450+ I32EnumAttrCase<"LinkOnceODRLinkage", 3, "linkonce_odr">;
451+ // Keep one copy of named function when linking (weak)
452+ def Global_WeakAnyLinkage :
453+ I32EnumAttrCase<"WeakAnyLinkage", 4, "weak">;
454+ // Same, but only replaced by something equivalent.
455+ def Global_WeakODRLinkage :
456+ I32EnumAttrCase<"WeakODRLinkage", 5, "weak_odr">;
457+ // TODO: should we add something like appending linkage too?
458+ // Special purpose, only applies to global arrays
459+ // def Global_AppendingLinkage :
460+ // I32EnumAttrCase<"AppendingLinkage", 6, "appending">;
461+ // Rename collisions when linking (static functions).
462+ def Global_InternalLinkage :
463+ I32EnumAttrCase<"InternalLinkage", 7, "internal">;
464+ // Like Internal, but omit from symbol table, prefix it with
465+ // "cir_" to prevent clash with MLIR's symbol "private".
466+ def Global_PrivateLinkage :
467+ I32EnumAttrCase<"PrivateLinkage", 8, "cir_private">;
468+ // ExternalWeak linkage description.
469+ def Global_ExternalWeakLinkage :
470+ I32EnumAttrCase<"ExternalWeakLinkage", 9, "extern_weak">;
471+ // Tentative definitions.
472+ def Global_CommonLinkage :
473+ I32EnumAttrCase<"CommonLinkage", 10, "common">;
474+
475+ /// An enumeration for the kinds of linkage for global values.
476+ def GlobalLinkageKind : I32EnumAttr<
477+ "GlobalLinkageKind",
478+ "Linkage type/kind",
479+ [Global_ExternalLinkage, Global_AvailableExternallyLinkage,
480+ Global_LinkOnceAnyLinkage, Global_LinkOnceODRLinkage,
481+ Global_WeakAnyLinkage, Global_WeakODRLinkage,
482+ Global_InternalLinkage, Global_PrivateLinkage,
483+ Global_ExternalWeakLinkage, Global_CommonLinkage
484+ ]> {
485+ let cppNamespace = "::cir";
486+ }
487+
433488// TODO(CIR): For starters, cir.global has only name and type. The other
434489// properties of a global variable will be added over time as more of ClangIR
435490// is upstreamed.
@@ -441,12 +496,19 @@ def GlobalOp : CIR_Op<"global"> {
441496
442497 The backing memory for the variable is allocated statically and is
443498 described by the type of the variable.
499+
500+ The `linkage` tracks C/C++ linkage types, currently very similar to LLVM's.
444501 }];
445502
446- let arguments = (ins SymbolNameAttr:$sym_name, TypeAttr:$sym_type,
447- OptionalAttr<AnyAttr>:$initial_value);
503+ let arguments = (ins SymbolNameAttr:$sym_name,
504+ TypeAttr:$sym_type,
505+ Arg<GlobalLinkageKind, "linkage type">:$linkage,
506+ OptionalAttr<AnyAttr>:$initial_value,
507+ UnitAttr:$dsolocal);
448508
449509 let assemblyFormat = [{
510+ $linkage
511+ (`dsolocal` $dsolocal^)?
450512 $sym_name
451513 custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value)
452514 attr-dict
@@ -455,12 +517,25 @@ def GlobalOp : CIR_Op<"global"> {
455517 let extraClassDeclaration = [{
456518 bool isDeclaration() { return !getInitialValue(); }
457519 bool hasInitializer() { return !isDeclaration(); }
520+ bool hasAvailableExternallyLinkage() {
521+ return cir::isAvailableExternallyLinkage(getLinkage());
522+ }
523+ bool hasInternalLinkage() {
524+ return cir::isInternalLinkage(getLinkage());
525+ }
526+ /// Whether the definition of this global may be replaced at link time.
527+ bool isWeakForLinker() { return cir::isWeakForLinker(getLinkage()); }
528+ bool isDSOLocal() { return getDsolocal(); }
458529 }];
459530
460531 let skipDefaultBuilders = 1;
461532
462- let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name,
463- "mlir::Type":$sym_type)>];
533+ let builders = [OpBuilder<(ins
534+ "llvm::StringRef":$sym_name,
535+ "mlir::Type":$sym_type,
536+ // CIR defaults to external linkage.
537+ CArg<"cir::GlobalLinkageKind",
538+ "cir::GlobalLinkageKind::ExternalLinkage">:$linkage)>];
464539
465540 let hasVerifier = 1;
466541}
0 commit comments