@@ -3061,3 +3061,174 @@ mlir::cir::SourceLanguage CIRGenModule::getCIRSourceLanguage() {
30613061 // TODO(cir): support remaining source languages.
30623062 llvm_unreachable (" CIR does not yet support the given source language" );
30633063}
3064+
3065+ // Returns the address space id that should be produced to the
3066+ // kernel_arg_addr_space metadata. This is always fixed to the ids
3067+ // as specified in the SPIR 2.0 specification in order to differentiate
3068+ // for example in clGetKernelArgInfo() implementation between the address
3069+ // spaces with targets without unique mapping to the OpenCL address spaces
3070+ // (basically all single AS CPUs).
3071+ static unsigned ArgInfoAddressSpace (LangAS AS) {
3072+ switch (AS) {
3073+ case LangAS::opencl_global:
3074+ return 1 ;
3075+ case LangAS::opencl_constant:
3076+ return 2 ;
3077+ case LangAS::opencl_local:
3078+ return 3 ;
3079+ case LangAS::opencl_generic:
3080+ return 4 ; // Not in SPIR 2.0 specs.
3081+ case LangAS::opencl_global_device:
3082+ return 5 ;
3083+ case LangAS::opencl_global_host:
3084+ return 6 ;
3085+ default :
3086+ return 0 ; // Assume private.
3087+ }
3088+ }
3089+
3090+ void CIRGenModule::genKernelArgMetadata (mlir::cir::FuncOp Fn,
3091+ const FunctionDecl *FD,
3092+ CIRGenFunction *CGF) {
3093+ assert (((FD && CGF) || (!FD && !CGF)) &&
3094+ " Incorrect use - FD and CGF should either be both null or not!" );
3095+ // Create MDNodes that represent the kernel arg metadata.
3096+ // Each MDNode is a list in the form of "key", N number of values which is
3097+ // the same number of values as their are kernel arguments.
3098+
3099+ const PrintingPolicy &Policy = getASTContext ().getPrintingPolicy ();
3100+
3101+ // Integer values for the kernel argument address space qualifiers.
3102+ SmallVector<int32_t , 8 > addressQuals;
3103+
3104+ // Attrs for the kernel argument access qualifiers (images only).
3105+ SmallVector<mlir::Attribute, 8 > accessQuals;
3106+
3107+ // Attrs for the kernel argument type names.
3108+ SmallVector<mlir::Attribute, 8 > argTypeNames;
3109+
3110+ // Attrs for the kernel argument base type names.
3111+ SmallVector<mlir::Attribute, 8 > argBaseTypeNames;
3112+
3113+ // Attrs for the kernel argument type qualifiers.
3114+ SmallVector<mlir::Attribute, 8 > argTypeQuals;
3115+
3116+ // Attrs for the kernel argument names.
3117+ SmallVector<mlir::Attribute, 8 > argNames;
3118+
3119+ // OpenCL image and pipe types require special treatments for some metadata
3120+ assert (!MissingFeatures::openCLBuiltinTypes ());
3121+
3122+ if (FD && CGF)
3123+ for (unsigned i = 0 , e = FD->getNumParams (); i != e; ++i) {
3124+ const ParmVarDecl *parm = FD->getParamDecl (i);
3125+ // Get argument name.
3126+ argNames.push_back (builder.getStringAttr (parm->getName ()));
3127+
3128+ if (!getLangOpts ().OpenCL )
3129+ continue ;
3130+ QualType ty = parm->getType ();
3131+ std::string typeQuals;
3132+
3133+ // Get image and pipe access qualifier:
3134+ if (ty->isImageType () || ty->isPipeType ()) {
3135+ llvm_unreachable (" NYI" );
3136+ } else
3137+ accessQuals.push_back (builder.getStringAttr (" none" ));
3138+
3139+ auto getTypeSpelling = [&](QualType Ty) {
3140+ auto typeName = Ty.getUnqualifiedType ().getAsString (Policy);
3141+
3142+ if (Ty.isCanonical ()) {
3143+ StringRef typeNameRef = typeName;
3144+ // Turn "unsigned type" to "utype"
3145+ if (typeNameRef.consume_front (" unsigned " ))
3146+ return std::string (" u" ) + typeNameRef.str ();
3147+ if (typeNameRef.consume_front (" signed " ))
3148+ return typeNameRef.str ();
3149+ }
3150+
3151+ return typeName;
3152+ };
3153+
3154+ if (ty->isPointerType ()) {
3155+ QualType pointeeTy = ty->getPointeeType ();
3156+
3157+ // Get address qualifier.
3158+ addressQuals.push_back (
3159+ ArgInfoAddressSpace (pointeeTy.getAddressSpace ()));
3160+
3161+ // Get argument type name.
3162+ std::string typeName = getTypeSpelling (pointeeTy) + " *" ;
3163+ std::string baseTypeName =
3164+ getTypeSpelling (pointeeTy.getCanonicalType ()) + " *" ;
3165+ argTypeNames.push_back (builder.getStringAttr (typeName));
3166+ argBaseTypeNames.push_back (builder.getStringAttr (baseTypeName));
3167+
3168+ // Get argument type qualifiers:
3169+ if (ty.isRestrictQualified ())
3170+ typeQuals = " restrict" ;
3171+ if (pointeeTy.isConstQualified () ||
3172+ (pointeeTy.getAddressSpace () == LangAS::opencl_constant))
3173+ typeQuals += typeQuals.empty () ? " const" : " const" ;
3174+ if (pointeeTy.isVolatileQualified ())
3175+ typeQuals += typeQuals.empty () ? " volatile" : " volatile" ;
3176+ } else {
3177+ uint32_t AddrSpc = 0 ;
3178+ bool isPipe = ty->isPipeType ();
3179+ if (ty->isImageType () || isPipe)
3180+ llvm_unreachable (" NYI" );
3181+
3182+ addressQuals.push_back (AddrSpc);
3183+
3184+ // Get argument type name.
3185+ ty = isPipe ? ty->castAs <PipeType>()->getElementType () : ty;
3186+ std::string typeName = getTypeSpelling (ty);
3187+ std::string baseTypeName = getTypeSpelling (ty.getCanonicalType ());
3188+
3189+ // Remove access qualifiers on images
3190+ // (as they are inseparable from type in clang implementation,
3191+ // but OpenCL spec provides a special query to get access qualifier
3192+ // via clGetKernelArgInfo with CL_KERNEL_ARG_ACCESS_QUALIFIER):
3193+ if (ty->isImageType ()) {
3194+ llvm_unreachable (" NYI" );
3195+ }
3196+
3197+ argTypeNames.push_back (builder.getStringAttr (typeName));
3198+ argBaseTypeNames.push_back (builder.getStringAttr (baseTypeName));
3199+
3200+ if (isPipe)
3201+ llvm_unreachable (" NYI" );
3202+ }
3203+ argTypeQuals.push_back (builder.getStringAttr (typeQuals));
3204+ }
3205+
3206+ bool shouldEmitArgName = getCodeGenOpts ().EmitOpenCLArgMetadata ||
3207+ getCodeGenOpts ().HIPSaveKernelArgName ;
3208+
3209+ if (getLangOpts ().OpenCL ) {
3210+ // The kernel arg name is emitted only when `-cl-kernel-arg-info` is on,
3211+ // since it is only used to support `clGetKernelArgInfo` which requires
3212+ // `-cl-kernel-arg-info` to work. The other metadata are mandatory because
3213+ // they are necessary for OpenCL runtime to set kernel argument.
3214+ mlir::ArrayAttr resArgNames = {};
3215+ if (shouldEmitArgName)
3216+ resArgNames = builder.getArrayAttr (argNames);
3217+
3218+ // Update the function's extra attributes with the kernel argument metadata.
3219+ auto value = mlir::cir::OpenCLKernelArgMetadataAttr::get (
3220+ Fn.getContext (), builder.getI32ArrayAttr (addressQuals),
3221+ builder.getArrayAttr (accessQuals), builder.getArrayAttr (argTypeNames),
3222+ builder.getArrayAttr (argBaseTypeNames),
3223+ builder.getArrayAttr (argTypeQuals), resArgNames);
3224+ mlir::NamedAttrList items{Fn.getExtraAttrs ().getElements ().getValue ()};
3225+ auto oldValue = items.set (value.getMnemonic (), value);
3226+ if (oldValue != value) {
3227+ Fn.setExtraAttrsAttr (mlir::cir::ExtraFuncAttributesAttr::get (
3228+ builder.getContext (), builder.getDictionaryAttr (items)));
3229+ }
3230+ } else {
3231+ if (shouldEmitArgName)
3232+ llvm_unreachable (" NYI HIPSaveKernelArgName" );
3233+ }
3234+ }
0 commit comments