|
20 | 20 | #include "clang/CIR/Dialect/IR/CIRAttrs.h"
|
21 | 21 | #include "clang/CIR/Dialect/IR/CIRDialect.h"
|
22 | 22 |
|
23 |
| -using namespace cir; |
| 23 | +using cir::CIRBaseBuilderTy; |
| 24 | +using cir::LoweringPrepareCXXABI; |
| 25 | +using cir::MissingFeatures; |
| 26 | +using namespace mlir; |
| 27 | +using namespace mlir::cir; |
24 | 28 |
|
25 | 29 | namespace {
|
26 | 30 |
|
27 | 31 | class LoweringPrepareItaniumCXXABI : public LoweringPrepareCXXABI {
|
28 | 32 | public:
|
29 | 33 | mlir::Value lowerDynamicCast(CIRBaseBuilderTy &builder,
|
30 | 34 | mlir::cir::DynamicCastOp op) override;
|
| 35 | + mlir::Value lowerVAArg(CIRBaseBuilderTy &builder, |
| 36 | + mlir::cir::VAArgOp op) override; |
31 | 37 | };
|
32 | 38 |
|
33 | 39 | } // namespace
|
@@ -115,3 +121,100 @@ LoweringPrepareItaniumCXXABI::lowerDynamicCast(CIRBaseBuilderTy &builder,
|
115 | 121 | })
|
116 | 122 | .getResult();
|
117 | 123 | }
|
| 124 | + |
| 125 | +static mlir::Value createGetMemberOp(CIRBaseBuilderTy &builder, |
| 126 | + mlir::Location &loc, mlir::Value structPtr, |
| 127 | + const char *fldName, unsigned idx) { |
| 128 | + |
| 129 | + assert(structPtr.getType().isa<mlir::cir::PointerType>()); |
| 130 | + auto structBaseTy = |
| 131 | + structPtr.getType().cast<mlir::cir::PointerType>().getPointee(); |
| 132 | + assert(structBaseTy.isa<mlir::cir::StructType>()); |
| 133 | + auto fldTy = structBaseTy.cast<mlir::cir::StructType>().getMembers()[idx]; |
| 134 | + auto fldPtrTy = ::mlir::cir::PointerType::get(builder.getContext(), fldTy); |
| 135 | + return builder.create<mlir::cir::GetMemberOp>(loc, fldPtrTy, structPtr, |
| 136 | + fldName, idx); |
| 137 | +} |
| 138 | + |
| 139 | +mlir::Value LoweringPrepareItaniumCXXABI::lowerVAArg(CIRBaseBuilderTy &builder, |
| 140 | + mlir::cir::VAArgOp op) { |
| 141 | + auto loc = op->getLoc(); |
| 142 | + auto valist = op->getOperand(0); |
| 143 | + auto opResTy = op.getType(); |
| 144 | + bool isFloatingType = |
| 145 | + opResTy.isa<mlir::cir::SingleType, mlir::cir::DoubleType>(); |
| 146 | + auto offsP = createGetMemberOp(builder, loc, valist, |
| 147 | + isFloatingType ? "vr_offs" : "gr_offs", |
| 148 | + isFloatingType ? 4 : 3); |
| 149 | + auto offs = builder.create<mlir::cir::LoadOp>(loc, offsP); |
| 150 | + auto boolTy = builder.getBoolTy(); |
| 151 | + auto zeroValue = builder.create<mlir::cir::ConstantOp>( |
| 152 | + loc, offs.getType(), mlir::cir::IntAttr::get(offs.getType(), 0)); |
| 153 | + auto cmpRes = builder.create<mlir::cir::CmpOp>(loc, boolTy, CmpOpKind::ge, |
| 154 | + offs, zeroValue); |
| 155 | + auto curInsertionP = builder.saveInsertionPoint(); |
| 156 | + auto currentBlock = builder.getInsertionBlock(); |
| 157 | + |
| 158 | + auto maybeRegBlock = builder.createBlock(builder.getBlock()->getParent()); |
| 159 | + auto inRegBlock = builder.createBlock(builder.getBlock()->getParent()); |
| 160 | + auto onStackBlock = builder.createBlock(builder.getBlock()->getParent()); |
| 161 | + |
| 162 | + builder.restoreInsertionPoint(curInsertionP); |
| 163 | + builder.create<mlir::cir::BrCondOp>(loc, cmpRes, onStackBlock, maybeRegBlock); |
| 164 | + auto newEndBlock = currentBlock->splitBlock(op); |
| 165 | + |
| 166 | + builder.setInsertionPointToEnd(onStackBlock); |
| 167 | + auto stackP = createGetMemberOp(builder, loc, valist, "stack", 0); |
| 168 | + auto stack = builder.create<mlir::cir::LoadOp>(loc, stackP); |
| 169 | + auto ptrDiffTy = |
| 170 | + mlir::cir::IntType::get(builder.getContext(), 64, /*signed=*/false); |
| 171 | + auto eight = builder.create<mlir::cir::ConstantOp>( |
| 172 | + loc, ptrDiffTy, mlir::cir::IntAttr::get(ptrDiffTy, 8)); |
| 173 | + auto i8Ty = IntegerType::get(builder.getContext(), 8); |
| 174 | + auto i8PtrTy = PointerType::get(builder.getContext(), i8Ty); |
| 175 | + auto castStack = |
| 176 | + builder.createCast(mlir::cir::CastKind::bitcast, stack, i8PtrTy); |
| 177 | + auto newStackAsi8Ptr = builder.create<mlir::cir::PtrStrideOp>( |
| 178 | + loc, castStack.getType(), castStack, eight); |
| 179 | + auto newStack = builder.createCast(mlir::cir::CastKind::bitcast, |
| 180 | + newStackAsi8Ptr, stack.getType()); |
| 181 | + builder.createStore(loc, newStack, stackP); |
| 182 | + builder.create<mlir::cir::BrOp>(loc, mlir::ValueRange{stack}, newEndBlock); |
| 183 | + |
| 184 | + builder.setInsertionPointToEnd(maybeRegBlock); |
| 185 | + auto boundaryValue = builder.create<mlir::cir::ConstantOp>( |
| 186 | + loc, offs.getType(), |
| 187 | + mlir::cir::IntAttr::get(offs.getType(), isFloatingType ? 16 : 8)); |
| 188 | + auto newRegsOffs = builder.create<mlir::cir::BinOp>( |
| 189 | + loc, offs.getType(), mlir::cir::BinOpKind::Add, offs, boundaryValue); |
| 190 | + builder.createStore(loc, newRegsOffs, offsP); |
| 191 | + auto maybeRegCmpRes = builder.create<mlir::cir::CmpOp>( |
| 192 | + loc, boolTy, CmpOpKind::le, newRegsOffs, zeroValue); |
| 193 | + builder.create<mlir::cir::BrCondOp>(loc, maybeRegCmpRes, inRegBlock, |
| 194 | + onStackBlock); |
| 195 | + |
| 196 | + builder.setInsertionPointToEnd(inRegBlock); |
| 197 | + auto regTopP = createGetMemberOp(builder, loc, valist, |
| 198 | + isFloatingType ? "vr_top" : "gr_top", |
| 199 | + isFloatingType ? 2 : 1); |
| 200 | + auto regTop = builder.create<mlir::cir::LoadOp>(loc, regTopP); |
| 201 | + auto castRegTop = |
| 202 | + builder.createCast(mlir::cir::CastKind::bitcast, regTop, i8PtrTy); |
| 203 | + auto resAsInt8P = builder.create<mlir::cir::PtrStrideOp>( |
| 204 | + loc, castRegTop.getType(), castRegTop, offs); |
| 205 | + auto resAsVoidP = builder.createCast(mlir::cir::CastKind::bitcast, resAsInt8P, |
| 206 | + regTop.getType()); |
| 207 | + builder.create<mlir::cir::BrOp>(loc, mlir::ValueRange{resAsVoidP}, |
| 208 | + newEndBlock); |
| 209 | + |
| 210 | + // generate additional instructions for end block |
| 211 | + builder.setInsertionPoint(op); |
| 212 | + newEndBlock->addArgument(stack.getType(), loc); |
| 213 | + auto resP = newEndBlock->getArgument(0); |
| 214 | + assert(resP.getType().isa<mlir::cir::PointerType>()); |
| 215 | + auto opResPTy = PointerType::get(builder.getContext(), opResTy); |
| 216 | + auto castResP = |
| 217 | + builder.createCast(mlir::cir::CastKind::bitcast, resP, opResPTy); |
| 218 | + auto res = builder.create<mlir::cir::LoadOp>(loc, castResP); |
| 219 | + return res.getResult(); |
| 220 | +} |
0 commit comments