Skip to content

Commit 710de09

Browse files
mmhaxlauko
andauthored
[CIR] Upstream global variable linkage types (llvm#129072)
This change implements variable linkage types in ClangIR except for common linkage which requires Comdat support. --------- Co-authored-by: Morris Hafner <mhafner@nvidia.com> Co-authored-by: Henrich Lauko <xlauko@mail.muni.cz>
1 parent 0efaad0 commit 710de09

23 files changed

+797
-111
lines changed

clang/include/clang/CIR/Dialect/IR/CIRDialect.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
3030
#include "clang/CIR/Dialect/IR/CIROpsDialect.h.inc"
31+
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
32+
#include "clang/CIR/Interfaces/CIROpInterfaces.h"
3133

3234
// TableGen'erated files for MLIR dialects require that a macro be defined when
3335
// they are included. GET_OP_CLASSES tells the file to define the classes for

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ include "clang/CIR/Dialect/IR/CIRDialect.td"
1818
include "clang/CIR/Dialect/IR/CIRTypes.td"
1919
include "clang/CIR/Dialect/IR/CIRAttrs.td"
2020

21+
include "clang/CIR/Interfaces/CIROpInterfaces.td"
22+
2123
include "mlir/IR/BuiltinAttributeInterfaces.td"
2224
include "mlir/IR/EnumAttr.td"
2325
include "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
@@ -459,8 +521,12 @@ def GlobalOp : CIR_Op<"global"> {
459521

460522
let skipDefaultBuilders = 1;
461523

462-
let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name,
463-
"mlir::Type":$sym_type)>];
524+
let builders = [OpBuilder<(ins
525+
"llvm::StringRef":$sym_name,
526+
"mlir::Type":$sym_type,
527+
// CIR defaults to external linkage.
528+
CArg<"cir::GlobalLinkageKind",
529+
"cir::GlobalLinkageKind::ExternalLinkage">:$linkage)>];
464530

