@@ -3061,3 +3061,174 @@ mlir::cir::SourceLanguage CIRGenModule::getCIRSourceLanguage() {
3061
3061
// TODO(cir): support remaining source languages.
3062
3062
llvm_unreachable (" CIR does not yet support the given source language" );
3063
3063
}
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