Skip to content

Commit a7399fd

Browse files
Update test to unmap before read
Created using spr 1.3.6
2 parents a03db21 + 20a8299 commit a7399fd

File tree

110 files changed

+2875
-1543
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+2875
-1543
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2254,6 +2254,87 @@ def CIR_StackRestoreOp : CIR_Op<"stackrestore"> {
22542254
let assemblyFormat = "$ptr attr-dict `:` qualified(type($ptr))";
22552255
}
22562256

2257+
//===----------------------------------------------------------------------===//
2258+
// InlineAsmOp
2259+
//===----------------------------------------------------------------------===//
2260+
2261+
def CIR_AsmFlavor : CIR_I32EnumAttr<"AsmFlavor", "ATT or Intel",
2262+
[I32EnumAttrCase<"x86_att", 0>,
2263+
I32EnumAttrCase<"x86_intel", 1>]>;
2264+
2265+
def CIR_InlineAsmOp : CIR_Op<"asm", [RecursiveMemoryEffects]> {
2266+
let description = [{
2267+
The `cir.asm` operation represents C/C++ asm inline.
2268+
2269+
CIR constraints strings follow the same rules that are established for
2270+
the C level assembler constraints with several differences caused by
2271+
clang::AsmStmt processing.
2272+
2273+
Thus, numbers that appears in the constraint string may also refer to:
2274+
- the output variable index referenced by the input operands.
2275+
- the index of early-clobber operand
2276+
2277+
Operand attributes are a storage, where each element corresponds to the
2278+
operand with the same index. The first index relates to the operation
2279+
result (if any).
2280+
The operands themselves are stored as VariadicOfVariadic in the following
2281+
order: output, input and then in/out operands. When several output operands
2282+
are present, the result type may be represented as an anonymous record type.
2283+
2284+
Example:
2285+
```C++
2286+
__asm__("foo" : : : );
2287+
__asm__("bar $42 %[val]" : [val] "=r" (x), "+&r"(x));
2288+
__asm__("baz $42 %[val]" : [val] "=r" (x), "+&r"(x) : "[val]"(y));
2289+
```
2290+
2291+
```mlir
2292+
!rec_22anon2E022 = !cir.record<struct "anon.0" {!cir.int<s, 32>, !cir.int<s, 32>}>
2293+
!rec_22anon2E122 = !cir.record<struct "anon.1" {!cir.int<s, 32>, !cir.int<s, 32>}>
2294+
...
2295+
%0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
2296+
%1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["y", init]
2297+
...
2298+
%2 = cir.load %0 : !cir.ptr<!s32i>, !s32i
2299+
%3 = cir.load %1 : !cir.ptr<!s32i>, !s32i
2300+
2301+
cir.asm(x86_att,
2302+
out = [],
2303+
in = [],
2304+
in_out = [],
2305+
{"foo" "~{dirflag},~{fpsr},~{flags}"}) side_effects
2306+
2307+
cir.asm(x86_att,
2308+
out = [],
2309+
in = [],
2310+
in_out = [%2 : !s32i],
2311+
{"bar $$42 $0" "=r,=&r,1,~{dirflag},~{fpsr},~{flags}"}) -> !rec_22anon2E022
2312+
2313+
cir.asm(x86_att,
2314+
out = [],
2315+
in = [%3 : !s32i],
2316+
in_out = [%2 : !s32i],
2317+
{"baz $$42 $0" "=r,=&r,0,1,~{dirflag},~{fpsr},~{flags}"}) -> !rec_22anon2E122
2318+
```
2319+
}];
2320+
2321+
let results = (outs Optional<CIR_AnyType>:$res);
2322+
2323+
let arguments =
2324+
(ins VariadicOfVariadic<AnyType, "operands_segments">:$asm_operands,
2325+
StrAttr:$asm_string, StrAttr:$constraints, UnitAttr:$side_effects,
2326+
CIR_AsmFlavor:$asm_flavor, ArrayAttr:$operand_attrs,
2327+
DenseI32ArrayAttr:$operands_segments);
2328+
2329+
let builders = [OpBuilder<(ins
2330+
"llvm::ArrayRef<mlir::ValueRange>":$asmOperands,
2331+
"llvm::StringRef":$asmString, "llvm::StringRef":$constraints,
2332+
"bool":$sideEffects, "AsmFlavor":$asmFlavor,
2333+
"llvm::ArrayRef<mlir::Attribute>":$operandAttrs)>];
2334+
2335+
let hasCustomAssemblyFormat = 1;
2336+
}
2337+
22572338
//===----------------------------------------------------------------------===//
22582339
// UnreachableOp
22592340
//===----------------------------------------------------------------------===//

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,6 +2419,209 @@ OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
24192419
return IntAttr::get(input.getContext(), input.getType(), resultValue);
24202420
}
24212421