465531
let hasVerifier = 1;
466532
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file declares the CIR enumerations.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef CLANG_CIR_DIALECT_IR_CIROPSENUMS_H
14+
#define CLANG_CIR_DIALECT_IR_CIROPSENUMS_H
15+
16+
#include "mlir/IR/BuiltinAttributes.h"
17+
#include "clang/CIR/Dialect/IR/CIROpsEnums.h.inc"
18+
19+
namespace cir {
20+
21+
static bool isExternalLinkage(GlobalLinkageKind linkage) {
22+
return linkage == GlobalLinkageKind::ExternalLinkage;
23+
}
24+
static bool isAvailableExternallyLinkage(GlobalLinkageKind linkage) {
25+
return linkage == GlobalLinkageKind::AvailableExternallyLinkage;
26+
}
27+
static bool isLinkOnceAnyLinkage(GlobalLinkageKind linkage) {
28+
return linkage == GlobalLinkageKind::LinkOnceAnyLinkage;
29+
}
30+
static bool isLinkOnceODRLinkage(GlobalLinkageKind linkage) {
31+
return linkage == GlobalLinkageKind::LinkOnceODRLinkage;
32+
}
33+
static bool isLinkOnceLinkage(GlobalLinkageKind linkage) {
34+
return isLinkOnceAnyLinkage(linkage) || isLinkOnceODRLinkage(linkage);
35+
}
36+
static bool isWeakAnyLinkage(GlobalLinkageKind linkage) {
37+
return linkage == GlobalLinkageKind::WeakAnyLinkage;
38+
}
39+
static bool isWeakODRLinkage(GlobalLinkageKind linkage) {
40+
return linkage == GlobalLinkageKind::WeakODRLinkage;
41+
}
42+
static bool isWeakLinkage(GlobalLinkageKind linkage) {
43+
return isWeakAnyLinkage(linkage) || isWeakODRLinkage(linkage);
44+
}
45+
static bool isInternalLinkage(GlobalLinkageKind linkage) {
46+
return linkage == GlobalLinkageKind::InternalLinkage;
47+
}
48+
static bool isPrivateLinkage(GlobalLinkageKind linkage) {
49+
return linkage == GlobalLinkageKind::PrivateLinkage;
50+
}
51+
static bool isLocalLinkage(GlobalLinkageKind linkage) {
52+
return isInternalLinkage(linkage) || isPrivateLinkage(linkage);
53+
}
54+
static bool isExternalWeakLinkage(GlobalLinkageKind linkage) {
55+
return linkage == GlobalLinkageKind::ExternalWeakLinkage;
56+
}
57+
LLVM_ATTRIBUTE_UNUSED static bool isCommonLinkage(GlobalLinkageKind linkage) {
58+
return linkage == GlobalLinkageKind::CommonLinkage;
59+
}
60+
LLVM_ATTRIBUTE_UNUSED static bool
61+
isValidDeclarationLinkage(GlobalLinkageKind linkage) {
62+
return isExternalWeakLinkage(linkage) || isExternalLinkage(linkage);
63+
}
64+
65+
/// Whether the definition of this global may be replaced by something
66+
/// non-equivalent at link time. For example, if a function has weak linkage
67+
/// then the code defining it may be replaced by different code.
68+
LLVM_ATTRIBUTE_UNUSED static bool
69+
isInterposableLinkage(GlobalLinkageKind linkage) {
70+
switch (linkage) {
71+
case GlobalLinkageKind::WeakAnyLinkage:
72+
case GlobalLinkageKind::LinkOnceAnyLinkage:
73+
case GlobalLinkageKind::CommonLinkage:
74+
case GlobalLinkageKind::ExternalWeakLinkage:
75+
return true;
76+
77+
case GlobalLinkageKind::AvailableExternallyLinkage:
78+
case GlobalLinkageKind::LinkOnceODRLinkage:
79+
case GlobalLinkageKind::WeakODRLinkage:
80+
// The above three cannot be overridden but can be de-refined.
81+
82+
case GlobalLinkageKind::ExternalLinkage:
83+
case GlobalLinkageKind::InternalLinkage:
84+
case GlobalLinkageKind::PrivateLinkage:
85+
return false;
86+
}
87+
llvm_unreachable("Fully covered switch above!");
88+
}
89+
90+
/// Whether the definition of this global may be discarded if it is not used
91+
/// in its compilation unit.
92+
LLVM_ATTRIBUTE_UNUSED static bool
93+
isDiscardableIfUnused(GlobalLinkageKind linkage) {
94+
return isLinkOnceLinkage(linkage) || isLocalLinkage(linkage) ||
95+
isAvailableExternallyLinkage(linkage);
96+
}
97+
98+
/// Whether the definition of this global may be replaced at link time. NB:
99+
/// Using this method outside of the code generators is almost always a
100+
/// mistake: when working at the IR level use isInterposable instead as it
101+
/// knows about ODR semantics.
102+
LLVM_ATTRIBUTE_UNUSED static bool isWeakForLinker(GlobalLinkageKind linkage) {
103+
return linkage == GlobalLinkageKind::WeakAnyLinkage ||
104+
linkage == GlobalLinkageKind::WeakODRLinkage ||
105+
linkage == GlobalLinkageKind::LinkOnceAnyLinkage ||
106+
linkage == GlobalLinkageKind::LinkOnceODRLinkage ||
107+
linkage == GlobalLinkageKind::CommonLinkage ||
108+
linkage == GlobalLinkageKind::ExternalWeakLinkage;
109+
}
110+
111+
LLVM_ATTRIBUTE_UNUSED static bool isValidLinkage(GlobalLinkageKind gl) {
112+
return isExternalLinkage(gl) || isLocalLinkage(gl) || isWeakLinkage(gl) ||
113+
isLinkOnceLinkage(gl);
114+
}
115+
116+
} // namespace cir
117+
118+
#endif // CLANG_CIR_DIALECT_IR_CIROPSENUMS_H

clang/include/clang/CIR/Dialect/IR/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ add_dependencies(mlir-headers MLIRCIROpsIncGen)
1616

1717
mlir_tablegen(CIROpsAttributes.h.inc -gen-attrdef-decls)
1818
mlir_tablegen(CIROpsAttributes.cpp.inc -gen-attrdef-defs)
19-
add_public_tablegen_target(MLIRCIRAttrsEnumsGen)
19+
mlir_tablegen(CIROpsEnums.h.inc -gen-enum-decls)
20+
mlir_tablegen(CIROpsEnums.cpp.inc -gen-enum-defs)
21+
add_public_tablegen_target(MLIRCIREnumsGen)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Defines the interface to CIR operations.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef CLANG_CIR_INTERFACES_CIR_OP_H
14+
#define CLANG_CIR_INTERFACES_CIR_OP_H
15+
16+
#include "mlir/IR/Attributes.h"
17+
#include "mlir/IR/Operation.h"
18+
#include "mlir/IR/Value.h"
19+
#include "mlir/Interfaces/CallInterfaces.h"
20+
21+
#include "clang/AST/Attr.h"
22+
#include "clang/AST/DeclTemplate.h"
23+
#include "clang/AST/Mangle.h"
24+
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
25+
26+
/// Include the generated interface declarations.
27+
#include "clang/CIR/Interfaces/CIROpInterfaces.h.inc"
28+
29+
#endif // CLANG_CIR_INTERFACES_CIR_OP_H

0 commit comments

Comments
 (0)