Skip to content

Commit baecd48

Browse files
sitio-coutolanza
authored andcommitted
[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: 1ab2923 Pull Request resolved: #95
1 parent 3302640 commit baecd48

File tree

2 files changed

+113
-1
lines changed

2 files changed

+113
-1
lines changed

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "llvm/ADT/Sequence.h"
5050
#include "llvm/ADT/SmallVector.h"
5151
#include "llvm/Support/Casting.h"
52+
#include "llvm/Support/ErrorHandling.h"
5253
#include <optional>
5354

5455
using namespace cir;
@@ -544,6 +545,66 @@ class CIRConstantLowering
544545
}
545546
};
546547

548+
class CIRVAStartLowering
549+
: public mlir::OpConversionPattern<mlir::cir::VAStartOp> {
550+
public:
551+
using OpConversionPattern<mlir::cir::VAStartOp>::OpConversionPattern;
552+
553+
mlir::LogicalResult
554+
matchAndRewrite(mlir::cir::VAStartOp op, OpAdaptor adaptor,
555+
mlir::ConversionPatternRewriter &rewriter) const override {
556+
auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(getContext());
557+
auto vaList = rewriter.create<mlir::LLVM::BitcastOp>(
558+
op.getLoc(), i8PtrTy, adaptor.getOperands().front());
559+
rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
560+
return mlir::success();
561+
}
562+
};
563+
564+
class CIRVAEndLowering : public mlir::OpConversionPattern<mlir::cir::VAEndOp> {
565+
public:
566+
using OpConversionPattern<mlir::cir::VAEndOp>::OpConversionPattern;
567+
568+
mlir::LogicalResult
569+
matchAndRewrite(mlir::cir::VAEndOp op, OpAdaptor adaptor,
570+
mlir::ConversionPatternRewriter &rewriter) const override {
571+
auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(getContext());
572+
auto vaList = rewriter.create<mlir::LLVM::BitcastOp>(
573+
op.getLoc(), i8PtrTy, adaptor.getOperands().front());
574+
rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
575+
return mlir::success();
576+
}
577+
};
578+
579+
class CIRVACopyLowering
580+
: public mlir::OpConversionPattern<mlir::cir::VACopyOp> {
581+
public:
582+
using OpConversionPattern<mlir::cir::VACopyOp>::OpConversionPattern;
583+
584+
mlir::LogicalResult
585+
matchAndRewrite(mlir::cir::VACopyOp op, OpAdaptor adaptor,
586+
mlir::ConversionPatternRewriter &rewriter) const override {
587+
auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(getContext());
588+
auto dstList = rewriter.create<mlir::LLVM::BitcastOp>(
589+
op.getLoc(), i8PtrTy, adaptor.getOperands().front());
590+
auto srcList = rewriter.create<mlir::LLVM::BitcastOp>(
591+
op.getLoc(), i8PtrTy, adaptor.getOperands().back());
592+
rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
593+
return mlir::success();
594+
}
595+
};
596+
597+
class CIRVAArgLowering : public mlir::OpConversionPattern<mlir::cir::VAArgOp> {
598+
public:
599+
using OpConversionPattern<mlir::cir::VAArgOp>::OpConversionPattern;
600+
601+
mlir::LogicalResult
602+
matchAndRewrite(mlir::cir::VAArgOp op, OpAdaptor adaptor,
603+
mlir::ConversionPatternRewriter &rewriter) const override {
604+
return op.emitError("cir.vaarg lowering is NYI");
605+
}
606+
};
607+
547608
class CIRFuncLowering : public mlir::OpConversionPattern<mlir::cir::FuncOp> {
548609
public:
549610
using OpConversionPattern<mlir::cir::FuncOp>::OpConversionPattern;
@@ -997,7 +1058,8 @@ void populateCIRToLLVMConversionPatterns(mlir::RewritePatternSet &patterns,
9971058
CIRBinOpLowering, CIRLoadLowering, CIRConstantLowering,
9981059
CIRStoreLowering, CIRAllocaLowering, CIRFuncLowering,
9991060
CIRScopeOpLowering, CIRCastOpLowering, CIRIfLowering,
1000-
CIRGlobalOpLowering, CIRGetGlobalOpLowering>(
1061+
CIRGlobalOpLowering, CIRGetGlobalOpLowering, CIRVAStartLowering,
1062+
CIRVAEndLowering, CIRVACopyLowering, CIRVAArgLowering>(
10011063
converter, patterns.getContext());
10021064
}
10031065

@@ -1018,6 +1080,16 @@ void prepareTypeConverter(mlir::LLVMTypeConverter &converter) {
10181080
// LLVM doesn't work with signed types, so we drop the CIR signs here.
10191081
return mlir::IntegerType::get(type.getContext(), type.getWidth());
10201082
});
1083+
converter.addConversion([&](mlir::cir::StructType type) -> mlir::Type {
1084+
llvm::SmallVector<mlir::Type> llvmMembers;
1085+
for (auto ty : type.getMembers())
1086+
llvmMembers.push_back(converter.convertType(ty));
1087+
auto llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
1088+
type.getContext(), type.getTypeName());
1089+
if (llvmStruct.setBody(llvmMembers, /*isPacked=*/type.getPacked()).failed())
1090+
llvm_unreachable("Failed to set body of struct");
1091+
return llvmStruct;
1092+
});
10211093
}
10221094
} // namespace
10231095

