Skip to content

Commit 02bef56

Browse files
authored
[CIR][LoweringPrepare] Wrap cir.va_arg lowered code in a cir.scope (#1768)
The `cir.va_arg` lowering may introduce an if-else control flow. This breaks the verifier for control flow operations, e.g., `cir.for`, where there can be only one block inside of the `cond` and `step` regions. This PR wraps the lowered code in a `cir.scope` (only if it will lower to the if-else control flow). A dded a test for `va_arg` inside for loop condition, the basic pattern is: `for (; va_arg(...););`
1 parent ccb0498 commit 02bef56

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/LoweringPrepareX86CXXABI.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,18 @@ mlir::Value LoweringPrepareX86CXXABI::lowerVAArgX86_64(
129129
builder, datalayout, valist, ty, loc),
130130
ty));
131131

132-
auto currentBlock = builder.getInsertionBlock();
132+
mlir::OpBuilder::InsertPoint scopeIP;
133+
auto scopeOp = builder.create<cir::ScopeOp>(
134+
loc,
135+
[&](mlir::OpBuilder &opBuilder, mlir::Type &yieldTy, mlir::Location loc) {
136+
scopeIP = opBuilder.saveInsertionPoint();
137+
yieldTy = op.getType();
138+
});
139+
140+
mlir::Block *contBlock = scopeIP.getBlock();
141+
142+
mlir::Block *currentBlock = builder.createBlock(contBlock);
143+
builder.setInsertionPointToEnd(currentBlock);
133144

134145
// AMD64-ABI 3.5.7p5: Step 2. Compute num_gp to hold the number of
135146
// general purpose registers needed to pass type and num_fp to hold
@@ -163,7 +174,6 @@ mlir::Value LoweringPrepareX86CXXABI::lowerVAArgX86_64(
163174
inRegs = inRegs ? builder.createAnd(inRegs, fitsInFP) : fitsInFP;
164175
}
165176

166-
mlir::Block *contBlock = currentBlock->splitBlock(op);
167177
mlir::Block *inRegBlock = builder.createBlock(contBlock);
168178
mlir::Block *inMemBlock = builder.createBlock(contBlock);
169179
builder.setInsertionPointToEnd(currentBlock);
@@ -338,14 +348,19 @@ mlir::Value LoweringPrepareX86CXXABI::lowerVAArgX86_64(
338348
buildX86_64VAArgFromMemory(builder, datalayout, valist, ty, loc);
339349
builder.create<BrOp>(loc, mlir::ValueRange{memAddr}, contBlock);
340350

341-
// Return the appropriate result.
351+
// Yield the appropriate result.
342352
builder.setInsertionPointToStart(contBlock);
343353
mlir::Value res_addr = contBlock->addArgument(regAddr.getType(), loc);
344354

345-
return alignment
346-
? builder.createAlignedLoad(
347-
loc, builder.createPtrBitcast(res_addr, ty), alignment)
348-
: builder.createLoad(loc, builder.createPtrBitcast(res_addr, ty));
355+
mlir::Value result =
356+
alignment
357+
? builder.createAlignedLoad(
358+
loc, builder.createPtrBitcast(res_addr, ty), alignment)
359+
: builder.createLoad(loc, builder.createPtrBitcast(res_addr, ty));
360+
361+
builder.create<cir::YieldOp>(loc, result);
362+
363+
return scopeOp.getResult(0);
349364
}
350365
} // namespace
351366

clang/test/CIR/Lowering/var-arg-x86_64.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ double f1(int n, ...) {
4747
// CIR: [[VASTED_VA_LIST:%.+]] = cir.cast(array_to_ptrdecay, [[VA_LIST_ALLOCA]]
4848
// CIR: cir.va.start [[VASTED_VA_LIST]]
4949
// CIR: [[VASTED_VA_LIST:%.+]] = cir.cast(array_to_ptrdecay, [[VA_LIST_ALLOCA]]
50+
// CIR: [[VAARG_RESULT:%.+]] = cir.scope
5051
// CIR: [[FP_OFFSET_P:%.+]] = cir.get_member [[VASTED_VA_LIST]][1] {name = "fp_offset"}
5152
// CIR: [[FP_OFFSET:%.+]] = cir.load [[FP_OFFSET_P]]
5253
// CIR: [[OFFSET_CONSTANT:%.+]] = cir.const #cir.int<160>
@@ -75,7 +76,9 @@ double f1(int n, ...) {
7576
// CIR: ^[[ContBlock]]([[ARG:.+]]: !cir.ptr
7677
// CIR: [[CASTED_ARG_P:%.+]] = cir.cast(bitcast, [[ARG]]
7778
// CIR: [[CASTED_ARG:%.+]] = cir.load align(16) [[CASTED_ARG_P]]
78-
// CIR: cir.store{{.*}} [[CASTED_ARG]], [[RES]]
79+
// CIR: cir.yield [[CASTED_ARG]]
80+
//
81+
// CIR: cir.store{{.*}} [[VAARG_RESULT]], [[RES]]
7982
long double f2(int n, ...) {
8083
va_list valist;
8184
va_start(valist, n);
@@ -185,3 +188,23 @@ const char *f3(va_list args) {
185188

186189
// ...
187190
// CIR: cir.return
191+
192+
void f4(va_list args) {
193+
for (; va_arg(args, int); );
194+
}
195+
// CIR-LABEL: cir.func dso_local @f4
196+
// CIR: cir.for : cond {
197+
// CIR: %[[VALIST:.*]] = cir.load align(8) %[[VALIST_VAR]] : !cir.ptr<!cir.ptr<!rec___va_list_tag>>, !cir.ptr<!rec___va_list_tag>
198+
// CIR: %[[VAARG_RESULT:.*]] = cir.scope {
199+
// ... // The contents are tested elsewhere.
200+
// CIR: cir.yield {{.*}} : !s32i
201+
// CIR: } : !s32i
202+
// CIR: %[[CMP:.*]] = cir.cast(int_to_bool, %[[VAARG_RESULT]] : !s32i), !cir.bool
203+
// CIR: cir.condition(%[[CMP]])
204+
// CIR: } body {
205+
// CIR: cir.yield
206+
// CIR: } step {
207+
// CIR: cir.yield
208+
// CIR: }
209+
// CIR: cir.return
210+
// CIR: }

0 commit comments

Comments
 (0)