@@ -73,44 +73,40 @@ static bool shouldUseBarePtrCallConv(Operation *op,
73
73
}
74
74
75
75
// / Only retain those attributes that are not constructed by
76
- // / `LLVMFuncOp::build`. If `filterArgAttrs` is set, also filter out argument
77
- // / attributes.
78
- static void filterFuncAttributes (func::FuncOp func, bool filterArgAndResAttrs,
76
+ // / `LLVMFuncOp::build`.
77
+ static void filterFuncAttributes (func::FuncOp func,
79
78
SmallVectorImpl<NamedAttribute> &result) {
80
- for (const NamedAttribute &attr : func->getAttrs ()) {
81
- if (attr.getName () == SymbolTable::getSymbolAttrName () ||
82
- attr.getName () == func.getFunctionTypeAttrName () ||
83
- attr.getName () == linkageAttrName ||
79
+ for (const NamedAttribute &attr : func->getDiscardableAttrs ()) {
80
+ if (attr.getName () == linkageAttrName ||
84
81
attr.getName () == varargsAttrName ||
85
- attr.getName () == LLVM::LLVMDialect::getReadnoneAttrName () ||
86
- (filterArgAndResAttrs &&
87
- (attr.getName () == func.getArgAttrsAttrName () ||
88
- attr.getName () == func.getResAttrsAttrName ())))
82
+ attr.getName () == LLVM::LLVMDialect::getReadnoneAttrName ())
89
83
continue ;
90
84
result.push_back (attr);
91
85
}
92
86
}
93
87
94
- // / Adds a an empty set of argument attributes for the newly added argument in
95
- // / front of the existing ones.
96
- static void prependEmptyArgAttr (OpBuilder &builder,
97
- SmallVectorImpl<NamedAttribute> &newFuncAttrs,
98
- func::FuncOp func) {
99
- auto argAttrs = func.getArgAttrs ();
100
- // Nothing to do when there were no arg attrs beforehand.
101
- if (!argAttrs)
102
- return ;
103
-
104
- size_t numArguments = func.getNumArguments ();
105
- SmallVector<Attribute> newArgAttrs;
106
- newArgAttrs.reserve (numArguments + 1 );
107
- // Insert empty dictionary for the new argument.
108
- newArgAttrs.push_back (builder.getDictionaryAttr ({}));
109
-
110
- llvm::append_range (newArgAttrs, *argAttrs);
111
- auto newNamedAttr = builder.getNamedAttr (func.getArgAttrsAttrName (),
112
- builder.getArrayAttr (newArgAttrs));
113
- newFuncAttrs.push_back (newNamedAttr);
88
+ // / Propagate argument/results attributes.
89
+ static void propagateArgResAttrs (OpBuilder &builder, bool resultStructType,
90
+ func::FuncOp funcOp,
91
+ LLVM::LLVMFuncOp wrapperFuncOp) {
92
+ auto argAttrs = funcOp.getArgAttrs ();
93
+ if (!resultStructType) {
94
+ if (auto resAttrs = funcOp.getAllResultAttrs ())
95
+ wrapperFuncOp.setAllResultAttrs (resAttrs);
96
+ if (argAttrs)
97
+ wrapperFuncOp.setAllArgAttrs (*argAttrs);
98
+ } else {
99
+ SmallVector<Attribute> argAttributes;
100
+ // Only modify the argument and result attributes when the result is now
101
+ // an argument.
102
+ if (argAttrs) {
103
+ argAttributes.push_back (builder.getDictionaryAttr ({}));
104
+ argAttributes.append (argAttrs->begin (), argAttrs->end ());
105
+ wrapperFuncOp.setAllArgAttrs (argAttributes);
106
+ }
107
+ }
108
+ if (funcOp.getSymVisibilityAttr ())
109
+ wrapperFuncOp.setSymVisibility (funcOp.getSymVisibilityAttr ());
114
110
}
115
111
116
112
// / Creates an auxiliary function with pointer-to-memref-descriptor-struct
@@ -129,18 +125,14 @@ static void wrapForExternalCallers(OpBuilder &rewriter, Location loc,
129
125
auto [wrapperFuncType, resultStructType] =
130
126
typeConverter.convertFunctionTypeCWrapper (type);
131
127
132
- SmallVector<NamedAttribute, 4 > attributes;
133
- // Only modify the argument and result attributes when the result is now an
134
- // argument.
135
- if (resultStructType)
136
- prependEmptyArgAttr (rewriter, attributes, funcOp);
137
- filterFuncAttributes (
138
- funcOp, /* filterArgAndResAttrs=*/ static_cast <bool >(resultStructType),
139
- attributes);
128
+ SmallVector<NamedAttribute> attributes;
129
+ filterFuncAttributes (funcOp, attributes);
130
+
140
131
auto wrapperFuncOp = rewriter.create <LLVM::LLVMFuncOp>(
141
132
loc, llvm::formatv (" _mlir_ciface_{0}" , funcOp.getName ()).str (),
142
133
wrapperFuncType, LLVM::Linkage::External, /* dsoLocal=*/ false ,
143
134
/* cconv=*/ LLVM::CConv::C, /* comdat=*/ nullptr , attributes);
135
+ propagateArgResAttrs (rewriter, !!resultStructType, funcOp, wrapperFuncOp);
144
136
145
137
OpBuilder::InsertionGuard guard (rewriter);
146
138
rewriter.setInsertionPointToStart (wrapperFuncOp.addEntryBlock ());
@@ -199,19 +191,14 @@ static void wrapExternalFunction(OpBuilder &builder, Location loc,
199
191
assert (wrapperType && " unexpected type conversion failure" );
200
192
201
193
SmallVector<NamedAttribute, 4 > attributes;
202
- // Only modify the argument and result attributes when the result is now an
203
- // argument.
204
- if (resultStructType)
205
- prependEmptyArgAttr (builder, attributes, funcOp);
206
- filterFuncAttributes (
207
- funcOp, /* filterArgAndResAttrs=*/ static_cast <bool >(resultStructType),
208
- attributes);
194
+ filterFuncAttributes (funcOp, attributes);
209
195
210
196
// Create the auxiliary function.
211
197
auto wrapperFunc = builder.create <LLVM::LLVMFuncOp>(
212
198
loc, llvm::formatv (" _mlir_ciface_{0}" , funcOp.getName ()).str (),
213
199
wrapperType, LLVM::Linkage::External, /* dsoLocal=*/ false ,
214
200
/* cconv=*/ LLVM::CConv::C, /* comdat=*/ nullptr , attributes);
201
+ propagateArgResAttrs (builder, !!resultStructType, funcOp, wrapperFunc);
215
202
216
203
// The wrapper that we synthetize here should only be visible in this module.
217
204
newFuncOp.setLinkage (LLVM::Linkage::Private);
@@ -351,21 +338,56 @@ struct FuncOpConversionBase : public ConvertOpToLLVMPattern<func::FuncOp> {
351
338
if (!llvmType)
352
339
return rewriter.notifyMatchFailure (funcOp, " signature conversion failed" );
353
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
+
354
382
// Propagate argument/result attributes to all converted arguments/result
355
383
// obtained after converting a given original argument/result.
356
- SmallVector<NamedAttribute, 4 > attributes;
357
- filterFuncAttributes (funcOp, /* filterArgAndResAttrs=*/ true , attributes);
358
384
if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs ()) {
359
385
assert (!resAttrDicts.empty () && " expected array to be non-empty" );
360
- auto newResAttrDicts =
361
- (funcOp.getNumResults () == 1 )
362
- ? resAttrDicts
363
- : rewriter.getArrayAttr (rewriter.getDictionaryAttr ({}));
364
- attributes.push_back (
365
- rewriter.getNamedAttr (funcOp.getResAttrsAttrName (), newResAttrDicts));
386
+ if (funcOp.getNumResults () == 1 )
387
+ newFuncOp.setAllResultAttrs (resAttrDicts);
366
388
}
367
389
if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs ()) {
368
- SmallVector<Attribute, 4 > newArgAttrs (
390
+ SmallVector<Attribute> newArgAttrs (
369
391
cast<LLVM::LLVMFunctionType>(llvmType).getNumParams ());
370
392
for (unsigned i = 0 , e = funcOp.getNumArguments (); i < e; ++i) {
371
393
// Some LLVM IR attribute have a type attached to them. During FuncOp ->
@@ -415,48 +437,10 @@ struct FuncOpConversionBase : public ConvertOpToLLVMPattern<func::FuncOp> {
415
437
newArgAttrs[mapping->inputNo + j] =
416
438
DictionaryAttr::get (rewriter.getContext (), {});
417
439
}
418
- attributes. push_back (rewriter. getNamedAttr (
419
- funcOp. getArgAttrsAttrName (), rewriter.getArrayAttr (newArgAttrs) ));
440
+ if (!newArgAttrs. empty ())
441
+ newFuncOp. setAllArgAttrs ( rewriter.getArrayAttr (newArgAttrs));
420
442
}
421
443
422
- // Create an LLVM function, use external linkage by default until MLIR
423
- // functions have linkage.
424
- LLVM::Linkage linkage = LLVM::Linkage::External;
425
- if (funcOp->hasAttr (linkageAttrName)) {
426
- auto attr =
427
- dyn_cast<mlir::LLVM::LinkageAttr>(funcOp->getAttr (linkageAttrName));
428
- if (!attr) {
429
- funcOp->emitError () << " Contains " << linkageAttrName
430
- << " attribute not of type LLVM::LinkageAttr" ;
431
- return rewriter.notifyMatchFailure (
432
- funcOp, " Contains linkage attribute not of type LLVM::LinkageAttr" );
433
- }
434
- linkage = attr.getLinkage ();
435
- }
436
-
437
- // Create a memory effect attribute corresponding to readnone.
438
- StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName ();
439
- LLVM::MemoryEffectsAttr memoryAttr = {};
440
- if (funcOp->hasAttr (readnoneAttrName)) {
441
- auto attr = funcOp->getAttrOfType <UnitAttr>(readnoneAttrName);
442
- if (!attr) {
443
- funcOp->emitError () << " Contains " << readnoneAttrName
444
- << " attribute not of type UnitAttr" ;
445
- return rewriter.notifyMatchFailure (
446
- funcOp, " Contains readnone attribute not of type UnitAttr" );
447
- }
448
- memoryAttr = LLVM::MemoryEffectsAttr::get (rewriter.getContext (),
449
- {LLVM::ModRefInfo::NoModRef,
450
- LLVM::ModRefInfo::NoModRef,
451
- LLVM::ModRefInfo::NoModRef});
452
- }
453
- auto newFuncOp = rewriter.create <LLVM::LLVMFuncOp>(
454
- funcOp.getLoc (), funcOp.getName (), llvmType, linkage,
455
- /* dsoLocal=*/ false , /* cconv=*/ LLVM::CConv::C, /* comdat=*/ nullptr ,
456
- attributes);
457
- // If the memory attribute was created, add it to the function.
458
- if (memoryAttr)
459
- newFuncOp.setMemoryAttr (memoryAttr);
460
444
rewriter.inlineRegionBefore (funcOp.getBody (), newFuncOp.getBody (),
461
445
newFuncOp.end ());
462
446
if (failed (rewriter.convertRegionTypes (&newFuncOp.getBody (), *typeConverter,
0 commit comments