Index: libomptarget/include/omptarget.h =================================================================== --- libomptarget/include/omptarget.h +++ libomptarget/include/omptarget.h @@ -48,6 +48,8 @@ OMP_TGT_MAPTYPE_LITERAL = 0x100, // mapping is implicit OMP_TGT_MAPTYPE_IMPLICIT = 0x200, + // map the pointer as well as the pointee as reference + OMP_TGT_MAPTYPE_LAMBDA_REF = 0x400, // member of struct, member given by [16 MSBs] - 1 OMP_TGT_MAPTYPE_MEMBER_OF = 0xffff000000000000 }; Index: libomptarget/src/omptarget.cpp =================================================================== --- libomptarget/src/omptarget.cpp +++ libomptarget/src/omptarget.cpp @@ -215,8 +215,10 @@ int rc = OFFLOAD_SUCCESS; for (int32_t i = 0; i < arg_num; ++i) { // Ignore private variables and arrays - there is no mapping for them. + // Also ignore implicit mappings for lambdas - only in target. if ((arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) || - (arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE)) + (arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE) || + (arg_types[i] & OMP_TGT_MAPTYPE_LAMBDA_REF)) continue; void *HstPtrBegin = args[i]; @@ -341,8 +343,10 @@ for (int32_t i = arg_num - 1; i >= 0; --i) { // Ignore private variables and arrays - there is no mapping for them. // Also, ignore the use_device_ptr directive, it has no effect here. + // Also ignore implicit mappings for lambdas - only in target. if ((arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) || - (arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE)) + (arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE) || + (arg_types[i] & OMP_TGT_MAPTYPE_LAMBDA_REF)) continue; void *HstPtrBegin = args[i]; @@ -461,8 +465,10 @@ void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) { // process each input. for (int32_t i = 0; i < arg_num; ++i) { + // Ignore implicit mappings for lambdas - only in target. if ((arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) || - (arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE)) + (arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE) || + (arg_types[i] & OMP_TGT_MAPTYPE_LAMBDA_REF)) continue; void *HstPtrBegin = args[i]; @@ -603,6 +609,35 @@ for (int32_t i = 0; i < arg_num; ++i) { if (!(arg_types[i] & OMP_TGT_MAPTYPE_TARGET_PARAM)) { // This is not a target parameter, do not push it into tgt_args. + // Check for lambda mapping. + if (arg_types[i] & OMP_TGT_MAPTYPE_LAMBDA_REF) { + // The parent lambda must be processed already and it must be the last + // in tgt_args and tgt_offsets arrays. + void *HstPtrBegin = args[i]; + void *HstPtrBase = args_base[i]; + bool IsLast; // unused. + void *TgtPtrBase = + (void *)((intptr_t)tgt_args.back() + tgt_offsets.back()); + DP("Parent lambda base " DPxMOD "\n", DPxPTR(TgtPtrBase)); + uint64_t Delta = (uint64_t)HstPtrBegin - (uint64_t)HstPtrBase; + void *TgtPtrBegin = (void *)((uintptr_t)TgtPtrBase + Delta); + void *Pointer_TgtPtrBegin = Device.getTgtPtrBegin( + *(void **)HstPtrBegin, arg_sizes[i], IsLast, false); + if (!Pointer_TgtPtrBegin) { + DP("No lambda captured variable mapped (" DPxMOD ") - ignored\n", + DPxPTR(*(void **)HstPtrBegin)); + continue; + } + DP("Update lambda reference (" DPxMOD ") -> [" DPxMOD "]\n", + DPxPTR(Pointer_TgtPtrBegin), DPxPTR(TgtPtrBegin)); + int rt = Device.data_submit(TgtPtrBegin, &Pointer_TgtPtrBegin, + sizeof(void *)); + if (rt != OFFLOAD_SUCCESS) { + DP("Copying data to device failed.\n"); + rc = OFFLOAD_FAIL; + break; + } + } continue; } void *HstPtrBegin = args[i];