Index: mlir/lib/Target/LLVMIR/ModuleTranslation.cpp =================================================================== --- mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -889,9 +889,46 @@ mapFunction(function.getName(), llvmFunc); addRuntimePreemptionSpecifier(function.getDsoLocal(), llvmFunc); + // Convert function attributes. if (function->getAttrOfType(LLVMDialect::getReadnoneAttrName())) llvmFunc->setDoesNotAccessMemory(); + // Convert return attributes. + llvm::AttrBuilder retAttrs(llvmFunc->getContext()); + mlir::Type mlirRetTy = function.getResultTypes().front(); + if (auto attr = function->getAttrOfType( + LLVMDialect::getAlignAttrName())) { + if (!mlirRetTy.isa()) + return function.emitError("llvm.align attribute attached to LLVM " + "function returning non-pointer value"); + retAttrs.addAlignmentAttr(llvm::Align(attr.getInt())); + } + if (function->getAttrOfType(LLVMDialect::getNoAliasAttrName())) { + if (!mlirRetTy.isa()) + return function.emitError("llvm.noalias attribute attached to LLVM " + "function returning non-pointer value"); + retAttrs.addAttribute(llvm::Attribute::NoAlias); + } + if (function->getAttrOfType(LLVMDialect::getNoUndefAttrName())) { + if (mlirRetTy.isa()) + return function.emitError("llvm.noundef attribute attached to LLVM " + "function returning void"); + retAttrs.addAttribute(llvm::Attribute::NoUndef); + } + if (function->getAttrOfType(LLVMDialect::getSExtAttrName())) { + if (!mlirRetTy.isa()) + return function.emitError("llvm.signext attribute attached to LLVM " + "function returning non-integer value"); + retAttrs.addAttribute(llvm::Attribute::SExt); + } + if (function->getAttrOfType(LLVMDialect::getZExtAttrName())) { + if (!mlirRetTy.isa()) + return function.emitError("llvm.zeroext attribute attached to LLVM " + "function returning non-integer value"); + retAttrs.addAttribute(llvm::Attribute::ZExt); + } + llvmFunc->addRetAttrs(retAttrs); + // Convert argument attributes. unsigned int argIdx = 0; for (auto kvp : llvm::zip(function.getArgumentTypes(), llvmFunc->args())) { Index: mlir/test/Target/LLVMIR/llvmir-invalid.mlir =================================================================== --- mlir/test/Target/LLVMIR/llvmir-invalid.mlir +++ mlir/test/Target/LLVMIR/llvmir-invalid.mlir @@ -105,6 +105,31 @@ // ----- +// expected-error@+1{{llvm.align attribute attached to LLVM function returning non-pointer value}} +llvm.func @alignattr_ret() -> i32 attributes {llvm.align = 4} + +// ----- + +// expected-error@+1{{llvm.noalias attribute attached to LLVM function returning non-pointer value}} +llvm.func @noaliasattr_ret() -> i32 attributes {llvm.noalias} + +// ----- + +// expected-error@+1{{llvm.noundef attribute attached to LLVM function returning void}} +llvm.func @noundefattr_ret() attributes {llvm.noundef} + +// ----- + +// expected-error@+1{{llvm.signext attribute attached to LLVM function returning non-integer value}} +llvm.func @signextattr_ret() -> f32 attributes {llvm.signext} + +// ----- + +// expected-error@+1{{llvm.zeroext attribute attached to LLVM function returning non-integer value}} +llvm.func @zeroextattr_ret() -> f32 attributes {llvm.zeroext} + +// ----- + llvm.func @no_non_complex_struct() -> !llvm.array<2 x array<2 x array<2 x struct<(i32, i32, i32)>>>> { // expected-error @below{{expected struct type to be a complex number}} %0 = llvm.mlir.constant(dense<[[[1, 2], [3, 4]], [[42, 43], [44, 45]]]> : tensor<2x2x2xi32>) : !llvm.array<2 x array<2 x array<2 x struct<(i32, i32, i32)>>>> Index: mlir/test/Target/LLVMIR/llvmir.mlir =================================================================== --- mlir/test/Target/LLVMIR/llvmir.mlir +++ mlir/test/Target/LLVMIR/llvmir.mlir @@ -1124,6 +1124,17 @@ // CHECK-LABEL: declare void @zeroextattr_decl(i1 zeroext) llvm.func @zeroextattr_decl(i1 {llvm.zeroext}) +// CHECK-LABEL: declare align 4 ptr @alignattr_ret_decl() +llvm.func @alignattr_ret_decl() -> !llvm.ptr attributes {llvm.align = 4} +// CHECK-LABEL: declare noalias ptr @noaliasattr_ret_decl() +llvm.func @noaliasattr_ret_decl() -> !llvm.ptr attributes {llvm.noalias} +// CHECK-LABEL: declare noundef ptr @noundefattr_ret_decl() +llvm.func @noundefattr_ret_decl() -> !llvm.ptr attributes {llvm.noundef} +// CHECK-LABEL: declare signext i1 @signextattr_ret_decl() +llvm.func @signextattr_ret_decl() -> i1 attributes {llvm.signext} +// CHECK-LABEL: declare zeroext i1 @zeroextattr_ret_decl() +llvm.func @zeroextattr_ret_decl() -> i1 attributes {llvm.zeroext} + // CHECK-LABEL: @llvm_varargs(...) llvm.func @llvm_varargs(...)