@@ -919,13 +919,46 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands,
919919 memoryEffects, noUnwind, willReturn);
920920
921921 mlir::LLVM::LLVMFunctionType llvmFnTy;
922+
923+ // Temporary to handle the case where we need to prepend an operand if the
924+ // callee is an alias.
925+ SmallVector<mlir::Value> adjustedCallOperands;
926+
922927 if (calleeAttr) { // direct call
923- mlir::FunctionOpInterface fn =
924- mlir::SymbolTable::lookupNearestSymbolFrom<mlir::FunctionOpInterface>(
925- op, calleeAttr);
926- assert (fn && " Did not find function for call" );
927- llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
928- converter->convertType (fn.getFunctionType ()));
928+ mlir::Operation *callee =
929+ mlir::SymbolTable::lookupNearestSymbolFrom (op, calleeAttr);
930+ if (auto fn = dyn_cast<mlir::FunctionOpInterface>(callee)) {
931+ llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
932+ converter->convertType (fn.getFunctionType ()));
933+ } else if (auto alias = cast<mlir::LLVM::AliasOp>(callee)) {
934+ // If the callee wasan alias. In that case,
935+ // we need to prepend the address of the alias to the operands. The
936+ // way aliases work in the LLVM dialect is a little counter-intuitive.
937+ // The AliasOp itself is a pseudo-function that returns the address of
938+ // the global value being aliased, but when we generate the call we
939+ // need to insert an operation that gets the address of the AliasOp.
940+ // This all gets sorted out when the LLVM dialect is lowered to LLVM IR.
941+ auto symAttr = cast<mlir::FlatSymbolRefAttr>(calleeAttr);
942+ auto addrOfAlias =
943+ rewriter
944+ .create <mlir::LLVM::AddressOfOp>(
945+ op->getLoc (),
946+ mlir::LLVM::LLVMPointerType::get (rewriter.getContext ()),
947+ symAttr)
948+ .getResult ();
949+ adjustedCallOperands.push_back (addrOfAlias);
950+
951+ // Now add the regular operands and assign this to the range value.
952+ llvm::append_range (adjustedCallOperands, callOperands);
953+ callOperands = adjustedCallOperands;
954+
955+ // Clear the callee attribute because we're calling an alias.
956+ calleeAttr = {};
957+ llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(alias.getType ());
958+ } else {
959+ // Was this an ifunc?
960+ return op->emitError (" Unexpected callee type!" );
961+ }
929962 } else { // indirect call
930963 assert (!op->getOperands ().empty () &&
931964 " operands list must no be empty for the indirect call" );
@@ -1166,6 +1199,31 @@ void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
11661199 }
11671200}
11681201
1202+ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias (
1203+ cir::FuncOp op, mlir::FlatSymbolRefAttr aliasee, mlir::Type ty,
1204+ OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const {
1205+ SmallVector<mlir::NamedAttribute, 4 > attributes;
1206+ lowerFuncAttributes (op, /* filterArgAndResAttrs=*/ false , attributes);
1207+
1208+ mlir::Location loc = op.getLoc ();
1209+ auto aliasOp = rewriter.replaceOpWithNewOp <mlir::LLVM::AliasOp>(
1210+ op, ty, convertLinkage (op.getLinkage ()), op.getName (), op.getDsoLocal (),
1211+ /* threadLocal=*/ false , attributes);
1212+
1213+ // Create the alias body
1214+ mlir::OpBuilder builder (op.getContext ());
1215+ mlir::Block *block = builder.createBlock (&aliasOp.getInitializerRegion ());
1216+ builder.setInsertionPointToStart (block);
1217+ // The type of AddressOfOp is always a pointer.
1218+ assert (!cir::MissingFeatures::addressSpace ());
1219+ mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get (ty.getContext ());
1220+ auto addrOp =
1221+ builder.create <mlir::LLVM::AddressOfOp>(loc, ptrTy, aliasee.getValue ());
1222+ builder.create <mlir::LLVM::ReturnOp>(loc, addrOp);
1223+
1224+ return mlir::success ();
1225+ }
1226+
11691227mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite (
11701228 cir::FuncOp op, OpAdaptor adaptor,
11711229 mlir::ConversionPatternRewriter &rewriter) const {
@@ -1190,6 +1248,12 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
11901248 resultType ? resultType : mlir::LLVM::LLVMVoidType::get (getContext ()),
11911249 signatureConversion.getConvertedTypes (),
11921250 /* isVarArg=*/ fnType.isVarArg ());
1251+
1252+ // If this is an alias, it needs to be lowered to llvm::AliasOp.
1253+ std::optional<mlir::FlatSymbolRefAttr> aliasee = op.getAliaseeAttr ();
1254+ if (aliasee && *aliasee)
1255+ return matchAndRewriteAlias (op, *aliasee, llvmFnTy, adaptor, rewriter);
1256+
11931257 // LLVMFuncOp expects a single FileLine Location instead of a fused
11941258 // location.
11951259 mlir::Location loc = op.getLoc ();
0 commit comments