Skip to content

Commit 03ea851

Browse files
committed
[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: 5c48027 Pull Request resolved: #95
1 parent 34b4fb7 commit 03ea851

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

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

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "mlir/IR/IRMapping.h"
3535
#include "mlir/Pass/Pass.h"
3636
#include "mlir/Pass/PassManager.h"
37+
#include "mlir/Support/LogicalResult.h"
3738
#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
3839
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
3940
#include "mlir/Target/LLVMIR/Export.h"
@@ -47,6 +48,7 @@
4748
#include "llvm/ADT/Sequence.h"
4849
#include "llvm/ADT/SmallVector.h"
4950
#include "llvm/Support/Casting.h"
51+
#include "llvm/Support/ErrorHandling.h"
5052
#include <optional>
5153

5254
using namespace cir;
@@ -482,6 +484,66 @@ class CIRConstantLowering
482484
}
483485
};
484486

487+
class CIRVAStartLowering
488+
: public mlir::OpConversionPattern<mlir::cir::VAStartOp> {
489+
public:
490+
using OpConversionPattern<mlir::cir::VAStartOp>::OpConversionPattern;
491+
492+
mlir::LogicalResult
493+
matchAndRewrite(mlir::cir::VAStartOp op, OpAdaptor adaptor,
494+
mlir::ConversionPatternRewriter &rewriter) const override {
495+
auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getI8Type());
496+
auto vaList = rewriter.create<mlir::LLVM::BitcastOp>(
497+
op.getLoc(), i8PtrTy, adaptor.getOperands().front());
498+
rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
499+
return mlir::success();
500+
}
501+
};
502+
503+
class CIRVAEndLowering : public mlir::OpConversionPattern<mlir::cir::VAEndOp> {
504+
public:
505+
using OpConversionPattern<mlir::cir::VAEndOp>::OpConversionPattern;
506+
507+
mlir::LogicalResult
508+
matchAndRewrite(mlir::cir::VAEndOp op, OpAdaptor adaptor,
509+
mlir::ConversionPatternRewriter &rewriter) const override {
510+
auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getI8Type());
511+
auto vaList = rewriter.create<mlir::LLVM::BitcastOp>(
512+
op.getLoc(), i8PtrTy, adaptor.getOperands().front());
513+
rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
514+
return mlir::success();
515+
}
516+
};
517+
518+
class CIRVACopyLowering
519+
: public mlir::OpConversionPattern<mlir::cir::VACopyOp> {
520+
public:
521+
using OpConversionPattern<mlir::cir::VACopyOp>::OpConversionPattern;
522+
523+
mlir::LogicalResult
524+
matchAndRewrite(mlir::cir::VACopyOp op, OpAdaptor adaptor,
525+
mlir::ConversionPatternRewriter &rewriter) const override {
526+
auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getI8Type());
527+
auto dstList = rewriter.create<mlir::LLVM::BitcastOp>(
528+
op.getLoc(), i8PtrTy, adaptor.getOperands().front());
529+
auto srcList = rewriter.create<mlir::LLVM::BitcastOp>(
530+
op.getLoc(), i8PtrTy, adaptor.getOperands().back());
531+
rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
532+
return mlir::success();
533+
}
534+
};
535+
536+
class CIRVAArgLowering : public mlir::OpConversionPattern<mlir::cir::VAArgOp> {
537+
public:
538+
using OpConversionPattern<mlir::cir::VAArgOp>::OpConversionPattern;
539+
540+
mlir::LogicalResult
541+
matchAndRewrite(mlir::cir::VAArgOp op, OpAdaptor adaptor,
542+
mlir::ConversionPatternRewriter &rewriter) const override {
543+
return op.emitError("cir.vaarg lowering is NYI");
544+
}
545+
};
546+
485547
class CIRFuncLowering : public mlir::OpConversionPattern<mlir::cir::FuncOp> {
486548
public:
487549
using OpConversionPattern<mlir::cir::FuncOp>::OpConversionPattern;
@@ -1021,7 +1083,8 @@ void populateCIRToLLVMConversionPatterns(mlir::RewritePatternSet &patterns,
10211083
CIRBinOpLowering, CIRLoadLowering, CIRConstantLowering,
10221084
CIRStoreLowering, CIRAllocaLowering, CIRFuncLowering,
10231085
CIRScopeOpLowering, CIRCastOpLowering, CIRIfLowering,
1024-
CIRGlobalOpLowering, CIRGetGlobalOpLowering>(
1086+
CIRGlobalOpLowering, CIRGetGlobalOpLowering, CIRVAStartLowering,
1087+
CIRVAEndLowering, CIRVACopyLowering, CIRVAArgLowering>(
10251088
converter, patterns.getContext());
10261089
}
10271090

@@ -1044,6 +1107,16 @@ mlir::LLVMTypeConverter prepareTypeConverter(mlir::MLIRContext *ctx) {
10441107
// LLVM doesn't work with signed types, so we drop the CIR signs here.
10451108
return mlir::IntegerType::get(type.getContext(), type.getWidth());
10461109
});
1110+
converter.addConversion([&](mlir::cir::StructType type) -> mlir::Type {
1111+
llvm::SmallVector<mlir::Type> llvmMembers;
1112+
for (auto ty : type.getMembers())
1113+
llvmMembers.push_back(converter.convertType(ty));
1114+
auto llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
1115+
type.getContext(), type.getTypeName());
1116+
if (llvmStruct.setBody(llvmMembers, /*isPacked=*/type.getPacked()).failed())
1117+
llvm_unreachable("Failed to set body of struct");
1118+
return llvmStruct;
1119+
});
10471120

10481121
return converter;
10491122
}
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.vastart %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.vacopy %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.vaend %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)