function [stackProfile, profData] = executionStackHelper(...
     sectionIds, stackData, simTimes, ...
     lGlobalRegistry, lCodeDir, ...
     maxSectionId, bitsInChar, targetWordSize, isSimulink, ...
     lMaxStackSize, lTargetLargestAtomicIntegerType)
% EXECUTIONSTACKHELPER creates a stackProfile object from stack profiling
% samples

% Copyright 2023 The MathWorks, Inc.

arguments
    sectionIds (1,:) uint32
    stackData  (1,:) uint64
    simTimes  (1,:) double
    lGlobalRegistry (1,1) coder.profile.ProbeGlobalRegistry
    lCodeDir (1,:) char = ''
    maxSectionId (1,1) uint32 = 2^31-1
    bitsInChar (1,1) uint32 = 8
    targetWordSize (1,1) uint32 = 32
    isSimulink (1,1) logical = false
    lMaxStackSize (1,1) uint32 = 0
    lTargetLargestAtomicIntegerType (1,:) char = 'Char'
end

% initialize data
lModelName = lGlobalRegistry.Model;
lTaskIDs = uint32([]);
lFunctionIDs = uint32([]);
lCatchIDs = uint32([]);
lMatchCatchIds = uint32([]);

% extract probe information from the global register
probes = lGlobalRegistry.getAllProbes();
lNumProbes = numel(probes);
for i = 1:lNumProbes
    pType = probes{i}{1};
    pData = probes{i}{2};
    switch pType
        case coder_profile_ProbeType.OFFSET_STACK_PROBE.string
            % ignore - only needed with MATLAB Coder
        case coder_profile_ProbeType.TASK_STACK_PROBE.string
            lTaskIDs(end+1) = uint32(pData{1}); %#ok<AGROW>
        case coder_profile_ProbeType.EXEC_STACK_PROBE.string
            lFunctionIDs(end+1) = uint32(pData{1}); %#ok<AGROW>
        case coder_profile_ProbeType.CATCH_STACK_PROBE.string
            lCatchIDs(end+1) = uint32(pData{1}); %#ok<AGROW>
            lMatchCatchIds(end+1) = uint32(pData{5}); %#ok<AGROW>
    end
end

% process samples
profData = coder.profile.execStackAnalyze(...
    maxSectionId, ... % max section ID
    bitsInChar, ...   % #bits in char
    sectionIds, ...   % list of section IDs
    stackData, ...    % list of stack register
    simTimes, ...     % list of simulation times
    lTaskIDs, ...     % list of section IDs associated to tasks
    lFunctionIDs, ... % list of section IDs associated to functions
    lCatchIDs, ...    % list of section IDs associated to catch
    lMatchCatchIds);  % bind function and catch

% create execution stack
if isSimulink
    lReportFcn = 'coder.internal.SLCExecTimeReport';
else
    lReportFcn = 'coder.internal.MLCExecTimeReport';
end
stackProfile = coder.profile.ExecutionStack(profData, lReportFcn);
stackProfile.GlobalRegistry = lGlobalRegistry;
stackProfile.CodeDir = lCodeDir;
stackProfile.TargetWordSizeInBits = targetWordSize;
stackProfile.PtrSizeInBits = lGlobalRegistry.ProfilingStackDriver.getPtrSizeInBits();
stackProfile.TargetLargestAtomicIntegerType = lTargetLargestAtomicIntegerType;
stackProfile.IsGenericDriver = lGlobalRegistry.IsGenericStackDriver;
stackProfile.TopMostComponentName = lModelName;
stackProfile.OriginalComponentName = lModelName;
stackProfile.ShowCodeGenReportLink = false;
stackProfile.IsSimulinkWorkflow = isSimulink;
if lMaxStackSize > 0
    stackProfile.MaxStackUsageAllowed = lMaxStackSize;
end
stackProfile.traceabilityUpdate();

end
