Skip to content

Commit d49c098

Browse files
committed
[CIR] Add InlineAsmOp lowering to LLVM
1 parent 40788c8 commit d49c098

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed

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

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,6 +2263,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
22632263
patterns.add<CIRToLLVMCastOpLowering>(converter, patterns.getContext(), dl);
22642264
patterns.add<CIRToLLVMPtrStrideOpLowering>(converter, patterns.getContext(),
22652265
dl);
2266+
patterns.add<CIRToLLVMInlineAsmOpLowering>(converter, patterns.getContext(),
2267+
dl);
22662268
patterns.add<
22672269
// clang-format off
22682270
CIRToLLVMAssumeOpLowering,
@@ -2896,6 +2898,71 @@ mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
28962898
return mlir::success();
28972899
}
28982900

2901+
mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
2902+
cir::InlineAsmOp op, OpAdaptor adaptor,
2903+
mlir::ConversionPatternRewriter &rewriter) const {
2904+
mlir::Type llResTy;
2905+
if (op.getNumResults())
2906+
llResTy = getTypeConverter()->convertType(op.getType(0));
2907+
2908+
auto dialect = op.getAsmFlavor();
2909+
auto llDialect = dialect == cir::AsmFlavor::x86_att
2910+
? mlir::LLVM::AsmDialect::AD_ATT
2911+
: mlir::LLVM::AsmDialect::AD_Intel;
2912+
2913+
SmallVector<mlir::Attribute> opAttrs;
2914+
auto llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
2915+
2916+
// this is for the lowering to LLVM from LLVM dialect. Otherwise, if we
2917+
// don't have the result (i.e. void type as a result of operation), the
2918+
// element type attribute will be attached to the whole instruction, but not
2919+
// to the operand
2920+
if (!op.getNumResults())
2921+
opAttrs.push_back(mlir::Attribute());
2922+
2923+
SmallVector<mlir::Value> llvmOperands;
2924+
SmallVector<mlir::Value> cirOperands;
2925+
auto llvmAsmOps = adaptor.getAsmOperands();
2926+
auto cirAsmOps = op.getAsmOperands();
2927+
for (size_t i = 0; i < llvmAsmOps.size(); ++i) {
2928+
auto llvmOps = llvmAsmOps[i];
2929+
auto cirOps = cirAsmOps[i];
2930+
llvmOperands.append(llvmOps.begin(), llvmOps.end());
2931+
cirOperands.append(cirOps.begin(), cirOps.end());
2932+
}
2933+
2934+
// so far we infer the llvm dialect element type attr from
2935+
// CIR operand type.
2936+
auto cirOpAttrs = op.getOperandAttrs();
2937+
for (std::size_t i = 0; i < cirOpAttrs.size(); ++i) {
2938+
if (!cirOpAttrs[i]) {
2939+
opAttrs.push_back(mlir::Attribute());
2940+
continue;
2941+
}
2942+
2943+
SmallVector<mlir::NamedAttribute> attrs;
2944+
auto typ = cast<cir::PointerType>(cirOperands[i].getType());
2945+
auto typAttr = mlir::TypeAttr::get(convertTypeForMemory(
2946+
*getTypeConverter(), dataLayout, typ.getPointee()));
2947+
2948+
attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
2949+
auto newDict = rewriter.getDictionaryAttr(attrs);
2950+
opAttrs.push_back(newDict);
2951+
}
2952+
2953+
rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
2954+
op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
2955+
op.getSideEffectsAttr(),
2956+
/*is_align_stack*/ mlir::UnitAttr(),
2957+
/*tail_call_kind*/
2958+
mlir::LLVM::TailCallKindAttr::get(
2959+
getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
2960+
mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
2961+
rewriter.getArrayAttr(opAttrs));
2962+
2963+
return mlir::success();
2964+
}
2965+
28992966
std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
29002967
return std::make_unique<ConvertCIRToLLVMPass>();
29012968
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,23 @@ class CIRToLLVMGetBitfieldOpLowering
648648
mlir::ConversionPatternRewriter &) const override;
649649
};
650650

