================
@@ -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

Reply via email to