2422+
//===----------------------------------------------------------------------===//
2423+
// InlineAsmOp
2424+
//===----------------------------------------------------------------------===//
2425+
2426+
void cir::InlineAsmOp::print(OpAsmPrinter &p) {
2427+
p << '(' << getAsmFlavor() << ", ";
2428+
p.increaseIndent();
2429+
p.printNewline();
2430+
2431+
llvm::SmallVector<std::string, 3> names{"out", "in", "in_out"};
2432+
auto *nameIt = names.begin();
2433+
auto *attrIt = getOperandAttrs().begin();
2434+
2435+
for (mlir::OperandRange ops : getAsmOperands()) {
2436+
p << *nameIt << " = ";
2437+
2438+
p << '[';
2439+
llvm::interleaveComma(llvm::make_range(ops.begin(), ops.end()), p,
2440+
[&](Value value) {
2441+
p.printOperand(value);
2442+
p << " : " << value.getType();
2443+
if (*attrIt)
2444+
p << " (maybe_memory)";
2445+
attrIt++;
2446+
});
2447+
p << "],";
2448+
p.printNewline();
2449+
++nameIt;
2450+
}
2451+
2452+
p << "{";
2453+
p.printString(getAsmString());
2454+
p << " ";
2455+
p.printString(getConstraints());
2456+
p << "}";
2457+
p.decreaseIndent();
2458+
p << ')';
2459+
if (getSideEffects())
2460+
p << " side_effects";
2461+
2462+
std::array elidedAttrs{
2463+
llvm::StringRef("asm_flavor"), llvm::StringRef("asm_string"),
2464+
llvm::StringRef("constraints"), llvm::StringRef("operand_attrs"),
2465+
llvm::StringRef("operands_segments"), llvm::StringRef("side_effects")};
2466+
p.printOptionalAttrDict(getOperation()->getAttrs(), elidedAttrs);
2467+
2468+
if (auto v = getRes())
2469+
p << " -> " << v.getType();
2470+
}
2471+
2472+
void cir::InlineAsmOp::build(OpBuilder &odsBuilder, OperationState &odsState,
2473+
ArrayRef<ValueRange> asmOperands,
2474+
StringRef asmString, StringRef constraints,
2475+
bool sideEffects, cir::AsmFlavor asmFlavor,
2476+
ArrayRef<Attribute> operandAttrs) {
2477+
// Set up the operands_segments for VariadicOfVariadic
2478+
SmallVector<int32_t> segments;
2479+
for (auto operandRange : asmOperands) {
2480+
segments.push_back(operandRange.size());
2481+
odsState.addOperands(operandRange);
2482+
}
2483+
2484+
odsState.addAttribute(
2485+
"operands_segments",
2486+
DenseI32ArrayAttr::get(odsBuilder.getContext(), segments));
2487+
odsState.addAttribute("asm_string", odsBuilder.getStringAttr(asmString));
2488+
odsState.addAttribute("constraints", odsBuilder.getStringAttr(constraints));
2489+
odsState.addAttribute("asm_flavor",
2490+
AsmFlavorAttr::get(odsBuilder.getContext(), asmFlavor));
2491+
2492+
if (sideEffects)
2493+
odsState.addAttribute("side_effects", odsBuilder.getUnitAttr());
2494+
2495+
odsState.addAttribute("operand_attrs", odsBuilder.getArrayAttr(operandAttrs));
2496+
}
2497+
2498+
ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
2499+
OperationState &result) {
2500+
llvm::SmallVector<mlir::Attribute> operandAttrs;
2501+
llvm::SmallVector<int32_t> operandsGroupSizes;
2502+
std::string asmString, constraints;
2503+
Type resType;
2504+
MLIRContext *ctxt = parser.getBuilder().getContext();
2505+
2506+
auto error = [&](const Twine &msg) -> LogicalResult {
2507+
return parser.emitError(parser.getCurrentLocation(), msg);
2508+
};
2509+
2510+
auto expected = [&](const std::string &c) {
2511+
return error("expected '" + c + "'");
2512+
};
2513+
2514+
if (parser.parseLParen().failed())
2515+
return expected("(");
2516+
2517+
auto flavor = FieldParser<AsmFlavor, AsmFlavor>::parse(parser);
2518+
if (failed(flavor))
2519+
return error("Unknown AsmFlavor");
2520+
2521+
if (parser.parseComma().failed())
2522+
return expected(",");
2523+
2524+
auto parseValue = [&](Value &v) {
2525+
OpAsmParser::UnresolvedOperand op;
2526+
2527+
if (parser.parseOperand(op) || parser.parseColon())
2528+
return error("can't parse operand");
2529+
2530+
Type typ;
2531+
if (parser.parseType(typ).failed())
2532+
return error("can't parse operand type");
2533+
llvm::SmallVector<mlir::Value> tmp;
2534+
if (parser.resolveOperand(op, typ, tmp))
2535+
return error("can't resolve operand");
2536+
v = tmp[0];
2537+
return mlir::success();
2538+
};
2539+
2540+
auto parseOperands = [&](llvm::StringRef name) {
2541+
if (parser.parseKeyword(name).failed())
2542+
return error("expected " + name + " operands here");
2543+
if (parser.parseEqual().failed())
2544+
return expected("=");
2545+
if (parser.parseLSquare().failed())
2546+
return expected("[");
2547+
2548+
int size = 0;
2549+
if (parser.parseOptionalRSquare().succeeded()) {
2550+
operandsGroupSizes.push_back(size);
2551+
if (parser.parseComma())
2552+
return expected(",");
2553+
return mlir::success();
2554+
}
2555+
2556+
auto parseOperand = [&]() {
2557+
Value val;
2558+
if (parseValue(val).succeeded()) {
2559+
result.operands.push_back(val);
2560+
size++;
2561+
2562+
if (parser.parseOptionalLParen().failed()) {
2563+
operandAttrs.push_back(mlir::Attribute());
2564+
return mlir::success();
2565+
}
2566+
2567+
if (parser.parseKeyword("maybe_memory").succeeded()) {
2568+
operandAttrs.push_back(mlir::UnitAttr::get(ctxt));
2569+
if (parser.parseRParen())
2570+
return expected(")");
2571+
return mlir::success();
2572+
} else {
2573+
return expected("maybe_memory");
2574+
}
2575+
}
2576+
return mlir::failure();
2577+
};
2578+
2579+
if (parser.parseCommaSeparatedList(parseOperand).failed())
2580+
return mlir::failure();
2581+
2582+
if (parser.parseRSquare().failed() || parser.parseComma().failed())
2583+
return expected("]");
2584+
operandsGroupSizes.push_back(size);
2585+
return mlir::success();
2586+
};
2587+
2588+
if (parseOperands("out").failed() || parseOperands("in").failed() ||
2589+
parseOperands("in_out").failed())
2590+
return error("failed to parse operands");
2591+
2592+
if (parser.parseLBrace())
2593+
return expected("{");
2594+
if (parser.parseString(&asmString))
2595+
return error("asm string parsing failed");
2596+
if (parser.parseString(&constraints))
2597+
return error("constraints string parsing failed");
2598+
if (parser.parseRBrace())
2599+
return expected("}");
2600+
if (parser.parseRParen())
2601+
return expected(")");
2602+
2603+
if (parser.parseOptionalKeyword("side_effects").succeeded())
2604+
result.attributes.set("side_effects", UnitAttr::get(ctxt));
2605+
2606+
if (parser.parseOptionalArrow().succeeded() &&
2607+
parser.parseType(resType).failed())
2608+
return mlir::failure();
2609+
2610+
if (parser.parseOptionalAttrDict(result.attributes).failed())
2611+
return mlir::failure();
2612+
2613+
result.attributes.set("asm_flavor", AsmFlavorAttr::get(ctxt, *flavor));
2614+
result.attributes.set("asm_string", StringAttr::get(ctxt, asmString));
2615+
result.attributes.set("constraints", StringAttr::get(ctxt, constraints));
2616+
result.attributes.set("operand_attrs", ArrayAttr::get(ctxt, operandAttrs));
2617+
result.getOrAddProperties<InlineAsmOp::Properties>().operands_segments =
2618+
parser.getBuilder().getDenseI32ArrayAttr(operandsGroupSizes);
2619+
if (resType)
2620+
result.addTypes(TypeRange{resType});
2621+
2622+
return mlir::success();
2623+
}
2624+
24222625
//===----------------------------------------------------------------------===//
24232626
// TableGen'd op method definitions
24242627
//===----------------------------------------------------------------------===//

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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
22762276
patterns.add<CIRToLLVMCastOpLowering>(converter, patterns.getContext(), dl);
22772277
patterns.add<CIRToLLVMPtrStrideOpLowering>(converter, patterns.getContext(),
22782278
dl);
2279+
patterns.add<CIRToLLVMInlineAsmOpLowering>(converter, patterns.getContext(),
2280+
dl);
22792281
patterns.add<
22802282
// clang-format off
22812283
CIRToLLVMAssumeOpLowering,
@@ -2956,6 +2958,68 @@ mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
29562958
return mlir::success();
29572959
}
29582960

2961+
mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
2962+
cir::InlineAsmOp op, OpAdaptor adaptor,
2963+
mlir::ConversionPatternRewriter &rewriter) const {
2964+
mlir::Type llResTy;
2965+
if (op.getNumResults())
2966+
llResTy = getTypeConverter()->convertType(op.getType(0));
2967+
2968+
cir::AsmFlavor dialect = op.getAsmFlavor();
2969+
mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
2970+
? mlir::LLVM::AsmDialect::AD_ATT
2971+
: mlir::LLVM::AsmDialect::AD_Intel;
2972+
2973+
SmallVector<mlir::Attribute> opAttrs;
2974+
StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
2975+
2976+
// this is for the lowering to LLVM from LLVM dialect. Otherwise, if we
2977+
// don't have the result (i.e. void type as a result of operation), the
2978+
// element type attribute will be attached to the whole instruction, but not
2979+
// to the operand
2980+
if (!op.getNumResults())
2981+
opAttrs.push_back(mlir::Attribute());
2982+
2983+
SmallVector<mlir::Value> llvmOperands;
2984+
SmallVector<mlir::Value> cirOperands;
2985+
for (auto const&[llvmOp, cirOp] :
2986+
zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
2987+
append_range(llvmOperands, llvmOp);
2988+
append_range(cirOperands, cirOp);
2989+
}
2990+
2991+
// so far we infer the llvm dialect element type attr from
2992+
// CIR operand type.
2993+
for (auto const&[cirOpAttr, cirOp] : zip(op.getOperandAttrs(), cirOperands)) {
2994+
if (!cirOpAttr) {
2995+
opAttrs.push_back(mlir::Attribute());
2996+
continue;
2997+
}
2998+
2999+
llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
3000+
cir::PointerType typ =
3001+
mlir::cast<cir::PointerType>(cirOp.getType());
3002+
mlir::TypeAttr typAttr = mlir::TypeAttr::get(convertTypeForMemory(
3003+
*getTypeConverter(), dataLayout, typ.getPointee()));
3004+
3005+
attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
3006+
mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
3007+
opAttrs.push_back(newDict);
3008+
}
3009+
3010+
rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
3011+
op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
3012+
op.getSideEffectsAttr(),
3013+
/*is_align_stack*/ mlir::UnitAttr(),
3014+
/*tail_call_kind*/
3015+
mlir::LLVM::TailCallKindAttr::get(
3016+
getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
3017+
mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
3018+
rewriter.getArrayAttr(opAttrs));
3019+
3020+
return mlir::success();
3021+
}
3022+
29593023
std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
29603024
return std::make_unique<ConvertCIRToLLVMPass>();
29613025
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,23 @@ class CIRToLLVMFAbsOpLowering : public mlir::OpConversionPattern<cir::FAbsOp> {
667667
mlir::ConversionPatternRewriter &) const override;
668668
};
669669

670+
class CIRToLLVMInlineAsmOpLowering
671+
: public mlir::OpConversionPattern<cir::InlineAsmOp> {
672+
mlir::DataLayout const &dataLayout;
673+
674+
public:
675+
CIRToLLVMInlineAsmOpLowering(const mlir::TypeConverter &typeConverter,
676+
mlir::MLIRContext *context,
677+
mlir::DataLayout const &dataLayout)
678+
: OpConversionPattern(typeConverter, context), dataLayout(dataLayout) {}
679+
680+
using mlir::OpConversionPattern<cir::InlineAsmOp>::OpConversionPattern;
681+
682+
mlir::LogicalResult
683+
matchAndRewrite(cir::InlineAsmOp op, OpAdaptor,
684+
mlir::ConversionPatternRewriter &) const override;
685+
};
686+
670687
} // namespace direct
671688
} // namespace cir
672689

0 commit comments

Comments
 (0)