@@ -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) {
@@ -2526,25 +2566,58 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
25262566
25272567 // See if we have a target specific intrinsic.
25282568 std::string Name = getContext ().BuiltinInfo .getName (BuiltinID);
2529- Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
2569+ Intrinsic::ID intrinsicID = Intrinsic::not_intrinsic;
25302570 StringRef Prefix =
25312571 llvm::Triple::getArchTypePrefix (getTarget ().getTriple ().getArch ());
25322572 if (!Prefix.empty ()) {
2533- IntrinsicID = Intrinsic::getIntrinsicForClangBuiltin (Prefix.data (), Name);
2573+ intrinsicID = Intrinsic::getIntrinsicForClangBuiltin (Prefix.data (), Name);
25342574 // NOTE we don't need to perform a compatibility flag check here since the
25352575 // intrinsics are declared in Builtins*.def via LANGBUILTIN which filter the
25362576 // MS builtins via ALL_MS_LANGUAGES and are filtered earlier.
2537- if (IntrinsicID == Intrinsic::not_intrinsic)
2538- IntrinsicID = Intrinsic::getIntrinsicForMSBuiltin (Prefix.data (), Name);
2577+ if (intrinsicID == Intrinsic::not_intrinsic)
2578+ intrinsicID = Intrinsic::getIntrinsicForMSBuiltin (Prefix.data (), Name);
25392579 }
25402580
2541- if (IntrinsicID != Intrinsic::not_intrinsic) {
2581+ if (intrinsicID != Intrinsic::not_intrinsic) {
25422582 unsigned iceArguments = 0 ;
25432583 ASTContext::GetBuiltinTypeError error;
25442584 getContext ().GetBuiltinType (BuiltinID, error, &iceArguments);
25452585 assert (error == ASTContext::GE_None && " Should not codegen an error" );
2546- if (iceArguments > 0 )
2586+
2587+ llvm::StringRef name = llvm::Intrinsic::getName (intrinsicID);
2588+ // cir::LLVMIntrinsicCallOp expects intrinsic name to not have prefix
2589+ // "llvm." For example, `llvm.nvvm.barrier0` should be passed as
2590+ // `nvvm.barrier0`.
2591+ if (!name.consume_front (" llvm." ))
2592+ assert (false && " bad intrinsic name!" );
2593+
2594+ cir::FuncType intrinsicType =
2595+ getIntrinsicType (&getMLIRContext (), intrinsicID);
2596+
2597+ SmallVector<mlir::Value> args;
2598+ for (unsigned i = 0 ; i < E->getNumArgs (); i++) {
2599+ mlir::Value arg = emitScalarOrConstFoldImmArg (iceArguments, i, E);
2600+ mlir::Type argType = arg.getType ();
2601+ if (argType != intrinsicType.getInput (i))
2602+ llvm_unreachable (" NYI" );
2603+
2604+ args.push_back (arg);
2605+ }
2606+
2607+ auto intrinsicCall = builder.create <cir::LLVMIntrinsicCallOp>(
2608+ getLoc (E->getExprLoc ()), builder.getStringAttr (name),
2609+ intrinsicType.getReturnType (), args);
2610+
2611+ mlir::Type builtinReturnType = intrinsicCall.getResult ().getType ();
2612+ mlir::Type retTy = intrinsicType.getReturnType ();
2613+
2614+ if (builtinReturnType != retTy)
25472615 llvm_unreachable (" NYI" );
2616+
2617+ if (isa<cir::VoidType>(retTy))
2618+ return RValue::get (nullptr );
2619+
2620+ return RValue::get (intrinsicCall.getResult ());
25482621 }
25492622
25502623 // Some target-specific builtins can have aggregate return values, e.g.
0 commit comments