651+
class CIRToLLVMInlineAsmOpLowering
652+
: public mlir::OpConversionPattern<cir::InlineAsmOp> {
653+
mlir::DataLayout const &dataLayout;
654+
655+
public:
656+
CIRToLLVMInlineAsmOpLowering(const mlir::TypeConverter &typeConverter,
657+
mlir::MLIRContext *context,
658+
mlir::DataLayout const &dataLayout)
659+
: OpConversionPattern(typeConverter, context), dataLayout(dataLayout) {}
660+
661+
using mlir::OpConversionPattern<cir::InlineAsmOp>::OpConversionPattern;
662+
663+
mlir::LogicalResult
664+
matchAndRewrite(cir::InlineAsmOp op, OpAdaptor,
665+
mlir::ConversionPatternRewriter &) const override;
666+
};
667+
651668
} // namespace direct
652669
} // namespace cir
653670

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// RUN: cir-translate %s -cir-to-llvmir --target x86_64-unknown-linux-gnu --disable-cc-lowering | FileCheck %s
2+
3+
!s32i = !cir.int<s, 32>
4+
!u32i = !cir.int<u, 32>
5+
6+
module {
7+
cir.func @f1() {
8+
// CHECK: call void asm "", "~{dirflag},~{fpsr},~{flags}"()
9+
cir.asm(x86_att,
10+
out = [],
11+
in = [],
12+
in_out = [],
13+
{"" "~{dirflag},~{fpsr},~{flags}"})
14+
cir.return
15+
}
16+
17+
cir.func @f2() {
18+
// CHECK: call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"()
19+
cir.asm(x86_att,
20+
out = [],
21+
in = [],
22+
in_out = [],
23+
{"" "~{dirflag},~{fpsr},~{flags}"}) side_effects
24+
cir.return
25+
}
26+
27+
cir.func @f3() {
28+
// CHECK: call void asm sideeffect "abc", "~{dirflag},~{fpsr},~{flags}"()
29+
cir.asm(x86_att,
30+
out = [],
31+
in = [],
32+
in_out = [],
33+
{"abc" "~{dirflag},~{fpsr},~{flags}"}) side_effects
34+
cir.return
35+
}
36+
37+
cir.func @f4(%arg0: !s32i) {
38+
%0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
39+
cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i>
40+
// CHECK: call void asm sideeffect "", "*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) %2)
41+
cir.asm(x86_att,
42+
out = [],
43+
in = [%0 : !cir.ptr<!s32i> (maybe_memory)],
44+
in_out = [],
45+
{"" "*m,~{dirflag},~{fpsr},~{flags}"}) side_effects
46+
cir.return
47+
}
48+
49+
cir.func @f5() {
50+
// CHECK: call void asm inteldialect "", "~{dirflag},~{fpsr},~{flags}"()
51+
cir.asm(x86_intel,
52+
out = [],
53+
in = [],
54+
in_out = [],
55+
{"" "~{dirflag},~{fpsr},~{flags}"})
56+
cir.return
57+
}
58+
59+
cir.func @f6() -> !s32i {
60+
%0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
61+
// CHECK: %2 = call i32 asm sideeffect "movl $$42, $0", "=r,~{dirflag},~{fpsr},~{flags}"()
62+
%1 = cir.asm(x86_att,
63+
out = [],
64+
in = [],
65+
in_out = [],
66+
{"movl $$42, $0" "=r,~{dirflag},~{fpsr},~{flags}"}) side_effects -> !s32i
67+
cir.store align(4) %1, %0 : !s32i, !cir.ptr<!s32i>
68+
%3 = cir.load align(4) %0 : !cir.ptr<!s32i>, !s32i
69+
cir.return %3 : !s32i
70+
}
71+
72+
cir.func @f7(%arg0: !u32i) -> !u32i {
73+
%0 = cir.alloca !u32i, !cir.ptr<!u32i>, ["x", init] {alignment = 4 : i64}
74+
cir.store %arg0, %0 : !u32i, !cir.ptr<!u32i>
75+
%1 = cir.load align(4) %0 : !cir.ptr<!u32i>, !u32i
76+
// CHECK: %4 = call i32 asm sideeffect "addl $$42, $0", "=r,0,~{dirflag},~{fpsr},~{flags}"(i32 %3)
77+
%2 = cir.asm(x86_att,
78+
out = [],
79+
in = [],
80+
in_out = [%1 : !u32i],
81+
{"addl $$42, $0" "=r,0,~{dirflag},~{fpsr},~{flags}"}) side_effects -> !u32i
82+
cir.store align(4) %2, %0 : !u32i, !cir.ptr<!u32i>
83+
%3 = cir.load align(4) %0 : !cir.ptr<!u32i>, !u32i
84+
cir.return %3 : !u32i
85+
}
86+
}

0 commit comments

Comments
 (0)