================
@@ -83,16 +85,150 @@ static void collectClobbers(const CIRGenFunction &cgf,
const AsmStmt &s,
}
}
+using ConstraintInfos = SmallVector<TargetInfo::ConstraintInfo, 4>;
+
+static void collectInOutConstraintInfos(const CIRGenFunction &cgf,
+ const AsmStmt &s, ConstraintInfos &out,
+ ConstraintInfos &in) {
+
+ for (unsigned i = 0, e = s.getNumOutputs(); i != e; i++) {
+ StringRef name;
+ if (const GCCAsmStmt *gas = dyn_cast<GCCAsmStmt>(&s))
+ name = gas->getOutputName(i);
+ TargetInfo::ConstraintInfo info(s.getOutputConstraint(i), name);
+ bool isValid = cgf.getTarget().validateOutputConstraint(info);
+ (void)isValid;
+ assert(isValid && "Failed to parse output constraint");
+ out.push_back(info);
+ }
+
+ for (unsigned i = 0, e = s.getNumInputs(); i != e; i++) {
+ StringRef name;
+ if (const GCCAsmStmt *gas = dyn_cast<GCCAsmStmt>(&s))
+ name = gas->getInputName(i);
+ TargetInfo::ConstraintInfo info(s.getInputConstraint(i), name);
+ bool isValid = cgf.getTarget().validateInputConstraint(out, info);
+ assert(isValid && "Failed to parse input constraint");
+ (void)isValid;
+ in.push_back(info);
+ }
+}
+
+static void emitAsmStores(CIRGenFunction &cgf, const AsmStmt &s,
+ const llvm::ArrayRef<mlir::Value> regResults,
+ const llvm::ArrayRef<mlir::Type> resultRegTypes,
+ const llvm::ArrayRef<mlir::Type> resultTruncRegTypes,
+ const llvm::ArrayRef<LValue> resultRegDests,
+ const llvm::ArrayRef<QualType> resultRegQualTys,
+ const llvm::BitVector &resultTypeRequiresCast,
+ const llvm::BitVector &resultRegIsFlagReg) {
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ CIRGenModule &cgm = cgf.cgm;
+ mlir::MLIRContext *ctx = builder.getContext();
+
+ assert(regResults.size() == resultRegTypes.size());
+ assert(regResults.size() == resultTruncRegTypes.size());
+ assert(regResults.size() == resultRegDests.size());
+
+ // ResultRegDests can be also populated by addReturnRegisterOutputs() above,
+ // in which case its size may grow.
+ assert(resultTypeRequiresCast.size() <= resultRegDests.size());
+ assert(resultRegIsFlagReg.size() <= resultRegDests.size());
+
+ for (unsigned i = 0, e = regResults.size(); i != e; ++i) {
+ mlir::Value tmp = regResults[i];
+ mlir::Type truncTy = resultTruncRegTypes[i];
+
+ if (i < resultRegIsFlagReg.size() && resultRegIsFlagReg[i])
+ assert(!cir::MissingFeatures::asmLLVMAssume());
+
+ // If the result type of the LLVM IR asm doesn't match the result type of
+ // the expression, do the conversion.
+ if (resultRegTypes[i] != truncTy) {
+
+ // Truncate the integer result to the right size, note that TruncTy can
be
+ // a pointer.
+ if (mlir::isa<mlir::FloatType>(truncTy)) {
+ tmp = builder.createFloatingCast(tmp, truncTy);
+ } else if (isa<cir::PointerType>(truncTy) &&
+ isa<cir::IntType>(tmp.getType())) {
+ uint64_t resSize = cgm.getDataLayout().getTypeSizeInBits(truncTy);
+ tmp = builder.createIntCast(
+ tmp, cir::IntType::get(ctx, (unsigned)resSize, false));
+ tmp = builder.createIntToPtr(tmp, truncTy);
+ } else if (isa<cir::PointerType>(tmp.getType()) &&
+ isa<cir::IntType>(truncTy)) {
+ uint64_t tmpSize =
cgm.getDataLayout().getTypeSizeInBits(tmp.getType());
+ tmp = builder.createPtrToInt(
+ tmp, cir::IntType::get(ctx, (unsigned)tmpSize, false));
+ tmp = builder.createIntCast(tmp, truncTy);
+ } else if (isa<cir::IntType>(truncTy)) {
+ tmp = builder.createIntCast(tmp, truncTy);
+ } else if (isa<cir::VectorType>(truncTy)) {
+ assert(!cir::MissingFeatures::asmVectorType());
+ }
+ }
+
+ LValue dest = resultRegDests[i];
+ // ResultTypeRequiresCast elements correspond to the first
+ // ResultTypeRequiresCast.size() elements of RegResults.
+ if ((i < resultTypeRequiresCast.size()) && resultTypeRequiresCast[i]) {
+ unsigned size = cgf.getContext().getTypeSize(resultRegQualTys[i]);
+ Address addr =
+ dest.getAddress().withElementType(builder, resultRegTypes[i]);
+ if (cgm.getTargetCIRGenInfo().isScalarizableAsmOperand(cgf, truncTy)) {
+ builder.createStore(cgf.getLoc(s.getAsmLoc()), tmp, addr);
+ continue;
+ }
+
+ QualType ty =
+ cgf.getContext().getIntTypeForBitwidth(size, /*Signed=*/false);
+ if (ty.isNull()) {
+ const Expr *outExpr = s.getOutputExpr(i);
+ cgm.getDiags().Report(outExpr->getExprLoc(),
+ diag::err_store_value_to_reg);
+ return;
+ }
+ dest = cgf.makeAddrLValue(addr, ty);
+ }
+
+ cgf.emitStoreThroughLValue(RValue::get(tmp), dest);
+ }
+}
+
mlir::LogicalResult CIRGenFunction::emitAsmStmt(const AsmStmt &s) {
// Assemble the final asm string.
std::string asmString = s.generateAsmString(getContext());
+ SourceLocation srcLoc = s.getAsmLoc();
+ mlir::Location loc = getLoc(srcLoc);
+
+ // Get all the output and input constraints together.
+ ConstraintInfos outputConstraintInfos;
+ ConstraintInfos inputConstraintInfos;
+ collectInOutConstraintInfos(*this, s, outputConstraintInfos,
+ inputConstraintInfos);
bool isGCCAsmGoto = false;
std::string constraints;
+ std::vector<LValue> resultRegDests;
----------------
andykaylor wrote:
Should these all be `SmallVector`?
https://github.com/llvm/llvm-project/pull/176006
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits