1212// ===----------------------------------------------------------------------===//
1313#include " mlir/Dialect/LLVMIR/LLVMDialect.h"
1414#include " TypeDetail.h"
15+ #include " mlir/Dialect/LLVMIR/LLVMAttrs.h"
1516#include " mlir/Dialect/LLVMIR/LLVMInterfaces.h"
1617#include " mlir/Dialect/LLVMIR/LLVMTypes.h"
1718#include " mlir/IR/Builders.h"
@@ -2854,6 +2855,39 @@ static void moveConstantAllocasToEntryBlock(
28542855 }
28552856}
28562857
2858+ static Value handleByValArgument (OpBuilder &builder, Operation *callable,
2859+ Value argument,
2860+ NamedAttribute byValAttribute) {
2861+ auto func = cast<LLVM::LLVMFuncOp>(callable);
2862+ LLVM::MemoryEffectsAttr memoryEffects = func.getMemoryAttr ();
2863+ // If there is no memory effects attribute, assume that the function is
2864+ // not read-only.
2865+ bool isReadOnly = memoryEffects &&
2866+ memoryEffects.getArgMem () != ModRefInfo::ModRef &&
2867+ memoryEffects.getArgMem () != ModRefInfo::Mod;
2868+ if (isReadOnly)
2869+ return argument;
2870+ // Resolve the pointee type and its size.
2871+ auto ptrType = cast<LLVM::LLVMPointerType>(argument.getType ());
2872+ Type elementType = cast<TypeAttr>(byValAttribute.getValue ()).getValue ();
2873+ unsigned int typeSize =
2874+ DataLayout (callable->getParentOfType <DataLayoutOpInterface>())
2875+ .getTypeSize (elementType);
2876+ // Allocate the new value on the stack.
2877+ Value one = builder.create <LLVM::ConstantOp>(
2878+ func.getLoc (), builder.getI64Type (), builder.getI64IntegerAttr (1 ));
2879+ Value allocaOp =
2880+ builder.create <LLVM::AllocaOp>(func.getLoc (), ptrType, elementType, one);
2881+ // Copy the pointee to the newly allocated value.
2882+ Value copySize = builder.create <LLVM::ConstantOp>(
2883+ func.getLoc (), builder.getI64Type (), builder.getI64IntegerAttr (typeSize));
2884+ Value isVolatile = builder.create <LLVM::ConstantOp>(
2885+ func.getLoc (), builder.getI1Type (), builder.getBoolAttr (false ));
2886+ builder.create <LLVM::MemcpyOp>(func.getLoc (), allocaOp, argument, copySize,
2887+ isVolatile);
2888+ return allocaOp;
2889+ }
2890+
28572891namespace {
28582892struct LLVMInlinerInterface : public DialectInlinerInterface {
28592893 using DialectInlinerInterface::DialectInlinerInterface;
@@ -2866,8 +2900,19 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
28662900 auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(callable);
28672901 if (!callOp || !funcOp)
28682902 return false ;
2869- // TODO: Handle argument and result attributes;
2870- if (funcOp.getArgAttrs () || funcOp.getResAttrs ())
2903+ if (auto attrs = funcOp.getArgAttrs ()) {
2904+ for (Attribute attr : *attrs) {
2905+ auto attrDict = cast<DictionaryAttr>(attr);
2906+ for (NamedAttribute attr : attrDict) {
2907+ if (attr.getName () == LLVMDialect::getByValAttrName ())
2908+ continue ;
2909+ // TODO: Handle all argument attributes;
2910+ return false ;
2911+ }
2912+ }
2913+ }
2914+ // TODO: Handle result attributes;
2915+ if (funcOp.getResAttrs ())
28712916 return false ;
28722917 // TODO: Handle exceptions.
28732918 if (funcOp.getPersonality ())
@@ -2942,6 +2987,14 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
29422987 dst.replaceAllUsesWith (src);
29432988 }
29442989
2990+ Value handleArgument (OpBuilder &builder, Operation *call, Operation *callable,
2991+ Value argument, Type targetType,
2992+ DictionaryAttr argumentAttrs) const final {
2993+ if (auto attr = argumentAttrs.getNamed (LLVMDialect::getByValAttrName ()))
2994+ return handleByValArgument (builder, callable, argument, *attr);
2995+ return argument;
2996+ }
2997+
29452998 void processInlinedCallBlocks (
29462999 Operation *call,
29473000 iterator_range<Region::iterator> inlinedBlocks) const override {
0 commit comments