@@ -467,6 +467,46 @@ static bool isMemBuiltinOutOfBoundPossible(const clang::Expr *sizeArg,
467467 return size.ugt (dstSize);
468468}
469469
470+ static mlir::Type
471+ decodeFixedType (ArrayRef<llvm::Intrinsic::IITDescriptor> &infos,
472+ mlir::MLIRContext *context) {
473+ using namespace llvm ::Intrinsic;
474+
475+ IITDescriptor descriptor = infos.front ();
476+ infos = infos.slice (1 );
477+
478+ switch (descriptor.Kind ) {
479+ case IITDescriptor::Void:
480+ return VoidType::get (context);
481+ case IITDescriptor::Integer:
482+ return IntType::get (context, descriptor.Integer_Width , /* signed=*/ true );
483+ case IITDescriptor::Float:
484+ return SingleType::get (context);
485+ case IITDescriptor::Double:
486+ return DoubleType::get (context);
487+ default :
488+ llvm_unreachable (" NYI" );
489+ }
490+ }
491+
492+ // llvm::Intrinsics accepts only LLVMContext. We need to reimplement it here.
493+ static cir::FuncType getIntrinsicType (mlir::MLIRContext *context,
494+ llvm::Intrinsic::ID id) {
495+ using namespace llvm ::Intrinsic;
496+
497+ SmallVector<IITDescriptor, 8 > table;
498+ getIntrinsicInfoTableEntries (id, table);
499+
500+ ArrayRef<IITDescriptor> tableRef = table;
501+ mlir::Type resultTy = decodeFixedType (tableRef, context);
502+
503+ SmallVector<mlir::Type, 8 > argTypes;
504+ while (!tableRef.empty ())
505+ argTypes.push_back (decodeFixedType (tableRef, context));
506+
507+ return FuncType::get (argTypes, resultTy);
508+ }
509+
470510RValue CIRGenFunction::emitBuiltinExpr (const GlobalDecl GD, unsigned BuiltinID,
471511 const CallExpr *E,
472512 ReturnValueSlot ReturnValue) {
@@ -2525,25 +2565,46 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
25252565
25262566 // See if we have a target specific intrinsic.
25272567 std::string Name = getContext ().BuiltinInfo .getName (BuiltinID);
2528- Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
2568+ Intrinsic::ID intrinsicID = Intrinsic::not_intrinsic;
25292569 StringRef Prefix =
25302570 llvm::Triple::getArchTypePrefix (getTarget ().getTriple ().getArch ());
25312571 if (!Prefix.empty ()) {
2532- IntrinsicID = Intrinsic::getIntrinsicForClangBuiltin (Prefix.data (), Name);
2572+ intrinsicID = Intrinsic::getIntrinsicForClangBuiltin (Prefix.data (), Name);
25332573 // NOTE we don't need to perform a compatibility flag check here since the
25342574 // intrinsics are declared in Builtins*.def via LANGBUILTIN which filter the
25352575 // MS builtins via ALL_MS_LANGUAGES and are filtered earlier.
2536- if (IntrinsicID == Intrinsic::not_intrinsic)
2537- IntrinsicID = Intrinsic::getIntrinsicForMSBuiltin (Prefix.data (), Name);
2576+ if (intrinsicID == Intrinsic::not_intrinsic)
2577+ intrinsicID = Intrinsic::getIntrinsicForMSBuiltin (Prefix.data (), Name);
25382578 }
25392579
2540- if (IntrinsicID != Intrinsic::not_intrinsic) {
2580+ if (intrinsicID != Intrinsic::not_intrinsic) {
25412581 unsigned iceArguments = 0 ;
25422582 ASTContext::GetBuiltinTypeError error;
25432583 getContext ().GetBuiltinType (BuiltinID, error, &iceArguments);
25442584 assert (error == ASTContext::GE_None && " Should not codegen an error" );
2545- if (iceArguments > 0 )
2546- llvm_unreachable (" NYI" );
2585+
2586+ llvm::StringRef name = llvm::Intrinsic::getName (intrinsicID);
2587+ // cir::LLVMIntrinsicCallOp expects intrinsic name to not have prefix
2588+ // "llvm." For example, `llvm.nvvm.barrier0` should be passed as
2589+ // `nvvm.barrier0`.
2590+ if (!name.consume_front (" llvm." ))
2591+ assert (false && " bad intrinsic name!" );
2592+
2593+ cir::FuncType intrinsicType =
2594+ getIntrinsicType (&getMLIRContext (), intrinsicID);
2595+
2596+ SmallVector<mlir::Value> args;
2597+ for (unsigned i = 0 ; i < E->getNumArgs (); i++) {
2598+ mlir::Value arg = emitScalarExpr (E->getArg (i));
2599+ if (arg.getType () != intrinsicType.getInput (i))
2600+ llvm_unreachable (" NYI" );
2601+
2602+ args.push_back (arg);
2603+ }
2604+ auto intrinsicCall = builder.create <cir::LLVMIntrinsicCallOp>(
2605+ getLoc (E->getExprLoc ()), builder.getStringAttr (name),
2606+ intrinsicType.getReturnType (), args);
2607+ return RValue::get (intrinsicCall.getResult ());
25472608 }
25482609
25492610 // Some target-specific builtins can have aggregate return values, e.g.
0 commit comments