@@ -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"
@@ -278,6 +280,59 @@ def ScopeOp : CIR_Op<"scope", [
278280// GlobalOp
279281//===----------------------------------------------------------------------===//
280282
283+ // Linkage types. This is currently a replay of llvm/IR/GlobalValue.h, this is
284+ // currently handy as part of forwarding appropriate linkage types for LLVM
285+ // lowering, specially useful for C++ support.
286+
287+ // Externally visible function
288+ def Global_ExternalLinkage :
289+ I32EnumAttrCase<"ExternalLinkage", 0, "external">;
290+ // Available for inspection, not emission.
291+ def Global_AvailableExternallyLinkage :
292+ I32EnumAttrCase<"AvailableExternallyLinkage", 1, "available_externally">;
293+ // Keep one copy of function when linking (inline)
294+ def Global_LinkOnceAnyLinkage :
295+ I32EnumAttrCase<"LinkOnceAnyLinkage", 2, "linkonce">;
296+ // Same, but only replaced by something equivalent.
297+ def Global_LinkOnceODRLinkage :
298+ I32EnumAttrCase<"LinkOnceODRLinkage", 3, "linkonce_odr">;
299+ // Keep one copy of named function when linking (weak)
300+ def Global_WeakAnyLinkage :
301+ I32EnumAttrCase<"WeakAnyLinkage", 4, "weak">;
302+ // Same, but only replaced by something equivalent.
303+ def Global_WeakODRLinkage :
304+ I32EnumAttrCase<"WeakODRLinkage", 5, "weak_odr">;
305+ // TODO: should we add something like appending linkage too?
306+ // Special purpose, only applies to global arrays
307+ // def Global_AppendingLinkage :
308+ // I32EnumAttrCase<"AppendingLinkage", 6, "appending">;
309+ // Rename collisions when linking (static functions).
310+ def Global_InternalLinkage :
311+ I32EnumAttrCase<"InternalLinkage", 7, "internal">;
312+ // Like Internal, but omit from symbol table, prefix it with
313+ // "cir_" to prevent clash with MLIR's symbol "private".
314+ def Global_PrivateLinkage :
315+ I32EnumAttrCase<"PrivateLinkage", 8, "cir_private">;
316+ // ExternalWeak linkage description.
317+ def Global_ExternalWeakLinkage :
318+ I32EnumAttrCase<"ExternalWeakLinkage", 9, "extern_weak">;
319+ // Tentative definitions.
320+ def Global_CommonLinkage :
321+ I32EnumAttrCase<"CommonLinkage", 10, "common">;
322+
323+ /// An enumeration for the kinds of linkage for global values.
324+ def GlobalLinkageKind : I32EnumAttr<
325+ "GlobalLinkageKind",
326+ "Linkage type/kind",
327+ [Global_ExternalLinkage, Global_AvailableExternallyLinkage,
328+ Global_LinkOnceAnyLinkage, Global_LinkOnceODRLinkage,
329+ Global_WeakAnyLinkage, Global_WeakODRLinkage,
330+ Global_InternalLinkage, Global_PrivateLinkage,
331+ Global_ExternalWeakLinkage, Global_CommonLinkage
332+ ]> {
333+ let cppNamespace = "::cir";
334+ }
335+
281336// TODO(CIR): For starters, cir.global has only name and type. The other
282337// properties of a global variable will be added over time as more of ClangIR
283338// is upstreamed.
@@ -289,12 +344,19 @@ def GlobalOp : CIR_Op<"global"> {
289344
290345 The backing memory for the variable is allocated statically and is
291346 described by the type of the variable.
347+
348+ The `linkage` tracks C/C++ linkage types, currently very similar to LLVM's.
292349 }];
293350
294- let arguments = (ins SymbolNameAttr:$sym_name, TypeAttr:$sym_type,
295- OptionalAttr<AnyAttr>:$initial_value);
351+ let arguments = (ins SymbolNameAttr:$sym_name,
352+ TypeAttr:$sym_type,
353+ Arg<GlobalLinkageKind, "linkage type">:$linkage,
354+ OptionalAttr<AnyAttr>:$initial_value,
355+ UnitAttr:$dsolocal);
296356
297357 let assemblyFormat = [{
358+ $linkage
359+ (`dsolocal` $dsolocal^)?
298360 $sym_name
299361 custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value)
300362 attr-dict
@@ -303,12 +365,25 @@ def GlobalOp : CIR_Op<"global"> {
303365 let extraClassDeclaration = [{
304366 bool isDeclaration() { return !getInitialValue(); }
305367 bool hasInitializer() { return !isDeclaration(); }
368+ bool hasAvailableExternallyLinkage() {
369+ return cir::isAvailableExternallyLinkage(getLinkage());
370+ }
371+ bool hasInternalLinkage() {
372+ return cir::isInternalLinkage(getLinkage());
373+ }
374+ /// Whether the definition of this global may be replaced at link time.
375+ bool isWeakForLinker() { return cir::isWeakForLinker(getLinkage()); }
376+ bool isDSOLocal() { return getDsolocal(); }
306377 }];
307378
308379 let skipDefaultBuilders = 1;
309380
310- let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name,
311- "mlir::Type":$sym_type)>];
381+ let builders = [OpBuilder<(ins
382+ "llvm::StringRef":$sym_name,
383+ "mlir::Type":$sym_type,
384+ // CIR defaults to external linkage.
385+ CArg<"cir::GlobalLinkageKind",
386+ "cir::GlobalLinkageKind::ExternalLinkage">:$linkage)>];
312387
313388 let hasVerifier = 1;
314389}
0 commit comments