Skip to content

Commit b945378

Browse files
committed
[CIR] Upstream global variable linkage types
This change implements variable linkage types in ClangIR except for common linkage which requires Comdat support.
1 parent 1357279 commit b945378

File tree

19 files changed

+608
-41
lines changed

19 files changed

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

clang/include/clang/CIR/Interfaces/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
# directory which is not the case for CIR (and also FIR, both have similar
44
# workarounds).
55

6+
function(add_clang_mlir_op_interface interface)
7+
set(LLVM_TARGET_DEFINITIONS ${interface}.td)
8+
mlir_tablegen(${interface}.h.inc -gen-op-interface-decls)
9+
mlir_tablegen(${interface}.cpp.inc -gen-op-interface-defs)
10+
add_public_tablegen_target(MLIR${interface}IncGen)
11+
add_dependencies(mlir-generic-headers MLIR${interface}IncGen)
12+
endfunction()
13+
614
function(add_clang_mlir_type_interface interface)
715
set(LLVM_TARGET_DEFINITIONS ${interface}.td)
816
mlir_tablegen(${interface}.h.inc -gen-type-interface-decls)
@@ -11,4 +19,5 @@ function(add_clang_mlir_type_interface interface)
1119
add_dependencies(mlir-generic-headers MLIR${interface}IncGen)
1220
endfunction()
1321

22+
add_clang_mlir_op_interface(CIROpInterfaces)
1423
add_clang_mlir_type_interface(CIRFPTypeInterface)

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ struct MissingFeatures {
3636
static bool opGlobalConstant() { return false; }
3737
static bool opGlobalAlignment() { return false; }
3838
static bool opGlobalLinkage() { return false; }
39+
40+
static bool supportIFuncAttr() { return false; }
41+
static bool supportVisibility() { return false; }
42+
static bool supportComdat() { return false; }
3943
};
4044

4145
} // namespace cir

0 commit comments

Comments
 (0)