Unverified Commit 189d42bd authored by Shintaro Iwasaki's avatar Shintaro Iwasaki Committed by GitHub
Browse files

Merge pull request #7 from shintaro-iwasaki/bolt-2de327

merge 2de327
parents 485c815a 4003c401
name: main branch sync
on:
push:
branches:
- 'main'
jobs:
branch_sync:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
with:
# persist-credentials: false allows us to use our own credentials for
# pushing to the repository. Otherwise, the default github actions token
# is used.
persist-credentials: false
fetch-depth: 0
- name: Update branch
env:
LLVMBOT_TOKEN: ${{ secrets.LLVMBOT_MAIN_SYNC }}
run: |
git push https://$LLVMBOT_TOKEN@github.com/${{ github.repository }} HEAD:master
//===------- SourceInfo.h - Target independent OpenMP target RTL -- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Methods used to describe source information in target regions
//
//===----------------------------------------------------------------------===//
#ifndef _SOURCE_INFO_H_
#define _SOURCE_INFO_H_
#include <string>
#ifdef _WIN32
static const bool OS_WINDOWS = true;
#else
static const bool OS_WINDOWS = false;
#endif
/// Type alias for source location information for variable mappings with
/// data layout ";name;filename;row;col;;\0" from clang.
using map_var_info_t = void *;
/// The ident structure that describes a source location from kmp.h. with
/// source location string data as ";filename;function;line;column;;\0".
struct ident_t {
// Ident_t flags described in kmp.h.
int32_t reserved_1;
int32_t flags;
int32_t reserved_2;
int32_t reserved_3;
char const *psource;
};
/// Struct to hold source individual location information.
class SourceInfo {
/// Underlying string copy of the original source information.
const std::string sourceStr;
/// Location fields extracted from the source information string.
const std::string name;
const std::string filename;
const int32_t line;
const int32_t column;
std::string initStr(const void *name) {
if (!name)
return ";unknown;unknown;0;0;;";
else
return std::string(reinterpret_cast<const char *>(name));
}
/// Get n-th substring in an expression separated by ;.
std::string getSubstring(const int n) const {
std::size_t begin = sourceStr.find(';');
std::size_t end = sourceStr.find(';', begin + 1);
for (int i = 0; i < n; i++) {
begin = end;
end = sourceStr.find(';', begin + 1);
}
return sourceStr.substr(begin + 1, end - begin - 1);
};
/// Get the filename from a full path.
std::string removePath(const std::string &path) const {
std::size_t pos = (OS_WINDOWS) ? path.rfind('\\') : path.rfind('/');
return path.substr(pos + 1);
};
public:
SourceInfo(const ident_t *loc)
: sourceStr(initStr(loc->psource)), name(getSubstring(1)),
filename(removePath(getSubstring(0))), line(std::stoi(getSubstring(2))),
column(std::stoi(getSubstring(3))) {}
SourceInfo(const map_var_info_t name)
: sourceStr(initStr(name)), name(getSubstring(0)),
filename(removePath(getSubstring(1))), line(std::stoi(getSubstring(2))),
column(std::stoi(getSubstring(3))) {}
const char *getName() const { return name.c_str(); }
const char *getFilename() const { return filename.c_str(); }
int32_t getLine() const { return line; }
int32_t getColumn() const { return column; }
bool isAvailible() const { return (line || column); }
};
/// Standalone function for getting the variable name of a mapping.
static inline std::string getNameFromMapping(const map_var_info_t name) {
if (!name)
return "unknown";
const std::string name_str(reinterpret_cast<const char *>(name));
std::size_t begin = name_str.find(';');
std::size_t end = name_str.find(';', begin + 1);
return name_str.substr(begin + 1, end - begin - 1);
}
#endif
......@@ -17,6 +17,8 @@
#include <stdint.h>
#include <stddef.h>
#include <SourceInfo.h>
#define OFFLOAD_SUCCESS (0)
#define OFFLOAD_FAIL (~0)
......@@ -50,6 +52,8 @@ enum tgt_map_type {
OMP_TGT_MAPTYPE_CLOSE = 0x400,
// runtime error if not already allocated
OMP_TGT_MAPTYPE_PRESENT = 0x1000,
// descriptor for non-contiguous target-update
OMP_TGT_MAPTYPE_NON_CONTIG = 0x100000000000,
// member of struct, member given by [16 MSBs] - 1
OMP_TGT_MAPTYPE_MEMBER_OF = 0xffff000000000000
};
......@@ -121,6 +125,13 @@ struct __tgt_async_info {
void *Queue = nullptr;
};
/// This struct is a record of non-contiguous information
struct __tgt_target_non_contig {
uint64_t Offset;
uint64_t Count;
uint64_t Stride;
};
#ifdef __cplusplus
extern "C" {
#endif
......@@ -161,13 +172,16 @@ void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num,
int32_t depNum, void *depList,
int32_t noAliasDepNum,
void *noAliasDepList);
void __tgt_target_data_begin_mapper(int64_t device_id, int32_t arg_num,
void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
void __tgt_target_data_begin_mapper(ident_t *loc, int64_t device_id,
int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes,
int64_t *arg_types,
map_var_info_t *arg_names,
void **arg_mappers);
void __tgt_target_data_begin_nowait_mapper(
int64_t device_id, int32_t arg_num, void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types, void **arg_mappers, int32_t depNum,
ident_t *loc, int64_t device_id, int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes, int64_t *arg_types,
map_var_info_t *arg_names, void **arg_mappers, int32_t depNum,
void *depList, int32_t noAliasDepNum, void *noAliasDepList);
// passes data from the target, release target memory and destroys the
......@@ -180,16 +194,16 @@ void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num,
int64_t *arg_sizes, int64_t *arg_types,
int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList);
void __tgt_target_data_end_mapper(int64_t device_id, int32_t arg_num,
void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
void __tgt_target_data_end_mapper(ident_t *loc, int64_t device_id,
int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes,
int64_t *arg_types, map_var_info_t *arg_names,
void **arg_mappers);
void __tgt_target_data_end_nowait_mapper(int64_t device_id, int32_t arg_num,
void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
void **arg_mappers, int32_t depNum,
void *depList, int32_t noAliasDepNum,
void *noAliasDepList);
void __tgt_target_data_end_nowait_mapper(
ident_t *loc, int64_t device_id, int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes, int64_t *arg_types,
map_var_info_t *arg_names, void **arg_mappers, int32_t depNum,
void *depList, int32_t noAliasDepNum, void *noAliasDepList);
/// passes data to/from the target
void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
......@@ -201,13 +215,16 @@ void __tgt_target_data_update_nowait(int64_t device_id, int32_t arg_num,
int32_t depNum, void *depList,
int32_t noAliasDepNum,
void *noAliasDepList);
void __tgt_target_data_update_mapper(int64_t device_id, int32_t arg_num,
void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
void __tgt_target_data_update_mapper(ident_t *loc, int64_t device_id,
int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes,
int64_t *arg_types,
map_var_info_t *arg_names,
void **arg_mappers);
void __tgt_target_data_update_nowait_mapper(
int64_t device_id, int32_t arg_num, void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types, void **arg_mappers, int32_t depNum,
ident_t *loc, int64_t device_id, int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes, int64_t *arg_types,
map_var_info_t *arg_names, void **arg_mappers, int32_t depNum,
void *depList, int32_t noAliasDepNum, void *noAliasDepList);
// Performs the same actions as data_begin in case arg_num is non-zero
......@@ -223,15 +240,16 @@ int __tgt_target_nowait(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types, int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList);
int __tgt_target_mapper(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types, void **arg_mappers);
int __tgt_target_nowait_mapper(int64_t device_id, void *host_ptr,
int __tgt_target_mapper(ident_t *loc, int64_t device_id, void *host_ptr,
int32_t arg_num, void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
map_var_info_t *arg_names, void **arg_mappers);
int __tgt_target_nowait_mapper(ident_t *loc, int64_t device_id, void *host_ptr,
int32_t arg_num, void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
void **arg_mappers, int32_t depNum,
void *depList, int32_t noAliasDepNum,
void *noAliasDepList);
map_var_info_t *arg_names, void **arg_mappers,
int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList);
int __tgt_target_teams(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes,
......@@ -243,18 +261,20 @@ int __tgt_target_teams_nowait(int64_t device_id, void *host_ptr,
int32_t num_teams, int32_t thread_limit,
int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList);
int __tgt_target_teams_mapper(int64_t device_id, void *host_ptr,
int __tgt_target_teams_mapper(ident_t *loc, int64_t device_id, void *host_ptr,
int32_t arg_num, void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
void **arg_mappers, int32_t num_teams,
int32_t thread_limit);
map_var_info_t *arg_names, void **arg_mappers,
int32_t num_teams, int32_t thread_limit);
int __tgt_target_teams_nowait_mapper(
int64_t device_id, void *host_ptr, int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes, int64_t *arg_types, void **arg_mappers,
int32_t num_teams, int32_t thread_limit, int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList);
ident_t *loc, int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types,
map_var_info_t *arg_names, void **arg_mappers, int32_t num_teams,
int32_t thread_limit, int32_t depNum, void *depList, int32_t noAliasDepNum,
void *noAliasDepList);
void __kmpc_push_target_tripcount(int64_t device_id, uint64_t loop_tripcount);
void __kmpc_push_target_tripcount(ident_t *loc, int64_t device_id,
uint64_t loop_tripcount);
#ifdef __cplusplus
}
......
......@@ -45,6 +45,29 @@
#endif
#define DEBUG_PREFIX "Target " GETNAME(TARGET_NAME) " RTL"
// hostrpc interface, FIXME: consider moving to its own include these are
// statically linked into amdgpu/plugin if present from hostrpc_services.a,
// linked as --whole-archive to override the weak symbols that are used to
// implement a fallback for toolchains that do not yet have a hostrpc library.
extern "C" {
unsigned long hostrpc_assign_buffer(hsa_agent_t agent, hsa_queue_t *this_Q,
uint32_t device_id);
hsa_status_t hostrpc_init();
hsa_status_t hostrpc_terminate();
__attribute__((weak)) hsa_status_t hostrpc_init() { return HSA_STATUS_SUCCESS; }
__attribute__((weak)) hsa_status_t hostrpc_terminate() {
return HSA_STATUS_SUCCESS;
}
__attribute__((weak)) unsigned long
hostrpc_assign_buffer(hsa_agent_t, hsa_queue_t *, uint32_t device_id) {
DP("Warning: Attempting to assign hostrpc to device %u, but hostrpc library "
"missing\n",
device_id);
return 0;
}
}
int print_kernel_trace;
// Size of the target call stack struture
......@@ -183,17 +206,15 @@ struct KernelTy {
// 1 - Generic mode (with master warp)
int8_t ExecutionMode;
int16_t ConstWGSize;
int8_t MaxParLevel;
int32_t device_id;
void *CallStackAddr;
void *CallStackAddr = nullptr;
const char *Name;
KernelTy(int8_t _ExecutionMode, int16_t _ConstWGSize, int8_t _MaxParLevel,
int32_t _device_id, void *_CallStackAddr, const char *_Name,
KernelTy(int8_t _ExecutionMode, int16_t _ConstWGSize, int32_t _device_id,
void *_CallStackAddr, const char *_Name,
uint32_t _kernarg_segment_size)
: ExecutionMode(_ExecutionMode), ConstWGSize(_ConstWGSize),
MaxParLevel(_MaxParLevel), device_id(_device_id),
CallStackAddr(_CallStackAddr), Name(_Name) {
device_id(_device_id), CallStackAddr(_CallStackAddr), Name(_Name) {
DP("Construct kernelinfo: ExecMode %d\n", ExecutionMode);
std::string N(_Name);
......@@ -324,7 +345,8 @@ public:
std::vector<std::pair<std::unique_ptr<void, atmiFreePtrDeletor>, uint64_t>>
deviceStateStore;
static const int HardTeamLimit = 1 << 20; // 1 Meg
static const unsigned HardTeamLimit =
(1 << 16) - 1; // 64K needed to fit in uint16
static const int DefaultNumTeams = 128;
static const int Max_Teams =
llvm::omp::AMDGPUGpuGridValues[llvm::omp::GVIDX::GV_Max_Teams];
......@@ -432,6 +454,8 @@ public:
DP("Error when initializing HSA-ATMI\n");
return;
}
// Init hostcall soon after initializing ATMI
hostrpc_init();
HSAAgents = find_gpu_agents();
NumberOfDevices = (int)HSAAgents.size();
......@@ -521,6 +545,8 @@ public:
// atmi_finalize removes access to it
deviceStateStore.clear();
KernelArgPoolMap.clear();
// Terminate hostrpc before finalizing ATMI
hostrpc_terminate();
atmi_finalize();
}
};
......@@ -650,7 +676,7 @@ int32_t __tgt_rtl_init_device(int device_id) {
DeviceInfo.ComputeUnits[device_id] = compute_units;
DP("Using %d compute unis per grid\n", DeviceInfo.ComputeUnits[device_id]);
}
if (print_kernel_trace > 1)
if (print_kernel_trace == 4)
fprintf(stderr, "Device#%-2d CU's: %2d\n", device_id,
DeviceInfo.ComputeUnits[device_id]);
......@@ -926,8 +952,49 @@ __tgt_target_table *__tgt_rtl_load_binary(int32_t device_id,
return res;
}
static atmi_status_t atmi_calloc(void **ret_ptr, size_t size,
atmi_mem_place_t place) {
uint64_t rounded = 4 * ((size + 3) / 4);
void *ptr;
atmi_status_t err = atmi_malloc(&ptr, rounded, place);
if (err != ATMI_STATUS_SUCCESS) {
return err;
}
hsa_status_t rc = hsa_amd_memory_fill(ptr, 0, rounded / 4);
if (rc != HSA_STATUS_SUCCESS) {
fprintf(stderr, "zero fill device_state failed with %u\n", rc);
atmi_free(ptr);
return ATMI_STATUS_ERROR;
}
*ret_ptr = ptr;
return ATMI_STATUS_SUCCESS;
}
__tgt_target_table *__tgt_rtl_load_binary_locked(int32_t device_id,
__tgt_device_image *image) {
// This function loads the device image onto gpu[device_id] and does other
// per-image initialization work. Specifically:
//
// - Initialize an omptarget_device_environmentTy instance embedded in the
// image at the symbol "omptarget_device_environment"
// Fields debug_level, device_num, num_devices. Used by the deviceRTL.
//
// - Allocate a large array per-gpu (could be moved to init_device)
// - Read a uint64_t at symbol omptarget_nvptx_device_State_size
// - Allocate at least that many bytes of gpu memory
// - Zero initialize it
// - Write the pointer to the symbol omptarget_nvptx_device_State
//
// - Pulls some per-kernel information together from various sources and
// records it in the KernelsList for quicker access later
//
// The initialization can be done before or after loading the image onto the
// gpu. This function presently does a mixture. Using the hsa api to get/set
// the information is simpler to implement, in exchange for more complicated
// runtime behaviour. E.g. launching a kernel or using dma to get eight bytes
// back from the gpu vs a hashtable lookup on the host.
const size_t img_size = (char *)image->ImageEnd - (char *)image->ImageStart;
......@@ -964,7 +1031,7 @@ __tgt_target_table *__tgt_rtl_load_binary_locked(int32_t device_id,
if (si.size != sizeof(host_device_env)) {
return ATMI_STATUS_ERROR;
}
DP("Setting global device environment %lu bytes\n", si.size);
DP("Setting global device environment %u bytes\n", si.size);
uint64_t offset = (char *)si.addr - (char *)image->ImageStart;
void *pos = (char *)data + offset;
memcpy(pos, &host_device_env, sizeof(host_device_env));
......@@ -993,61 +1060,64 @@ __tgt_target_table *__tgt_rtl_load_binary_locked(int32_t device_id,
DP("ATMI module successfully loaded!\n");
// Zero the pseudo-bss variable by calling into hsa
// Do this post-load to handle got
uint64_t device_State_bytes =
get_device_State_bytes((char *)image->ImageStart, img_size);
auto &dss = DeviceInfo.deviceStateStore[device_id];
if (device_State_bytes != 0) {
if (dss.first.get() == nullptr) {
assert(dss.second == 0);
void *ptr = NULL;
atmi_status_t err =
atmi_malloc(&ptr, device_State_bytes, get_gpu_mem_place(device_id));
if (err != ATMI_STATUS_SUCCESS) {
fprintf(stderr, "Failed to allocate device_state array\n");
return NULL;
}
dss = {std::unique_ptr<void, RTLDeviceInfoTy::atmiFreePtrDeletor>{ptr},
device_State_bytes};
}
void *ptr = dss.first.get();
if (device_State_bytes != dss.second) {
fprintf(stderr, "Inconsistent sizes of device_State unsupported\n");
exit(1);
}
{
// the device_State array is either large value in bss or a void* that
// needs to be assigned to a pointer to an array of size device_state_bytes
void *state_ptr;
uint32_t state_ptr_size;
err = atmi_interop_hsa_get_symbol_info(get_gpu_mem_place(device_id),
"omptarget_nvptx_device_State",
&state_ptr, &state_ptr_size);
atmi_status_t err = atmi_interop_hsa_get_symbol_info(
get_gpu_mem_place(device_id), "omptarget_nvptx_device_State",
&state_ptr, &state_ptr_size);
if (err != ATMI_STATUS_SUCCESS) {
fprintf(stderr, "failed to find device_state ptr\n");
fprintf(stderr, "failed to find device_state symbol\n");
return NULL;
}
if (state_ptr_size != sizeof(void *)) {
if (state_ptr_size < sizeof(void *)) {
fprintf(stderr, "unexpected size of state_ptr %u != %zu\n",
state_ptr_size, sizeof(void *));
return NULL;
}
// write ptr to device memory so it can be used by later kernels
err = DeviceInfo.freesignalpool_memcpy_h2d(state_ptr, &ptr, sizeof(void *),
device_id);
if (err != ATMI_STATUS_SUCCESS) {
fprintf(stderr, "memcpy install of state_ptr failed\n");
return NULL;
}
// if it's larger than a void*, assume it's a bss array and no further
// initialization is required. Only try to set up a pointer for
// sizeof(void*)
if (state_ptr_size == sizeof(void *)) {
uint64_t device_State_bytes =
get_device_State_bytes((char *)image->ImageStart, img_size);
if (device_State_bytes == 0) {
return NULL;
}
assert((device_State_bytes & 0x3) == 0); // known >= 4 byte aligned
hsa_status_t rc = hsa_amd_memory_fill(ptr, 0, device_State_bytes / 4);
if (rc != HSA_STATUS_SUCCESS) {
fprintf(stderr, "zero fill device_state failed with %u\n", rc);
return NULL;
auto &dss = DeviceInfo.deviceStateStore[device_id];
if (dss.first.get() == nullptr) {
assert(dss.second == 0);
void *ptr = NULL;
atmi_status_t err =
atmi_calloc(&ptr, device_State_bytes, get_gpu_mem_place(device_id));
if (err != ATMI_STATUS_SUCCESS) {
fprintf(stderr, "Failed to allocate device_state array\n");
return NULL;
}
dss = {std::unique_ptr<void, RTLDeviceInfoTy::atmiFreePtrDeletor>{ptr},
device_State_bytes};
}
void *ptr = dss.first.get();
if (device_State_bytes != dss.second) {
fprintf(stderr, "Inconsistent sizes of device_State unsupported\n");
exit(1);
}
// write ptr to device memory so it can be used by later kernels
err = DeviceInfo.freesignalpool_memcpy_h2d(state_ptr, &ptr,
sizeof(void *), device_id);
if (err != ATMI_STATUS_SUCCESS) {
fprintf(stderr, "memcpy install of state_ptr failed\n");
return NULL;
}
}
}
......@@ -1140,9 +1210,6 @@ __tgt_target_table *__tgt_rtl_load_binary_locked(int32_t device_id,
// get flat group size if present, else Default_WG_Size
int16_t WGSizeVal = RTLDeviceInfoTy::Default_WG_Size;
// Max parallel level
int16_t MaxParLevVal = 0;
// get Kernel Descriptor if present.
// Keep struct in sync wih getTgtAttributeStructQTy in CGOpenMPRuntime.cpp
struct KernDescValType {
......@@ -1150,8 +1217,6 @@ __tgt_target_table *__tgt_rtl_load_binary_locked(int32_t device_id,
uint16_t TSize;
uint16_t WG_Size;
uint8_t Mode;
uint8_t HostServices;
uint8_t MaxParallelLevel;
};
struct KernDescValType KernDescVal;
std::string KernDescNameStr(e->name);
......@@ -1160,7 +1225,7 @@ __tgt_target_table *__tgt_rtl_load_binary_locked(int32_t device_id,
void *KernDescPtr;
uint32_t KernDescSize;
void *CallStackAddr;
void *CallStackAddr = nullptr;
err = interop_get_symbol_info((char *)image->ImageStart, img_size,
KernDescName, &KernDescPtr, &KernDescSize);
......@@ -1182,32 +1247,6 @@ __tgt_target_table *__tgt_rtl_load_binary_locked(int32_t device_id,
DP("KernDesc: TSize: %d\n", KernDescVal.TSize);
DP("KernDesc: WG_Size: %d\n", KernDescVal.WG_Size);
DP("KernDesc: Mode: %d\n", KernDescVal.Mode);
DP("KernDesc: HostServices: %x\n", KernDescVal.HostServices);
DP("KernDesc: MaxParallelLevel: %x\n", KernDescVal.MaxParallelLevel);
// gather location of callStack and size of struct
MaxParLevVal = KernDescVal.MaxParallelLevel;
if (MaxParLevVal > 0) {
uint32_t varsize;
const char *CsNam = "omptarget_nest_par_call_stack";
err = atmi_interop_hsa_get_symbol_info(place, CsNam, &CallStackAddr,
&varsize);
if (err != ATMI_STATUS_SUCCESS) {
fprintf(stderr, "Addr of %s failed\n", CsNam);
return NULL;
}
void *StructSizePtr;
const char *SsNam = "omptarget_nest_par_call_struct_size";
err = interop_get_symbol_info((char *)image->ImageStart, img_size,
SsNam, &StructSizePtr, &varsize);
if ((err != ATMI_STATUS_SUCCESS) ||
(varsize != sizeof(TgtStackItemSize))) {
fprintf(stderr, "Addr of %s failed\n", SsNam);
return NULL;
}
memcpy(&TgtStackItemSize, StructSizePtr, sizeof(TgtStackItemSize));
DP("Size of our struct is %d\n", TgtStackItemSize);
}