Skip to content

Commit 55f33fb

Browse files
committed
[CIR][CIRGen][LowerToLLVM] Support for LinkerOptions
1 parent 23dc430 commit 55f33fb

File tree

8 files changed

+101
-5
lines changed

8 files changed

+101
-5
lines changed

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5691,6 +5691,36 @@ def SignBitOp : CIR_Op<"signbit", [Pure]> {
56915691
}];
56925692
}
56935693

5694+
//===----------------------------------------------------------------------===//
5695+
// LinkerOptionsOp
5696+
//===----------------------------------------------------------------------===//
5697+
5698+
def LinkerOptionsOp : CIR_Op<"linker_options"> {
5699+
let summary = "Options to pass to the linker when the object file is linked";
5700+
let description = [{
5701+
Pass the given options to the linker when the resulting object file
5702+
is linked.
5703+
This is used extensively on Windows to determine the C runtime that the
5704+
object files should link against.
5705+
5706+
Examples:
5707+
```mlir
5708+
// Link against the MSVC static threaded CRT.
5709+
cir.linker_options ["/DEFAULTLIB:", "libcmt"]
5710+
5711+
// Link against aarch64 compiler-rt builtins
5712+
cir.linker_options ["-l", "clang_rt.builtins-aarch64"]
5713+
}];
5714+
5715+
let arguments = (ins StrArrayAttr:$options);
5716+
5717+
let assemblyFormat = [{
5718+
$options attr-dict
5719+
}];
5720+
5721+
let hasVerifier = 1;
5722+
}
5723+
56945724
//===----------------------------------------------------------------------===//
56955725
// Standard library function calls
56965726
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,6 @@ struct MissingFeatures {
370370
static bool emitAtAvailableLinkGuard() { return false; }
371371
static bool emitLLVMUsed() { return false; }
372372
static bool sanStats() { return false; }
373-
static bool linkerOptionsMetadata() { return false; }
374373
static bool emitModuleLinkOptions() { return false; }
375374
static bool elfDependentLibraries() { return false; }
376375
static bool dwarfVersion() { return false; }

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,7 +2041,7 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
20412041
case PCK_Unknown:
20422042
llvm_unreachable("unexpected pragma comment kind");
20432043
case PCK_Linker:
2044-
assert(!MissingFeatures::emitModuleLinkOptions() && "NYI");
2044+
appendLinkerOptions(PCD->getArg());
20452045
break;
20462046
case PCK_Lib:
20472047
assert(!MissingFeatures::elfDependentLibraries() && "NYI");
@@ -3341,6 +3341,18 @@ CIRGenModule::GetAddrOfGlobal(GlobalDecl gd, ForDefinition_t isForDefinition) {
33413341
.getDefiningOp();
33423342
}
33433343

3344+
void CIRGenModule::emitModuleLinkOptions() {
3345+
assert(!MissingFeatures::emitModuleLinkOptions());
3346+
3347+
// Add the linker options metadata flag.
3348+
llvm::SmallVector<mlir::Attribute, 16> args;
3349+
for (const auto &opt : linkerOptionsMetadata) {
3350+
args.push_back(opt);
3351+
}
3352+
mlir::ArrayAttr arr = builder.getArrayAttr(args);
3353+
getBuilder().create<cir::LinkerOptionsOp>(theModule->getLoc(), arr);
3354+
}
3355+
33443356
void CIRGenModule::Release() {
33453357
assert(!MissingFeatures::emitModuleInitializers());
33463358
emitDeferred(getCodeGenOpts().ClangIRBuildDeferredThreshold);
@@ -3392,9 +3404,9 @@ void CIRGenModule::Release() {
33923404
assert(!MissingFeatures::emitLLVMUsed());
33933405
assert(!MissingFeatures::sanStats());
33943406

3395-
if (codeGenOpts.Autolink && (astContext.getLangOpts().Modules ||
3396-
!MissingFeatures::linkerOptionsMetadata())) {
3397-
assert(!MissingFeatures::emitModuleLinkOptions());
3407+
if (codeGenOpts.Autolink &&
3408+
(astContext.getLangOpts().Modules || !linkerOptionsMetadata.empty())) {
3409+
emitModuleLinkOptions();
33983410
}
33993411

34003412
// On ELF we pass the dependent library specifiers directly to the linker
@@ -4229,6 +4241,11 @@ void CIRGenModule::emitGlobalAnnotations() {
42294241
deferredAnnotations.clear();
42304242
}
42314243

4244+
void CIRGenModule::appendLinkerOptions(StringRef Opts) {
4245+
linkerOptionsMetadata.push_back(
4246+
mlir::StringAttr::get(&getMLIRContext(), Opts));
4247+
}
4248+
42324249
cir::TBAAAttr CIRGenModule::getTBAATypeInfo(QualType qTy) {
42334250
if (!tbaa) {
42344251
return nullptr;

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ class CIRGenModule : public CIRGenTypeCache {
154154
llvm::DenseMap<const Expr *, mlir::Operation *>
155155
materializedGlobalTemporaryMap;
156156

157+
llvm::SmallVector<mlir::StringAttr, 16> linkerOptionsMetadata;
158+
157159
public:
158160
mlir::ModuleOp getModule() const { return theModule; }
159161
CIRGenBuilderTy &getBuilder() { return builder; }
@@ -776,6 +778,9 @@ class CIRGenModule : public CIRGenTypeCache {
776778
/// Helper for `emitDeferred` to apply actual codegen.
777779
void emitGlobalDecl(clang::GlobalDecl &D);
778780

781+
/// Emit the link options introduced by imported modules.
782+
void emitModuleLinkOptions();
783+
779784
const llvm::Triple &getTriple() const { return target.getTriple(); }
780785

781786
// Finalize CIR code generation.
@@ -952,6 +957,9 @@ class CIRGenModule : public CIRGenTypeCache {
952957
/// Add global annotations for a global value.
953958
/// Those annotations are emitted during lowering to the LLVM code.
954959
void addGlobalAnnotations(const ValueDecl *d, mlir::Operation *gv);
960+
961+
/// Appends Opts to the "llvm.linker.options" metadata value.
962+
void appendLinkerOptions(StringRef Opts);
955963
};
956964
} // namespace clang::CIRGen
957965

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4017,6 +4017,18 @@ LogicalResult cir::CatchParamOp::verify() {
40174017
return success();
40184018
}
40194019

4020+
//===----------------------------------------------------------------------===//
4021+
// LinkerOptionsOp
4022+
//===----------------------------------------------------------------------===//
4023+
4024+
LogicalResult cir::LinkerOptionsOp::verify() {
4025+
if (mlir::Operation *parentOp = (*this)->getParentOp();
4026+
parentOp && !isa<mlir::ModuleOp>(parentOp))
4027+
return emitOpError("must appear at the module level");
4028+
4029+
return success();
4030+
}
4031+
40204032
//===----------------------------------------------------------------------===//
40214033
// TableGen'd op method definitions
40224034
//===----------------------------------------------------------------------===//

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4230,6 +4230,15 @@ mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
42304230
return mlir::success();
42314231
}
42324232

4233+
mlir::LogicalResult CIRToLLVMLinkerOptionsOpLowering::matchAndRewrite(
4234+
cir::LinkerOptionsOp op, OpAdaptor adaptor,
4235+
mlir::ConversionPatternRewriter &rewriter) const {
4236+
auto newOp = rewriter.create<mlir::LLVM::LinkerOptionsOp>(
4237+
op.getLoc(), op.getOptionsAttr());
4238+
rewriter.replaceOp(op, newOp);
4239+
return mlir::success();
4240+
}
4241+
42334242
void populateCIRToLLVMConversionPatterns(
42344243
mlir::RewritePatternSet &patterns, mlir::TypeConverter &converter,
42354244
mlir::DataLayout &dataLayout, cir::LowerModule *lowerModule,
@@ -4315,6 +4324,7 @@ void populateCIRToLLVMConversionPatterns(
43154324
CIRToLLVMIsConstantOpLowering,
43164325
CIRToLLVMIsFPClassOpLowering,
43174326
CIRToLLVMLLVMIntrinsicCallOpLowering,
4327+
CIRToLLVMLinkerOptionsOpLowering,
43184328
CIRToLLVMMemChrOpLowering,
43194329
CIRToLLVMMemCpyInlineOpLowering,
43204330
CIRToLLVMMemCpyOpLowering,

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,17 @@ class CIRToLLVMSignBitOpLowering
12461246
matchAndRewrite(cir::SignBitOp op, OpAdaptor adaptor,
12471247
mlir::ConversionPatternRewriter &rewriter) const override;
12481248
};
1249+
1250+
class CIRToLLVMLinkerOptionsOpLowering
1251+
: public mlir::OpConversionPattern<cir::LinkerOptionsOp> {
1252+
public:
1253+
using OpConversionPattern<cir::LinkerOptionsOp>::OpConversionPattern;
1254+
1255+
mlir::LogicalResult
1256+
matchAndRewrite(cir::LinkerOptionsOp op, OpAdaptor adaptor,
1257+
mlir::ConversionPatternRewriter &rewriter) const override;
1258+
};
1259+
12491260
mlir::ArrayAttr lowerCIRTBAAAttr(mlir::Attribute tbaa,
12501261
mlir::ConversionPatternRewriter &rewriter,
12511262
cir::LowerModule *lowerMod);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: cir-opt -cir-to-llvm %s | FileCheck %s
2+
3+
module {
4+
cir.linker_options ["/DEFAULTLIB:", "libcmt"]
5+
}
6+
7+
// CHECK: module {
8+
// CHECK-NEXT: llvm.linker_options ["/DEFAULTLIB:", "libcmt"]
9+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)