@@ -945,13 +945,45 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands,
945
945
memoryEffects, noUnwind, willReturn);
946
946
947
947
mlir::LLVM::LLVMFunctionType llvmFnTy;
948
+
949
+ // Temporary to handle the case where we need to prepend an operand if the
950
+ // callee is an alias.
951
+ SmallVector<mlir::Value> adjustedCallOperands;
952
+
948
953
if (calleeAttr) { // direct call
949
- mlir::FunctionOpInterface fn =
950
- mlir::SymbolTable::lookupNearestSymbolFrom<mlir::FunctionOpInterface>(
951
- op, calleeAttr);
952
- assert (fn && " Did not find function for call" );
953
- llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
954
- converter->convertType (fn.getFunctionType ()));
954
+ mlir::Operation *callee =
955
+ mlir::SymbolTable::lookupNearestSymbolFrom (op, calleeAttr);
956
+ if (auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
957
+ llvmFnTy = converter->convertType <mlir::LLVM::LLVMFunctionType>(
958
+ fn.getFunctionType ());
959
+ assert (llvmFnTy && " Failed to convert function type" );
960
+ } else if (auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
961
+ // If the callee was an alias. In that case,
962
+ // we need to prepend the address of the alias to the operands. The
963
+ // way aliases work in the LLVM dialect is a little counter-intuitive.
964
+ // The AliasOp itself is a pseudo-function that returns the address of
965
+ // the global value being aliased, but when we generate the call we
966
+ // need to insert an operation that gets the address of the AliasOp.
967
+ // This all gets sorted out when the LLVM dialect is lowered to LLVM IR.
968
+ auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
969
+ auto addrOfAlias =
970
+ mlir::LLVM::AddressOfOp::create (
971
+ rewriter, op->getLoc (),
972
+ mlir::LLVM::LLVMPointerType::get (rewriter.getContext ()), symAttr)
973
+ .getResult ();
974
+ adjustedCallOperands.push_back (addrOfAlias);
975
+
976
+ // Now add the regular operands and assign this to the range value.
977
+ llvm::append_range (adjustedCallOperands, callOperands);
978
+ callOperands = adjustedCallOperands;
979
+
980
+ // Clear the callee attribute because we're calling an alias.
981
+ calleeAttr = {};
982
+ llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType ());
983
+ } else {
984
+ // Was this an ifunc?
985
+ return op->emitError (" Unexpected callee type!" );
986
+ }
955
987
} else { // indirect call
956
988
assert (!op->getOperands ().empty () &&
957
989
" operands list must no be empty for the indirect call" );
@@ -1198,6 +1230,30 @@ void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
1198
1230
}
1199
1231
}
1200
1232
1233
+ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias (
1234
+ cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
1235
+ mlir::ConversionPatternRewriter &rewriter) const {
1236
+ SmallVector<mlir::NamedAttribute, 4 > attributes;
1237
+ lowerFuncAttributes (op, /* filterArgAndResAttrs=*/ false , attributes);
1238
+
1239
+ mlir::Location loc = op.getLoc ();
1240
+ auto aliasOp = rewriter.replaceOpWithNewOp <mlir::LLVM::AliasOp>(
1241
+ op, ty, convertLinkage (op.getLinkage ()), op.getName (), op.getDsoLocal (),
1242
+ /* threadLocal=*/ false , attributes);
1243
+
1244
+ // Create the alias body
1245
+ mlir::OpBuilder builder (op.getContext ());
1246
+ mlir::Block *block = builder.createBlock (&aliasOp.getInitializerRegion ());
1247
+ builder.setInsertionPointToStart (block);
1248
+ // The type of AddressOfOp is always a pointer.
1249
+ assert (!cir::MissingFeatures::addressSpace ());
1250
+ mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get (ty.getContext ());
1251
+ auto addrOp = mlir::LLVM::AddressOfOp::create (builder, loc, ptrTy, aliasee);
1252
+ mlir::LLVM::ReturnOp::create (builder, loc, addrOp);
1253
+
1254
+ return mlir::success ();
1255
+ }
1256
+
1201
1257
mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite (
1202
1258
cir::FuncOp op, OpAdaptor adaptor,
1203
1259
mlir::ConversionPatternRewriter &rewriter) const {
@@ -1222,6 +1278,11 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
1222
1278
resultType ? resultType : mlir::LLVM::LLVMVoidType::get (getContext ()),
1223
1279
signatureConversion.getConvertedTypes (),
1224
1280
/* isVarArg=*/ fnType.isVarArg ());
1281
+
1282
+ // If this is an alias, it needs to be lowered to llvm::AliasOp.
1283
+ if (std::optional<llvm::StringRef> aliasee = op.getAliasee ())
1284
+ return matchAndRewriteAlias (op, *aliasee, llvmFnTy, adaptor, rewriter);
1285
+
1225
1286
// LLVMFuncOp expects a single FileLine Location instead of a fused
1226
1287
// location.
1227
1288
mlir::Location loc = op.getLoc ();
0 commit comments