From fa1511f1fb452fc5e13615332b429eb13f4a0fc1 Mon Sep 17 00:00:00 2001 From: Vinicius Couto Espindola Date: Tue, 6 Jun 2023 20:46:22 -0300 Subject: [PATCH] [CIR][Lowering] Partially lower variadic builtins Implement lowering steps for va_start, va_end, and va_copy. The va_arg was not implemented because it requires ABI-specific lowering. ghstack-source-id: 1ab2923027143aa28bb7361b884a5c8ee04cfbc9 Pull Request resolved: https://github.com/llvm/clangir/pull/95 --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 74 ++++++++++++++++++- clang/test/CIR/Lowering/variadics.cir | 40 ++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 clang/test/CIR/Lowering/variadics.cir diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index f54314dcece2..862131d2a8e2 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -49,6 +49,7 @@ #include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include using namespace cir; @@ -544,6 +545,66 @@ class CIRConstantLowering } }; +class CIRVAStartLowering + : public mlir::OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(mlir::cir::VAStartOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(getContext()); + auto vaList = rewriter.create( + op.getLoc(), i8PtrTy, adaptor.getOperands().front()); + rewriter.replaceOpWithNewOp(op, vaList); + return mlir::success(); + } +}; + +class CIRVAEndLowering : public mlir::OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(mlir::cir::VAEndOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(getContext()); + auto vaList = rewriter.create( + op.getLoc(), i8PtrTy, adaptor.getOperands().front()); + rewriter.replaceOpWithNewOp(op, vaList); + return mlir::success(); + } +}; + +class CIRVACopyLowering + : public mlir::OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(mlir::cir::VACopyOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(getContext()); + auto dstList = rewriter.create( + op.getLoc(), i8PtrTy, adaptor.getOperands().front()); + auto srcList = rewriter.create( + op.getLoc(), i8PtrTy, adaptor.getOperands().back()); + rewriter.replaceOpWithNewOp(op, dstList, srcList); + return mlir::success(); + } +}; + +class CIRVAArgLowering : public mlir::OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(mlir::cir::VAArgOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + return op.emitError("cir.vaarg lowering is NYI"); + } +}; + class CIRFuncLowering : public mlir::OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; @@ -997,7 +1058,8 @@ void populateCIRToLLVMConversionPatterns(mlir::RewritePatternSet &patterns, CIRBinOpLowering, CIRLoadLowering, CIRConstantLowering, CIRStoreLowering, CIRAllocaLowering, CIRFuncLowering, CIRScopeOpLowering, CIRCastOpLowering, CIRIfLowering, - CIRGlobalOpLowering, CIRGetGlobalOpLowering>( + CIRGlobalOpLowering, CIRGetGlobalOpLowering, CIRVAStartLowering, + CIRVAEndLowering, CIRVACopyLowering, CIRVAArgLowering>( converter, patterns.getContext()); } @@ -1018,6 +1080,16 @@ void prepareTypeConverter(mlir::LLVMTypeConverter &converter) { // LLVM doesn't work with signed types, so we drop the CIR signs here. return mlir::IntegerType::get(type.getContext(), type.getWidth()); }); + converter.addConversion([&](mlir::cir::StructType type) -> mlir::Type { + llvm::SmallVector llvmMembers; + for (auto ty : type.getMembers()) + llvmMembers.push_back(converter.convertType(ty)); + auto llvmStruct = mlir::LLVM::LLVMStructType::getIdentified( + type.getContext(), type.getTypeName()); + if (llvmStruct.setBody(llvmMembers, /*isPacked=*/type.getPacked()).failed()) + llvm_unreachable("Failed to set body of struct"); + return llvmStruct; + }); } } // namespace diff --git a/clang/test/CIR/Lowering/variadics.cir b/clang/test/CIR/Lowering/variadics.cir new file mode 100644 index 000000000000..db687ba228ca --- /dev/null +++ b/clang/test/CIR/Lowering/variadics.cir @@ -0,0 +1,40 @@ +// RUN: cir-tool %s -cir-to-llvm -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=MLIR + +!s32i = !cir.int +!u32i = !cir.int +!u8i = !cir.int + +!ty_22struct2E__va_list_tag22 = !cir.struct<"struct.__va_list_tag", !u32i, !u32i, !cir.ptr, !cir.ptr, #cir.recdecl.ast> + +module { + cir.func @average(%arg0: !s32i, ...) -> !s32i { + %0 = cir.alloca !s32i, cir.ptr , ["count", init] {alignment = 4 : i64} + %1 = cir.alloca !s32i, cir.ptr , ["__retval"] {alignment = 4 : i64} + %2 = cir.alloca !cir.array, cir.ptr >, ["args"] {alignment = 16 : i64} + %3 = cir.alloca !cir.array, cir.ptr >, ["args_copy"] {alignment = 16 : i64} + cir.store %arg0, %0 : !s32i, cir.ptr + %4 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr>), !cir.ptr + cir.va.start %4 : !cir.ptr + // MLIR: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr) -> !llvm.ptr + // MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr to !llvm.ptr + // MLIR-NEXT: llvm.intr.vastart %{{[0-9]+}} : !llvm.ptr + %5 = cir.cast(array_to_ptrdecay, %3 : !cir.ptr>), !cir.ptr + %6 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr>), !cir.ptr + cir.va.copy %6 to %5 : !cir.ptr, !cir.ptr + // MLIR: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr) -> !llvm.ptr + // MLIR-NEXT: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr) -> !llvm.ptr + // MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr to !llvm.ptr + // MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr to !llvm.ptr + // MLIR-NEXT: llvm.intr.vacopy %13 to %{{[0-9]+}} : !llvm.ptr, !llvm.ptr + %7 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr>), !cir.ptr + cir.va.end %7 : !cir.ptr + // MLIR: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr) -> !llvm.ptr + // MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr to !llvm.ptr + // MLIR-NEXT: llvm.intr.vaend %{{[0-9]+}} : !llvm.ptr + %8 = cir.const(#cir.int<0> : !s32i) : !s32i + cir.store %8, %1 : !s32i, cir.ptr + %9 = cir.load %1 : cir.ptr , !s32i + cir.return %9 : !s32i + } +}