Skip to content

Commit 1e0d114

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 a46e15f commit 1e0d114

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;
@@ -534,6 +535,66 @@ class CIRConstantLowering
534535
}
535536
};
536537

538+
class CIRVAStartLowering
539+
: public mlir::OpConversionPattern<mlir::cir::VAStartOp> {
540+
public:
541+
using OpConversionPattern<mlir::cir::VAStartOp>::OpConversionPattern;
542+
543+
mlir::LogicalResult
544+
matchAndRewrite(mlir::cir::VAStartOp op, OpAdaptor adaptor,
545+
mlir::ConversionPatternRewriter &rewriter) const override {
546+
auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getI8Type());
547+
auto vaList = rewriter.create<mlir::LLVM::BitcastOp>(
548+
op.getLoc(), i8PtrTy, adaptor.getOperands().front());
549+
rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
550+
return mlir::success();
551+
}
552+
};
553+
554+
class CIRVAEndLowering : public mlir::OpConversionPattern<mlir::cir::VAEndOp> {
555+
public:
556+
using OpConversionPattern<mlir::cir::VAEndOp>::OpConversionPattern;
557+
558+
mlir::LogicalResult
559+
matchAndRewrite(mlir::cir::VAEndOp op, OpAdaptor adaptor,
560+
mlir::ConversionPatternRewriter &rewriter) const override {
561+
auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getI8Type());
562+
auto vaList = rewriter.create<mlir::LLVM::BitcastOp>(
563+
op.getLoc(), i8PtrTy, adaptor.getOperands().front());
564+
rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
565+
return mlir::success();
566+
}
567+
};
568+
569+
class CIRVACopyLowering
570+
: public mlir::OpConversionPattern<mlir::cir::VACopyOp> {
571+
public:
572+
using OpConversionPattern<mlir::cir::VACopyOp>::OpConversionPattern;
573+
574+
mlir::LogicalResult
575+
matchAndRewrite(mlir::cir::VACopyOp op, OpAdaptor adaptor,
576+
mlir::ConversionPatternRewriter &rewriter) const override {
577+
auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getI8Type());
578+
auto dstList = rewriter.create<mlir::LLVM::BitcastOp>(
579+
op.getLoc(), i8PtrTy, adaptor.getOperands().front());
580+
auto srcList = rewriter.create<mlir::LLVM::BitcastOp>(
581+
op.getLoc(), i8PtrTy, adaptor.getOperands().back());
582+
rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
583+
return mlir::success();
584+
}
585+
};
586+
587+
class CIRVAArgLowering : public mlir::OpConversionPattern<mlir::cir::VAArgOp> {
588+
public:
589+
using OpConversionPattern<mlir::cir::VAArgOp>::OpConversionPattern;
590+
591+
mlir::LogicalResult
592+
matchAndRewrite(mlir::cir::VAArgOp op, OpAdaptor adaptor,
593+
mlir::ConversionPatternRewriter &rewriter) const override {
594+
return op.emitError("cir.vaarg lowering is NYI");
595+
}
596+
};
597+
537598
class CIRFuncLowering : public mlir::OpConversionPattern<mlir::cir::FuncOp> {
538599
public:
539600
using OpConversionPattern<mlir::cir::FuncOp>::OpConversionPattern;
@@ -987,7 +1048,8 @@ void populateCIRToLLVMConversionPatterns(mlir::RewritePatternSet &patterns,
9871048
CIRBinOpLowering, CIRLoadLowering, CIRConstantLowering,
9881049
CIRStoreLowering, CIRAllocaLowering, CIRFuncLowering,
9891050
CIRScopeOpLowering, CIRCastOpLowering, CIRIfLowering,
990-
CIRGlobalOpLowering, CIRGetGlobalOpLowering>(
1051+
CIRGlobalOpLowering, CIRGetGlobalOpLowering, CIRVAStartLowering,
1052+
CIRVAEndLowering, CIRVACopyLowering, CIRVAArgLowering>(
9911053
converter, patterns.getContext());
9921054
}
9931055

@@ -1010,6 +1072,16 @@ mlir::LLVMTypeConverter prepareTypeConverter(mlir::MLIRContext *ctx) {
10101072
// LLVM doesn't work with signed types, so we drop the CIR signs here.
10111073
return mlir::IntegerType::get(type.getContext(), type.getWidth());
10121074
});
1075+
converter.addConversion([&](mlir::cir::StructType type) -> mlir::Type {
1076+
llvm::SmallVector<mlir::Type> llvmMembers;
1077+
for (auto ty : type.getMembers())
1078+
llvmMembers.push_back(converter.convertType(ty));
1079+
auto llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
1080+
type.getContext(), type.getTypeName());
1081+
if (llvmStruct.setBody(llvmMembers, /*isPacked=*/type.getPacked()).failed())
1082+
llvm_unreachable("Failed to set body of struct");
1083+
return llvmStruct;
1084+
});
10131085

10141086
return converter;
10151087
}
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<array<1 x struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>>>) -> !llvm.ptr<struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>>
20+
// MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr<struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>> to !llvm.ptr<i8>
21+
// MLIR-NEXT: llvm.intr.vastart %{{[0-9]+}} : !llvm.ptr<i8>
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<array<1 x struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>>>) -> !llvm.ptr<struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>>
26+
// MLIR-NEXT: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr<array<1 x struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>>>) -> !llvm.ptr<struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>>
27+
// MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr<struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>> to !llvm.ptr<i8>
28+
// MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr<struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>> to !llvm.ptr<i8>
29+
// MLIR-NEXT: llvm.intr.vacopy %13 to %{{[0-9]+}} : !llvm.ptr<i8>, !llvm.ptr<i8>
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<array<1 x struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>>>) -> !llvm.ptr<struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>>
33+
// MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : !llvm.ptr<struct<"struct.__va_list_tag", (i32, i32, ptr<i8>, ptr<i8>)>> to !llvm.ptr<i8>
34+
// MLIR-NEXT: llvm.intr.vaend %{{[0-9]+}} : !llvm.ptr<i8>
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)