@@ -467,6 +467,46 @@ static bool isMemBuiltinOutOfBoundPossible(const clang::Expr *sizeArg,
467
467
return size.ugt (dstSize);
468
468
}
469
469
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
+
470
510
RValue CIRGenFunction::emitBuiltinExpr (const GlobalDecl GD, unsigned BuiltinID,
471
511
const CallExpr *E,
472
512
ReturnValueSlot ReturnValue) {
@@ -2526,25 +2566,58 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
2526
2566
2527
2567
// See if we have a target specific intrinsic.
2528
2568
std::string Name = getContext ().BuiltinInfo .getName (BuiltinID);
2529
- Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
2569
+ Intrinsic::ID intrinsicID = Intrinsic::not_intrinsic;
2530
2570
StringRef Prefix =
2531
2571
llvm::Triple::getArchTypePrefix (getTarget ().getTriple ().getArch ());
2532
2572
if (!Prefix.empty ()) {
2533
- IntrinsicID = Intrinsic::getIntrinsicForClangBuiltin (Prefix.data (), Name);
2573
+ intrinsicID = Intrinsic::getIntrinsicForClangBuiltin (Prefix.data (), Name);
2534
2574
// NOTE we don't need to perform a compatibility flag check here since the
2535
2575
// intrinsics are declared in Builtins*.def via LANGBUILTIN which filter the
2536
2576
// 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);
2539
2579
}
2540
2580
2541
- if (IntrinsicID != Intrinsic::not_intrinsic) {
2581
+ if (intrinsicID != Intrinsic::not_intrinsic) {
2542
2582
unsigned iceArguments = 0 ;
2543
2583
ASTContext::GetBuiltinTypeError error;
2544
2584
getContext ().GetBuiltinType (BuiltinID, error, &iceArguments);
2545
2585
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)
2547
2615
llvm_unreachable (" NYI" );
2616
+
2617
+ if (isa<cir::VoidType>(retTy))
2618
+ return RValue::get (nullptr );
2619
+
2620
+ return RValue::get (intrinsicCall.getResult ());
2548
2621
}
2549
2622
2550
2623
// Some target-specific builtins can have aggregate return values, e.g.
0 commit comments