@@ -74,7 +74,7 @@ static bool shouldUseBarePtrCallConv(Operation *op,
74
74
75
75
// / Only retain those attributes that are not constructed by
76
76
// / `LLVMFuncOp::build`.
77
- static void filterFuncAttributes (func::FuncOp func,
77
+ static void filterFuncAttributes (FunctionOpInterface func,
78
78
SmallVectorImpl<NamedAttribute> &result) {
79
79
for (const NamedAttribute &attr : func->getDiscardableAttrs ()) {
80
80
if (attr.getName () == linkageAttrName ||
@@ -87,26 +87,26 @@ static void filterFuncAttributes(func::FuncOp func,
87
87
88
88
// / Propagate argument/results attributes.
89
89
static void propagateArgResAttrs (OpBuilder &builder, bool resultStructType,
90
- func::FuncOp funcOp,
90
+ FunctionOpInterface funcOp,
91
91
LLVM::LLVMFuncOp wrapperFuncOp) {
92
- auto argAttrs = funcOp.getArgAttrs ();
92
+ auto argAttrs = funcOp.getAllArgAttrs ();
93
93
if (!resultStructType) {
94
94
if (auto resAttrs = funcOp.getAllResultAttrs ())
95
95
wrapperFuncOp.setAllResultAttrs (resAttrs);
96
96
if (argAttrs)
97
- wrapperFuncOp.setAllArgAttrs (* argAttrs);
97
+ wrapperFuncOp.setAllArgAttrs (argAttrs);
98
98
} else {
99
99
SmallVector<Attribute> argAttributes;
100
100
// Only modify the argument and result attributes when the result is now
101
101
// an argument.
102
102
if (argAttrs) {
103
103
argAttributes.push_back (builder.getDictionaryAttr ({}));
104
- argAttributes.append (argAttrs-> begin (), argAttrs-> end ());
104
+ argAttributes.append (argAttrs. begin (), argAttrs. end ());
105
105
wrapperFuncOp.setAllArgAttrs (argAttributes);
106
106
}
107
107
}
108
- if (funcOp. getSymVisibilityAttr ())
109
- wrapperFuncOp. setSymVisibility (funcOp.getSymVisibilityAttr ());
108
+ cast<FunctionOpInterface>(wrapperFuncOp. getOperation ())
109
+ . setVisibility (funcOp.getVisibility ());
110
110
}
111
111
112
112
// / Creates an auxiliary function with pointer-to-memref-descriptor-struct
@@ -119,9 +119,9 @@ static void propagateArgResAttrs(OpBuilder &builder, bool resultStructType,
119
119
// / the extra arguments.
120
120
static void wrapForExternalCallers (OpBuilder &rewriter, Location loc,
121
121
const LLVMTypeConverter &typeConverter,
122
- func::FuncOp funcOp,
122
+ FunctionOpInterface funcOp,
123
123
LLVM::LLVMFuncOp newFuncOp) {
124
- auto type = funcOp.getFunctionType ();
124
+ auto type = cast<FunctionType>( funcOp.getFunctionType () );
125
125
auto [wrapperFuncType, resultStructType] =
126
126
typeConverter.convertFunctionTypeCWrapper (type);
127
127
@@ -179,12 +179,13 @@ static void wrapForExternalCallers(OpBuilder &rewriter, Location loc,
179
179
// / corresponding to a memref descriptor.
180
180
static void wrapExternalFunction (OpBuilder &builder, Location loc,
181
181
const LLVMTypeConverter &typeConverter,
182
- func::FuncOp funcOp,
182
+ FunctionOpInterface funcOp,
183
183
LLVM::LLVMFuncOp newFuncOp) {
184
184
OpBuilder::InsertionGuard guard (builder);
185
185
186
186
auto [wrapperType, resultStructType] =
187
- typeConverter.convertFunctionTypeCWrapper (funcOp.getFunctionType ());
187
+ typeConverter.convertFunctionTypeCWrapper (
188
+ cast<FunctionType>(funcOp.getFunctionType ()));
188
189
// This conversion can only fail if it could not convert one of the argument
189
190
// types. But since it has been applied to a non-wrapper function before, it
190
191
// should have failed earlier and not reach this point at all.
@@ -205,7 +206,7 @@ static void wrapExternalFunction(OpBuilder &builder, Location loc,
205
206
builder.setInsertionPointToStart (newFuncOp.addEntryBlock ());
206
207
207
208
// Get a ValueRange containing arguments.
208
- FunctionType type = funcOp.getFunctionType ();
209
+ FunctionType type = cast<FunctionType>( funcOp.getFunctionType () );
209
210
SmallVector<Value, 8 > args;
210
211
args.reserve (type.getNumInputs ());
211
212
ValueRange wrapperArgsRange (newFuncOp.getArguments ());
@@ -317,6 +318,140 @@ static void modifyFuncOpToUseBarePtrCallingConv(
317
318
}
318
319
}
319
320
321
+ FailureOr<LLVM::LLVMFuncOp>
322
+ mlir::convertFuncOpToLLVMFuncOp (FunctionOpInterface funcOp,
323
+ ConversionPatternRewriter &rewriter,
324
+ const LLVMTypeConverter &converter) {
325
+ // Check the funcOp has `FunctionType`.
326
+ auto funcTy = dyn_cast<FunctionType>(funcOp.getFunctionType ());
327
+ if (!funcTy)
328
+ return rewriter.notifyMatchFailure (
329
+ funcOp, " Only support FunctionOpInterface with FunctionType" );
330
+
331
+ // Convert the original function arguments. They are converted using the
332
+ // LLVMTypeConverter provided to this legalization pattern.
333
+ auto varargsAttr = funcOp->getAttrOfType <BoolAttr>(varargsAttrName);
334
+ TypeConverter::SignatureConversion result (funcOp.getNumArguments ());
335
+ auto llvmType = converter.convertFunctionSignature (
336
+ funcTy, varargsAttr && varargsAttr.getValue (),
337
+ shouldUseBarePtrCallConv (funcOp, &converter), result);
338
+ if (!llvmType)
339
+ return rewriter.notifyMatchFailure (funcOp, " signature conversion failed" );
340
+
341
+ // Create an LLVM function, use external linkage by default until MLIR
342
+ // functions have linkage.
343
+ LLVM::Linkage linkage = LLVM::Linkage::External;
344
+ if (funcOp->hasAttr (linkageAttrName)) {
345
+ auto attr =
346
+ dyn_cast<mlir::LLVM::LinkageAttr>(funcOp->getAttr (linkageAttrName));
347
+ if (!attr) {
348
+ funcOp->emitError () << " Contains " << linkageAttrName
349
+ << " attribute not of type LLVM::LinkageAttr" ;
350
+ return rewriter.notifyMatchFailure (
351
+ funcOp, " Contains linkage attribute not of type LLVM::LinkageAttr" );
352
+ }
353
+ linkage = attr.getLinkage ();
354
+ }
355
+
356
+ SmallVector<NamedAttribute, 4 > attributes;
357
+ filterFuncAttributes (funcOp, attributes);
358
+ auto newFuncOp = rewriter.create <LLVM::LLVMFuncOp>(
359
+ funcOp.getLoc (), funcOp.getName (), llvmType, linkage,
360
+ /* dsoLocal=*/ false , /* cconv=*/ LLVM::CConv::C, /* comdat=*/ nullptr ,
361
+ attributes);
362
+ cast<FunctionOpInterface>(newFuncOp.getOperation ())
363
+ .setVisibility (funcOp.getVisibility ());
364
+
365
+ // Create a memory effect attribute corresponding to readnone.
366
+ StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName ();
367
+ if (funcOp->hasAttr (readnoneAttrName)) {
368
+ auto attr = funcOp->getAttrOfType <UnitAttr>(readnoneAttrName);
369
+ if (!attr) {
370
+ funcOp->emitError () << " Contains " << readnoneAttrName
371
+ << " attribute not of type UnitAttr" ;
372
+ return rewriter.notifyMatchFailure (
373
+ funcOp, " Contains readnone attribute not of type UnitAttr" );
374
+ }
375
+ auto memoryAttr = LLVM::MemoryEffectsAttr::get (
376
+ rewriter.getContext (),
377
+ {LLVM::ModRefInfo::NoModRef, LLVM::ModRefInfo::NoModRef,
378
+ LLVM::ModRefInfo::NoModRef});
379
+ newFuncOp.setMemoryAttr (memoryAttr);
380
+ }
381
+
382
+ // Propagate argument/result attributes to all converted arguments/result
383
+ // obtained after converting a given original argument/result.
384
+ if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs ()) {
385
+ assert (!resAttrDicts.empty () && " expected array to be non-empty" );
386
+ if (funcOp.getNumResults () == 1 )
387
+ newFuncOp.setAllResultAttrs (resAttrDicts);
388
+ }
389
+ if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs ()) {
390
+ SmallVector<Attribute> newArgAttrs (
391
+ cast<LLVM::LLVMFunctionType>(llvmType).getNumParams ());
392
+ for (unsigned i = 0 , e = funcOp.getNumArguments (); i < e; ++i) {
393
+ // Some LLVM IR attribute have a type attached to them. During FuncOp ->
394
+ // LLVMFuncOp conversion these types may have changed. Account for that
395
+ // change by converting attributes' types as well.
396
+ SmallVector<NamedAttribute, 4 > convertedAttrs;
397
+ auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
398
+ convertedAttrs.reserve (attrsDict.size ());
399
+ for (const NamedAttribute &attr : attrsDict) {
400
+ const auto convert = [&](const NamedAttribute &attr) {
401
+ return TypeAttr::get (converter.convertType (
402
+ cast<TypeAttr>(attr.getValue ()).getValue ()));
403
+ };
404
+ if (attr.getName ().getValue () ==
405
+ LLVM::LLVMDialect::getByValAttrName ()) {
406
+ convertedAttrs.push_back (rewriter.getNamedAttr (
407
+ LLVM::LLVMDialect::getByValAttrName (), convert (attr)));
408
+ } else if (attr.getName ().getValue () ==
409
+ LLVM::LLVMDialect::getByRefAttrName ()) {
410
+ convertedAttrs.push_back (rewriter.getNamedAttr (
411
+ LLVM::LLVMDialect::getByRefAttrName (), convert (attr)));
412
+ } else if (attr.getName ().getValue () ==
413
+ LLVM::LLVMDialect::getStructRetAttrName ()) {
414
+ convertedAttrs.push_back (rewriter.getNamedAttr (
415
+ LLVM::LLVMDialect::getStructRetAttrName (), convert (attr)));
416
+ } else if (attr.getName ().getValue () ==
417
+ LLVM::LLVMDialect::getInAllocaAttrName ()) {
418
+ convertedAttrs.push_back (rewriter.getNamedAttr (
419
+ LLVM::LLVMDialect::getInAllocaAttrName (), convert (attr)));
420
+ } else {
421
+ convertedAttrs.push_back (attr);
422
+ }
423
+ }
424
+ auto mapping = result.getInputMapping (i);
425
+ assert (mapping && " unexpected deletion of function argument" );
426
+ // Only attach the new argument attributes if there is a one-to-one
427
+ // mapping from old to new types. Otherwise, attributes might be
428
+ // attached to types that they do not support.
429
+ if (mapping->size == 1 ) {
430
+ newArgAttrs[mapping->inputNo ] =
431
+ DictionaryAttr::get (rewriter.getContext (), convertedAttrs);
432
+ continue ;
433
+ }
434
+ // TODO: Implement custom handling for types that expand to multiple
435
+ // function arguments.
436
+ for (size_t j = 0 ; j < mapping->size ; ++j)
437
+ newArgAttrs[mapping->inputNo + j] =
438
+ DictionaryAttr::get (rewriter.getContext (), {});
439
+ }
440
+ if (!newArgAttrs.empty ())
441
+ newFuncOp.setAllArgAttrs (rewriter.getArrayAttr (newArgAttrs));
442
+ }
443
+
444
+ rewriter.inlineRegionBefore (funcOp.getFunctionBody (), newFuncOp.getBody (),
445
+ newFuncOp.end ());
446
+ if (failed (rewriter.convertRegionTypes (&newFuncOp.getBody (), converter,
447
+ &result))) {
448
+ return rewriter.notifyMatchFailure (funcOp,
449
+ " region types conversion failed" );
450
+ }
451
+
452
+ return newFuncOp;
453
+ }
454
+
320
455
namespace {
321
456
322
457
struct FuncOpConversionBase : public ConvertOpToLLVMPattern <func::FuncOp> {
@@ -328,128 +463,9 @@ struct FuncOpConversionBase : public ConvertOpToLLVMPattern<func::FuncOp> {
328
463
FailureOr<LLVM::LLVMFuncOp>
329
464
convertFuncOpToLLVMFuncOp (func::FuncOp funcOp,
330
465
ConversionPatternRewriter &rewriter) const {
331
- // Convert the original function arguments. They are converted using the
332
- // LLVMTypeConverter provided to this legalization pattern.
333
- auto varargsAttr = funcOp->getAttrOfType <BoolAttr>(varargsAttrName);
334
- TypeConverter::SignatureConversion result (funcOp.getNumArguments ());
335
- auto llvmType = getTypeConverter ()->convertFunctionSignature (
336
- funcOp.getFunctionType (), varargsAttr && varargsAttr.getValue (),
337
- shouldUseBarePtrCallConv (funcOp, getTypeConverter ()), result);
338
- if (!llvmType)
339
- return rewriter.notifyMatchFailure (funcOp, " signature conversion failed" );
340
-
341
- // Create an LLVM function, use external linkage by default until MLIR
342
- // functions have linkage.
343
- LLVM::Linkage linkage = LLVM::Linkage::External;
344
- if (funcOp->hasAttr (linkageAttrName)) {
345
- auto attr =
346
- dyn_cast<mlir::LLVM::LinkageAttr>(funcOp->getAttr (linkageAttrName));
347
- if (!attr) {
348
- funcOp->emitError () << " Contains " << linkageAttrName
349
- << " attribute not of type LLVM::LinkageAttr" ;
350
- return rewriter.notifyMatchFailure (
351
- funcOp, " Contains linkage attribute not of type LLVM::LinkageAttr" );
352
- }
353
- linkage = attr.getLinkage ();
354
- }
355
-
356
- SmallVector<NamedAttribute, 4 > attributes;
357
- filterFuncAttributes (funcOp, attributes);
358
- auto newFuncOp = rewriter.create <LLVM::LLVMFuncOp>(
359
- funcOp.getLoc (), funcOp.getName (), llvmType, linkage,
360
- /* dsoLocal=*/ false , /* cconv=*/ LLVM::CConv::C, /* comdat=*/ nullptr ,
361
- attributes);
362
- if (funcOp.getSymVisibilityAttr ())
363
- newFuncOp.setSymVisibility (funcOp.getSymVisibilityAttr ());
364
-
365
- // Create a memory effect attribute corresponding to readnone.
366
- StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName ();
367
- if (funcOp->hasAttr (readnoneAttrName)) {
368
- auto attr = funcOp->getAttrOfType <UnitAttr>(readnoneAttrName);
369
- if (!attr) {
370
- funcOp->emitError () << " Contains " << readnoneAttrName
371
- << " attribute not of type UnitAttr" ;
372
- return rewriter.notifyMatchFailure (
373
- funcOp, " Contains readnone attribute not of type UnitAttr" );
374
- }
375
- auto memoryAttr = LLVM::MemoryEffectsAttr::get (
376
- rewriter.getContext (),
377
- {LLVM::ModRefInfo::NoModRef, LLVM::ModRefInfo::NoModRef,
378
- LLVM::ModRefInfo::NoModRef});
379
- newFuncOp.setMemoryAttr (memoryAttr);
380
- }
381
-
382
- // Propagate argument/result attributes to all converted arguments/result
383
- // obtained after converting a given original argument/result.
384
- if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs ()) {
385
- assert (!resAttrDicts.empty () && " expected array to be non-empty" );
386
- if (funcOp.getNumResults () == 1 )
387
- newFuncOp.setAllResultAttrs (resAttrDicts);
388
- }
389
- if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs ()) {
390
- SmallVector<Attribute> newArgAttrs (
391
- cast<LLVM::LLVMFunctionType>(llvmType).getNumParams ());
392
- for (unsigned i = 0 , e = funcOp.getNumArguments (); i < e; ++i) {
393
- // Some LLVM IR attribute have a type attached to them. During FuncOp ->
394
- // LLVMFuncOp conversion these types may have changed. Account for that
395
- // change by converting attributes' types as well.
396
- SmallVector<NamedAttribute, 4 > convertedAttrs;
397
- auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
398
- convertedAttrs.reserve (attrsDict.size ());
399
- for (const NamedAttribute &attr : attrsDict) {
400
- const auto convert = [&](const NamedAttribute &attr) {
401
- return TypeAttr::get (getTypeConverter ()->convertType (
402
- cast<TypeAttr>(attr.getValue ()).getValue ()));
403
- };
404
- if (attr.getName ().getValue () ==
405
- LLVM::LLVMDialect::getByValAttrName ()) {
406
- convertedAttrs.push_back (rewriter.getNamedAttr (
407
- LLVM::LLVMDialect::getByValAttrName (), convert (attr)));
408
- } else if (attr.getName ().getValue () ==
409
- LLVM::LLVMDialect::getByRefAttrName ()) {
410
- convertedAttrs.push_back (rewriter.getNamedAttr (
411
- LLVM::LLVMDialect::getByRefAttrName (), convert (attr)));
412
- } else if (attr.getName ().getValue () ==
413
- LLVM::LLVMDialect::getStructRetAttrName ()) {
414
- convertedAttrs.push_back (rewriter.getNamedAttr (
415
- LLVM::LLVMDialect::getStructRetAttrName (), convert (attr)));
416
- } else if (attr.getName ().getValue () ==
417
- LLVM::LLVMDialect::getInAllocaAttrName ()) {
418
- convertedAttrs.push_back (rewriter.getNamedAttr (
419
- LLVM::LLVMDialect::getInAllocaAttrName (), convert (attr)));
420
- } else {
421
- convertedAttrs.push_back (attr);
422
- }
423
- }
424
- auto mapping = result.getInputMapping (i);
425
- assert (mapping && " unexpected deletion of function argument" );
426
- // Only attach the new argument attributes if there is a one-to-one
427
- // mapping from old to new types. Otherwise, attributes might be
428
- // attached to types that they do not support.
429
- if (mapping->size == 1 ) {
430
- newArgAttrs[mapping->inputNo ] =
431
- DictionaryAttr::get (rewriter.getContext (), convertedAttrs);
432
- continue ;
433
- }
434
- // TODO: Implement custom handling for types that expand to multiple
435
- // function arguments.
436
- for (size_t j = 0 ; j < mapping->size ; ++j)
437
- newArgAttrs[mapping->inputNo + j] =
438
- DictionaryAttr::get (rewriter.getContext (), {});
439
- }
440
- if (!newArgAttrs.empty ())
441
- newFuncOp.setAllArgAttrs (rewriter.getArrayAttr (newArgAttrs));
442
- }
443
-
444
- rewriter.inlineRegionBefore (funcOp.getBody (), newFuncOp.getBody (),
445
- newFuncOp.end ());
446
- if (failed (rewriter.convertRegionTypes (&newFuncOp.getBody (), *typeConverter,
447
- &result))) {
448
- return rewriter.notifyMatchFailure (funcOp,
449
- " region types conversion failed" );
450
- }
451
-
452
- return newFuncOp;
466
+ return mlir::convertFuncOpToLLVMFuncOp (
467
+ cast<FunctionOpInterface>(funcOp.getOperation ()), rewriter,
468
+ *getTypeConverter ());
453
469
}
454
470
};
455
471
0 commit comments