diff --git a/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp b/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp --- a/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp +++ b/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp @@ -255,11 +255,23 @@ rewriter.getNamedAttr(function_like_impl::getArgDictAttrName(), rewriter.getArrayAttr(newArgAttrs))); } + for (auto pair : llvm::enumerate(attributes)) { + if (pair.value().first == "llvm.linkage") { + attributes.erase(attributes.begin() + pair.index()); + break; + } + } // Create an LLVM function, use external linkage by default until MLIR // functions have linkage. + LLVM::Linkage linkage = LLVM::Linkage::External; + if (funcOp->hasAttr("llvm.linkage")) { + linkage = funcOp->getAttr("llvm.linkage") + .cast() + .getValue(); + } auto newFuncOp = rewriter.create( - funcOp.getLoc(), funcOp.getName(), llvmType, LLVM::Linkage::External, + funcOp.getLoc(), funcOp.getName(), llvmType, linkage, /*dsoLocal*/ false, attributes); rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(), newFuncOp.end()); diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -1440,7 +1440,8 @@ // Parses one of the keywords provided in the list `keywords` and returns the // position of the parsed keyword in the list. If none of the keywords from the // list is parsed, returns -1. -static int parseOptionalKeywordAlternative(OpAsmParser &parser, +template +static int parseOptionalKeywordAlternative(T &parser, ArrayRef keywords) { for (auto en : llvm::enumerate(keywords)) { if (succeeded(parser.parseOptionalKeyword(en.value()))) @@ -2400,6 +2401,29 @@ return FMFAttr::get(parser.getBuilder().getContext(), flags); } +void printLinkageAttr(LLVM::LinkageAttr attr, DialectAsmPrinter &printer) { + printer << "linkage<" << stringifyLinkage(attr.getValue()) << ">"; +} + +Attribute parseLinkageAttr(MLIRContext *context, DialectAsmParser &parser, + Type type) { + if (failed(parser.parseLess())) + return {}; + + SmallVector names; + for (unsigned i = 0, e = getMaxEnumValForLinkage(); i <= e; ++i) + names.push_back(stringifyLinkage((LLVM::Linkage)i)); + + int index = parseOptionalKeywordAlternative(parser, names); + if (index == -1) + return {}; + + if (failed(parser.parseGreater())) + return {}; + + return LinkageAttr::get(parser.getBuilder().getContext(), (LLVM::Linkage)index); +} + LoopOptionsAttrBuilder::LoopOptionsAttrBuilder(LoopOptionsAttr attr) : options(attr.getOptions().begin(), attr.getOptions().end()) {} @@ -2578,7 +2602,12 @@ StringRef attrKind; if (parser.parseKeyword(&attrKind)) return {}; - { + if (attrKind == "linkage") { + Attribute attr = parseLinkageAttr(getContext(), parser, type); + if (!!attr) + return attr; + + } else { Attribute attr; auto parseResult = generatedAttributeParser(getContext(), parser, attrKind, type, attr); @@ -2590,6 +2619,10 @@ } void LLVMDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const { + if (auto lnkattr = attr.dyn_cast()) { + printLinkageAttr(lnkattr, os); + return; + } if (succeeded(generatedAttributePrinter(attr, os))) return; llvm_unreachable("Unknown attribute type"); diff --git a/mlir/test/Conversion/StandardToLLVM/convert-funcs.mlir b/mlir/test/Conversion/StandardToLLVM/convert-funcs.mlir --- a/mlir/test/Conversion/StandardToLLVM/convert-funcs.mlir +++ b/mlir/test/Conversion/StandardToLLVM/convert-funcs.mlir @@ -37,6 +37,9 @@ return %bbarg : () -> () } +// CHECK-LABEL: llvm.func extern_weak @llvmlinkage(i32) +func private @llvmlinkage(i32) attributes { "llvm.linkage" = #llvm.linkage } + // CHECK-LABEL: llvm.func @body(i32) func private @body(i32)