clang/test/CIR/Lowering/variadics.cir

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: cir-tool %s -cir-to-llvm -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=MLIR
3+
4+
!s32i = !cir.int<s, 32>
5+
!u32i = !cir.int<u, 32>
6+
!u8i = !cir.int<u, 8>
7+
8+
!ty_22struct2E__va_list_tag22 = !cir.struct<"struct.__va_list_tag", !u32i, !u32i, !cir.ptr<!u8i>, !cir.ptr<!u8i>, #cir.recdecl.ast>
9+
10+
module {
11+
cir.func @average(%arg0: !s32i, ...) -> !s32i {
12+
%0 = cir.alloca !s32i, cir.ptr <!s32i>, ["count", init] {alignment = 4 : i64}
13+
%1 = cir.alloca !s32i, cir.ptr <!s32i>, ["__retval"] {alignment = 4 : i64}
14+
%2 = cir.alloca !cir.array<!ty_22struct2E__va_list_tag22 x 1>, cir.ptr <!cir.array<!ty_22struct2E__va_list_tag22 x 1>>, ["args"] {alignment = 16 : i64}
15+
%3 = cir.alloca !cir.array<!ty_22struct2E__va_list_tag22 x 1>, cir.ptr <!cir.array<!ty_22struct2E__va_list_tag22 x 1>>, ["args_copy"] {alignment = 16 : i64}
16+
cir.store %arg0, %0 : !s32i, cir.ptr <!s32i>
17+
%4 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr<!cir.array<!ty_22struct2E__va_list_tag22 x 1>>), !cir.ptr<!ty_22struct2E__va_list_tag22>
18+
cir.va.start %4 : !cir.ptr<!ty_22struct2E__va_list_tag22>
19+
// MLIR: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr) -> !llvm.ptr
20+
// MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr to !llvm.ptr
21+
// MLIR-NEXT: llvm.intr.vastart %{{[0-9]+}} : !llvm.ptr
22+
%5 = cir.cast(array_to_ptrdecay, %3 : !cir.ptr<!cir.array<!ty_22struct2E__va_list_tag22 x 1>>), !cir.ptr<!ty_22struct2E__va_list_tag22>
23+
%6 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr<!cir.array<!ty_22struct2E__va_list_tag22 x 1>>), !cir.ptr<!ty_22struct2E__va_list_tag22>
24+
cir.va.copy %6 to %5 : !cir.ptr<!ty_22struct2E__va_list_tag22>, !cir.ptr<!ty_22struct2E__va_list_tag22>
25+
// MLIR: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr) -> !llvm.ptr
26+
// MLIR-NEXT: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr) -> !llvm.ptr
27+
// MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr to !llvm.ptr
28+
// MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr to !llvm.ptr
29+
// MLIR-NEXT: llvm.intr.vacopy %13 to %{{[0-9]+}} : !llvm.ptr, !llvm.ptr
30+
%7 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr<!cir.array<!ty_22struct2E__va_list_tag22 x 1>>), !cir.ptr<!ty_22struct2E__va_list_tag22>
31+
cir.va.end %7 : !cir.ptr<!ty_22struct2E__va_list_tag22>
32+
// MLIR: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr) -> !llvm.ptr
33+
// MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr to !llvm.ptr
34+
// MLIR-NEXT: llvm.intr.vaend %{{[0-9]+}} : !llvm.ptr
35+
%8 = cir.const(#cir.int<0> : !s32i) : !s32i
36+
cir.store %8, %1 : !s32i, cir.ptr <!s32i>
37+
%9 = cir.load %1 : cir.ptr <!s32i>, !s32i
38+
cir.return %9 : !s32i
39+
}
40+
}

0 commit comments

Comments
 (0)