layers: Addition of source_line_info.py script to simplify codegen debugging

vk-layer-generate.py and vk_helper.py now use added source_line_info.py script to insert comments throughout generated code indicating where the code was generated from.
diff --git a/source_line_info.py b/source_line_info.py
new file mode 100755
index 0000000..0d6f07e
--- /dev/null
+++ b/source_line_info.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2015 LunarG, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+from inspect import currentframe, getframeinfo
+
+# This is a wrapper class for inspect module that returns a formatted line
+#  with details of the source file and line number of python code who called
+#  into this class. The result can them be added to codegen to simplify
+#  debug as it shows where code was generated from.
+class sourcelineinfo():
+    def __init__(self):
+        self.general_prefix = "// CODEGEN : "
+        self.file_prefix = "file "
+        self.line_prefix = "line #"
+        self.enabled = True
+
+    def get(self):
+        if self.enabled:
+            frameinfo = getframeinfo(currentframe().f_back)
+            return "%s%s%s %s%s" % (self.general_prefix, self.file_prefix, frameinfo.filename, self.line_prefix, frameinfo.lineno)
+        return ""
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index 39158be..3431d89 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -31,6 +31,7 @@
 
 import vulkan
 import vk_helper
+from source_line_info import sourcelineinfo
 
 def proto_is_global(proto):
     if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name == "CreateInstance" or proto.name == "GetGlobalExtensionInfo" or proto.name == "GetPhysicalDeviceExtensionInfo":
@@ -53,6 +54,7 @@
         self.protos = vulkan.protos
         self.no_addr = False
         self.layer_name = ""
+        self.lineinfo = sourcelineinfo()
 
     def run(self):
         print(self.generate())
@@ -159,6 +161,7 @@
 
     def _gen_create_msg_callback(self):
         r_body = []
+        r_body.append('%s' % self.lineinfo.get())
         r_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)')
         r_body.append('{')
         r_body.append('    return layer_create_msg_callback(instance, instance_dispatch_table(instance), msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
@@ -167,6 +170,7 @@
 
     def _gen_destroy_msg_callback(self):
         r_body = []
+        r_body.append('%s' % self.lineinfo.get())
         r_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)')
         r_body.append('{')
         r_body.append('    return layer_destroy_msg_callback(instance, instance_dispatch_table(instance), msgCallback);')
@@ -176,6 +180,7 @@
     def _gen_layer_get_global_extension_info(self, layer="Generic"):
         ggei_body = []
         if layer == 'APIDump' or layer == 'Generic':
+            ggei_body.append('%s' % self.lineinfo.get())
             ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 1')
             ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
             ggei_body.append('    {')
@@ -186,6 +191,7 @@
             ggei_body.append('    }')
             ggei_body.append('};')
         else:
+            ggei_body.append('%s' % self.lineinfo.get())
             ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 2')
             ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
             ggei_body.append('    {')
@@ -202,6 +208,7 @@
             ggei_body.append('    }')
             ggei_body.append('};')
         ggei_body.append('')
+        ggei_body.append('%s' % self.lineinfo.get())
         ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)')
         ggei_body.append('{')
         ggei_body.append('    uint32_t *count;')
@@ -356,6 +363,7 @@
 
         # add customized layer_intercept_proc
         body = []
+        body.append('%s' % self.lineinfo.get())
         body.append("static inline void* layer_intercept_proc(const char *name)")
         body.append("{")
         body.append(generate_get_proc_addr_check("name"))
@@ -394,6 +402,7 @@
         exts = []
         exts.append(self._gen_create_msg_callback())
         exts.append(self._gen_destroy_msg_callback())
+        exts.append('%s' % self.lineinfo.get())
         exts.append('uint64_t objTrackGetObjectsCount(VkObjectType type)')
         exts.append('{')
         exts.append('    return numTotalObjs;')
@@ -423,6 +432,7 @@
         exts.append('    }')
         exts.append('    return VK_SUCCESS;')
         exts.append('}')
+        exts.append('%s' % self.lineinfo.get())
         exts.append('uint64_t objTrackGetObjectsOfTypeCount(VkObjectType type)')
         exts.append('{')
         exts.append('    return numObjs[type];')
@@ -457,6 +467,7 @@
 
     def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
         func_body = []
+        func_body.append('%s' % self.lineinfo.get())
         func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
                          "{\n"
                          "    void* addr;\n"
@@ -489,6 +500,7 @@
                                  '        return %s%s%s;' % (extra_space, ext_name, cpp_prefix, ext_name, cpp_postfix))
                 if 0 != len(ext_enable):
                     func_body.append('    }')
+        func_body.append('%s' % self.lineinfo.get())
         func_body.append("    {\n"
                          "        if (pDisp->GetDeviceProcAddr == NULL)\n"
                          "            return NULL;\n"
@@ -527,9 +539,11 @@
 
     def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
         func_body = ["#include \"vk_dispatch_table_helper.h\""]
+        func_body.append('%s' % self.lineinfo.get())
         func_body.append('static void init%s(void)\n'
                          '{\n' % self.layer_name)
         if init_opts:
+            func_body.append('%s' % self.lineinfo.get())
             func_body.append('    const char *strOpt;')
             func_body.append('    // initialize %s options' % self.layer_name)
             func_body.append('    getLayerOptionEnum("%sReportLevel", (uint32_t *) &g_reportFlags);' % self.layer_name)
@@ -546,8 +560,8 @@
             func_body.append('            g_logFile = stdout;')
             func_body.append('    }')
             func_body.append('')
-
         if lockname is not None:
+            func_body.append('%s' % self.lineinfo.get())
             func_body.append("    if (!%sLockInitialized)" % lockname)
             func_body.append("    {")
             func_body.append("        // TODO/TBD: Need to delete this mutex sometime.  How???")
@@ -620,6 +634,7 @@
         table = ''
         if proto_is_global(proto):
            table = 'Instance'
+        funcs.append('%s' % self.lineinfo.get())
         if proto.ret != "void":
             ret_val = "%s result = " % proto.ret
             stmt = "    return result;\n"
@@ -691,6 +706,7 @@
 class APIDumpSubcommand(Subcommand):
     def generate_header(self):
         header_txt = []
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('#include <fstream>')
         header_txt.append('#include <iostream>')
         header_txt.append('#include <string>')
@@ -721,6 +737,7 @@
         header_txt.append('    }')
         header_txt.append('}')
         header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('#include "loader_platform.h"')
         header_txt.append('#include "vkLayer.h"')
         header_txt.append('#include "vk_struct_string_helper_cpp.h"')
@@ -738,6 +755,7 @@
         header_txt.append('static int printLockInitialized = 0;')
         header_txt.append('static loader_platform_thread_mutex printLock;')
         header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('#define MAX_TID 513')
         header_txt.append('static loader_platform_thread_id tidMapping[MAX_TID] = {0};')
         header_txt.append('static uint32_t maxTID = 0;')
@@ -777,6 +795,7 @@
 
     def generate_init(self):
         func_body = []
+        func_body.append('%s' % self.lineinfo.get())
         func_body.append('#include "vk_dispatch_table_helper.h"')
         func_body.append('#include "layers_config.h"')
         func_body.append('')
@@ -811,6 +830,7 @@
         func_body.append('        }')
         func_body.append('    }')
         func_body.append('')
+        func_body.append('%s' % self.lineinfo.get())
         func_body.append('    char const*const noAddrStr = getLayerOption("APIDumpNoAddr");')
         func_body.append('    if(noAddrStr != NULL)')
         func_body.append('    {')
@@ -838,6 +858,7 @@
         func_body.append('        }')
         func_body.append('    }')
         func_body.append('')
+        func_body.append('%s' % self.lineinfo.get())
         func_body.append('    ConfigureOutputStream(writeToFile, flushAfterWrite);')
         func_body.append('')
         func_body.append('    if (!printLockInitialized)')
@@ -867,7 +888,8 @@
             ret_val = "%s result = " % proto.ret
             stmt = "    return result;\n"
         f_open = 'loader_platform_thread_lock_mutex(&printLock);\n    '
-        log_func = '    if (StreamControl::writeAddress == true) {'
+        log_func = '%s\n' % self.lineinfo.get()
+        log_func += '    if (StreamControl::writeAddress == true) {'
         log_func += '\n        (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
         log_func_no_addr = '\n        (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
         f_close = '\n    loader_platform_thread_unlock_mutex(&printLock);'
@@ -913,12 +935,14 @@
         log_func += ';'
         log_func_no_addr += ';'
         log_func += '\n    }\n    else {%s;\n    }' % log_func_no_addr;
+        log_func += '\n%s' % self.lineinfo.get()
         #print("Proto %s has param_dict: %s" % (proto.name, sp_param_dict))
         if len(sp_param_dict) > 0:
             indent = '    '
             log_func += '\n%sif (g_APIDumpDetailed) {' % indent
             indent += '    '
             i_decl = False
+            log_func += '\n%s' % self.lineinfo.get()
             log_func += '\n%sstring tmp_str;' % indent
             for sp_index in sp_param_dict:
                 #print("sp_index: %s" % str(sp_index))
@@ -927,6 +951,7 @@
                     local_name = proto.params[sp_index].name
                     if '*' not in proto.params[sp_index].ty:
                         local_name = '&%s' % proto.params[sp_index].name
+                    log_func += '\n%s' % self.lineinfo.get()
                     log_func += '\n%sif (%s) {' % (indent, local_name)
                     indent += '    '
                     log_func += '\n%stmp_str = %s(%s, "    ");' % (indent, cis_print_func, local_name)
@@ -949,6 +974,7 @@
                         i_decl = True
                     log_func += '\n%sif (%s) {' % (indent, proto.params[sp_index].name)
                     indent += '    '
+                    log_func += '\n%s' % self.lineinfo.get()
                     log_func += '\n%sfor (i = 0; i < %s; i++) {' % (indent, sp_param_dict[sp_index])
                     indent += '    '
                     log_func += '\n%s%s' % (indent, cis_print_func)
@@ -1033,6 +1059,7 @@
 class ObjectTrackerSubcommand(Subcommand):
     def generate_header(self):
         header_txt = []
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <inttypes.h>\n')
         header_txt.append('#include "loader_platform.h"\n')
         header_txt.append('#include "object_track.h"\n\n')
@@ -1053,6 +1080,7 @@
         header_txt.append('// Objects stored in a global map w/ struct containing basic info')
         header_txt.append('unordered_map<VkObject, OBJTRACK_NODE*> objMap;')
         header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('#define NUM_OBJECT_TYPES (VK_NUM_OBJECT_TYPE + (VK_OBJECT_TYPE_SWAP_CHAIN_WSI - VK_OBJECT_TYPE_DISPLAY_WSI))')
         header_txt.append('')
         header_txt.append('static uint64_t                         numObjs[NUM_OBJECT_TYPES]     = {0};')
@@ -1076,7 +1104,7 @@
         header_txt.append('    VkQueue                          queue;')
         header_txt.append('    uint32_t                         refCount;')
         header_txt.append('} OT_QUEUE_INFO;')
-        header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('// Global list of QueueInfo structures, one per queue')
         header_txt.append('static OT_QUEUE_INFO *g_pQueueInfo = NULL;')
         header_txt.append('')
@@ -1090,7 +1118,7 @@
         header_txt.append('    }')
         header_txt.append('    return index;')
         header_txt.append('}')
-        header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('// Validate that object is in the object map')
         header_txt.append('static void validate_object(const VkObject object)')
         header_txt.append('{')
@@ -1118,7 +1146,7 @@
         header_txt.append('        }')
         header_txt.append('    }')
         header_txt.append('}')
-        header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('// Add new queue to head of global queue list')
         header_txt.append('static void addQueueInfo(uint32_t queueNodeIndex, VkQueue queue)')
         header_txt.append('{')
@@ -1156,7 +1184,7 @@
         header_txt.append('    }')
         header_txt.append('    g_pQueueInfo = pQueueInfo;')
         header_txt.append('}')
-        header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('static void create_obj(VkObject vkObj, VkObjectType objType) {')
         header_txt.append('    char str[1024];')
         header_txt.append('    sprintf(str, "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkObjectType(objType), reinterpret_cast<VkUintPtrLeast64>(vkObj));')
@@ -1208,7 +1236,7 @@
         header_txt.append('        }')
         header_txt.append('    }')
         header_txt.append('}')
-        header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('// Reset selected flag state for an object node')
         header_txt.append('static void reset_status(VkObject vkObj, VkObjectType objType, ObjectStatusFlags status_flag) {')
         header_txt.append('    if (objMap.find(vkObj) != objMap.end()) {')
@@ -1249,7 +1277,7 @@
         header_txt.append('        }')
         header_txt.append('    }')
         header_txt.append('}')
-        header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('// Check object status for selected flag state')
         header_txt.append('static bool32_t validate_status(VkObject vkObj, VkObjectType objType, ObjectStatusFlags status_mask, ObjectStatusFlags status_flag, VkFlags msg_flags, OBJECT_TRACK_ERROR error_code, const char* fail_msg) {')
         header_txt.append('    if (objMap.find(vkObj) != objMap.end()) {')
@@ -1320,6 +1348,7 @@
         mutex_unlock = False
         if 'QueueSubmit' in proto.name:
             using_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            using_line += '%s\n' % self.lineinfo.get()
             using_line += '    set_status(fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED);\n'
             using_line += '    // TODO: Fix for updated memory reference mechanism\n'
             using_line += '    // validate_memory_mapping_status(pMemRefs, memRefCount);\n'
@@ -1327,23 +1356,28 @@
             mutex_unlock = True
         elif 'QueueBindSparse' in proto.name:
             using_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            using_line += '%s\n' % self.lineinfo.get()
             using_line += '    validateQueueFlags(queue, "%s");\n' % (proto.name)
             mutex_unlock = True
         elif 'QueueBindObject' in proto.name:
             using_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            using_line += '%s\n' % self.lineinfo.get()
             using_line += '    validateObjectType("vk%s", objType, object);\n' % (proto.name)
             mutex_unlock = True
         elif 'GetObjectInfo' in proto.name:
             using_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            using_line += '%s\n' % self.lineinfo.get()
             using_line += '    validateObjectType("vk%s", objType, object);\n' % (proto.name)
             mutex_unlock = True
         elif 'GetFenceStatus' in proto.name:
             using_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            using_line += '%s\n' % self.lineinfo.get()
             using_line += '    // Warn if submitted_flag is not set\n'
             using_line += '    validate_status(fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED, VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Status Requested for Unsubmitted Fence");\n'
             mutex_unlock = True
         elif 'WaitForFences' in proto.name:
             using_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            using_line += '%s\n' % self.lineinfo.get()
             using_line += '    // Warn if waiting on unsubmitted fence\n'
             using_line += '    for (uint32_t i = 0; i < fenceCount; i++) {\n'
             using_line += '        validate_status(pFences[i], VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED, VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Waiting for Unsubmitted Fence");\n'
@@ -1351,14 +1385,17 @@
             mutex_unlock = True
         elif 'MapMemory' in proto.name:
             using_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            using_line += '%s\n' % self.lineinfo.get()
             using_line += '    set_status(mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);\n'
             mutex_unlock = True
         elif 'UnmapMemory' in proto.name:
             using_line =  '    loader_platform_thread_lock_mutex(&objLock);\n'
+            using_line += '%s\n' % self.lineinfo.get()
             using_line += '    reset_status(mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);\n'
             mutex_unlock = True
         elif 'AllocDescriptor' in proto.name: # Allocates array of DSs
             create_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            create_line += '%s\n' % self.lineinfo.get()
             create_line += '    for (uint32_t i = 0; i < *pCount; i++) {\n'
             create_line += '        create_obj(pDescriptorSets[i], VK_OBJECT_TYPE_DESCRIPTOR_SET);\n'
             create_line += '    }\n'
@@ -1367,9 +1404,11 @@
             create_line =  '    loader_platform_thread_lock_mutex(&objLock);\n'
             create_line += '    if (result == VK_SUCCESS) {\n'
             if 'CreateDevice' in proto.name:
+                create_line += '%s\n' % self.lineinfo.get()
                 create_line += '        enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions);\n'
                 create_line += '        createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
             elif 'CreateInstance' in proto.name:
+                create_line += '%s\n' % self.lineinfo.get()
                 create_line += '        enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions);\n'
                 create_line += '        VkLayerInstanceDispatchTable *pTable = instance_dispatch_table(*pInstance);\n'
                 create_line += '        debug_report_init_instance_extension_dispatch_table(\n'
@@ -1382,10 +1421,12 @@
 
         if 'GetDeviceQueue' in proto.name:
             destroy_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            destroy_line += '%s\n' % self.lineinfo.get()
             destroy_line += '    addQueueInfo(queueNodeIndex, *pQueue);\n'
             destroy_line += '    loader_platform_thread_unlock_mutex(&objLock);\n'
         elif 'DestroyObject' in proto.name:
             destroy_line =  '    loader_platform_thread_lock_mutex(&objLock);\n'
+            destroy_line += '%s\n' % self.lineinfo.get()
             destroy_line += '    validateObjectType("vk%s", objType, object);\n' % (proto.name)
             destroy_line += '    destroy_obj(%s);\n' % (proto.params[2].name)
             destroy_line += '    loader_platform_thread_unlock_mutex(&objLock);\n'
@@ -1394,6 +1435,7 @@
             using_line +=  '    VkLayerDispatchTable *pDisp  = device_dispatch_table(device);\n'
             destroy_line  = '    deviceExtMap.erase(pDisp);\n'
             destroy_line += '    loader_platform_thread_lock_mutex(&objLock);\n'
+            destroy_line += '%s\n' % self.lineinfo.get()
             destroy_line += '    destroy_obj(device);\n'
             destroy_line += '    // Report any remaining objects\n'
             destroy_line += '    for (auto it = objMap.begin(); it != objMap.end(); ++it) {\n'
@@ -1428,10 +1470,12 @@
             destroy_line += '    destroy_instance_dispatch_table(key);\n'
         elif 'Free' in proto.name:
             destroy_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            destroy_line += '%s\n' % self.lineinfo.get()
             destroy_line += '    destroy_obj(%s);\n' % (proto.params[1].name)
             destroy_line += '    loader_platform_thread_unlock_mutex(&objLock);\n'
         elif 'Destroy' in proto.name:
             destroy_line  = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            destroy_line += '%s\n' % self.lineinfo.get()
             destroy_line += '    destroy_obj(%s);\n' % (param0_name)
             destroy_line += '    loader_platform_thread_unlock_mutex(&objLock);\n'
         if len(object_params) > 0:
@@ -1478,6 +1522,7 @@
                 table_type = "device"
             if 'CreateInstance' in proto.name:
                dispatch_param = '*' + proto.params[1].name
+            funcs.append('%s' % self.lineinfo.get())
             funcs.append('%s%s\n'
                      '{\n'
                      '%s'
@@ -1505,6 +1550,7 @@
 class ThreadingSubcommand(Subcommand):
     def generate_header(self):
         header_txt = []
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('#include <stdio.h>')
         header_txt.append('#include <stdlib.h>')
         header_txt.append('#include <string.h>')
@@ -1531,7 +1577,7 @@
         header_txt.append('static loader_platform_thread_cond threadingCond;')
         header_txt.append('static int printLockInitialized = 0;')
         header_txt.append('static loader_platform_thread_mutex printLock;\n')
-        header_txt.append('')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('static void useObject(VkObject object, const char* type)')
         header_txt.append('{')
         header_txt.append('    loader_platform_thread_id tid = loader_platform_get_thread_id();')
@@ -1556,6 +1602,7 @@
         header_txt.append('    }')
         header_txt.append('    loader_platform_thread_unlock_mutex(&threadingLock);')
         header_txt.append('}')
+        header_txt.append('%s' % self.lineinfo.get())
         header_txt.append('static void finishUsingObject(VkObject object)')
         header_txt.append('{')
         header_txt.append('    // Object is no longer in use')
@@ -1614,6 +1661,7 @@
             return None
         # Initialize in early calls
         if proto.params[0].ty == "VkPhysicalDevice":
+            funcs.append('%s' % self.lineinfo.get())
             funcs.append('%s%s\n'
                      '{\n'
                      '    %s%s_dispatch_table(%s)->%s;\n'
@@ -1622,6 +1670,7 @@
             return "\n".join(funcs)
         # Functions changing command buffers need thread safe use of first parameter
         if proto.params[0].ty == "VkCmdBuffer":
+            funcs.append('%s' % self.lineinfo.get())
             funcs.append('%s%s\n'
                      '{\n'
                      '    useObject((VkObject) %s, "%s");\n'
@@ -1677,6 +1726,7 @@
         if len(checked_params) == 0:
             return None
         # Surround call with useObject and finishUsingObject for each checked_param
+        funcs.append('%s' % self.lineinfo.get())
         funcs.append('%s%s' % (qual, decl))
         funcs.append('{')
         for param in checked_params:
diff --git a/vk_helper.py b/vk_helper.py
index 4a7dce5..46daad5 100755
--- a/vk_helper.py
+++ b/vk_helper.py
@@ -24,15 +24,14 @@
 import argparse
 import os
 import sys
+from source_line_info import sourcelineinfo
 
-# code_gen.py overview
-# This script generates code based on input headers
-# Initially it's intended to support Mantle and VK headers and
-#  generate wrappers functions that can be used to display
+# vk_helper.py overview
+# This script generates code based on vulkan input header
+#  It generate wrappers functions that can be used to display
 #  structs in a human-readable txt format, as well as utility functions
 #  to print enum values as strings
 
-
 def handle_args():
     parser = argparse.ArgumentParser(description='Perform analysis of vogl trace.')
     parser.add_argument('input_file', help='The input header file from which code will be generated.')
@@ -756,9 +755,12 @@
         sh_funcs = []
         # First generate prototypes for every struct
         # XXX - REMOVE this comment
+        lineinfo = sourcelineinfo()
+        sh_funcs.append('%s' % lineinfo.get())
         for s in sorted(self.struct_dict):
             sh_funcs.append('string %s(const %s* pStruct, const string prefix);' % (self._get_sh_func_name(s), typedef_fwd_dict[s]))
         sh_funcs.append('\n')
+        sh_funcs.append('%s' % lineinfo.get())
         for s in sorted(self.struct_dict):
             num_non_enum_elems = [(is_type(self.struct_dict[s][elem]['type'], 'enum') and not self.struct_dict[s][elem]['ptr']) for elem in self.struct_dict[s]].count(False)
             stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs
@@ -766,7 +768,9 @@
             for m in sorted(self.struct_dict[s]):
                 if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct') or self.struct_dict[s][m]['array']:
                     stp_list.append(self.struct_dict[s][m])
+            sh_funcs.append('%s' % lineinfo.get())
             sh_funcs.append('string %s(const %s* pStruct, const string prefix)\n{' % (self._get_sh_func_name(s), typedef_fwd_dict[s]))
+            sh_funcs.append('%s' % lineinfo.get())
             indent = '    '
             sh_funcs.append('%susing namespace StreamControl;' % (indent))
             sh_funcs.append('%sstring final_str;' % (indent))
@@ -784,16 +788,16 @@
                     if 1 < stp_list[index]['full_type'].count('*'):
                         addr_char = ''
                     if (stp_list[index]['array'] and 'char' not in stp_list[index]['type']):
-                        sh_funcs.append('/* A */');
+                        sh_funcs.append('%s' % lineinfo.get())
                         if stp_list[index]['dyn_array']:
-                            sh_funcs.append('/* AA */');
+                            sh_funcs.append('%s' % lineinfo.get())
                             array_count = 'pStruct->%s' % (stp_list[index]['array_size'])
                         else:
-                            sh_funcs.append('/* AB */');
+                            sh_funcs.append('%s' % lineinfo.get())
                             array_count = '%s' % (stp_list[index]['array_size'])
+                        sh_funcs.append('%s' % lineinfo.get())
                         sh_funcs.append('%sstp_strs[%u] = "";' % (indent, index))
                         if not idx_ss_decl:
-                            sh_funcs.append('/* AC */');
                             sh_funcs.append('%sstringstream index_ss;' % (indent))
                             idx_ss_decl = True
                         sh_funcs.append('%sif (pStruct->%s) {' % (indent, stp_list[index]['name']))
@@ -803,81 +807,94 @@
                         sh_funcs.append('%sindex_ss.str("");' % (indent))
                         sh_funcs.append('%sindex_ss << i;' % (indent))
                         if is_type(stp_list[index]['type'], 'enum'):
-                            #sh_funcs.append('/* AD */');
+                            sh_funcs.append('%s' % lineinfo.get())
                             addr_char = ''
                             #value_print = 'string_%s(%spStruct->%s)' % (self.struct_dict[s][m]['type'], deref, self.struct_dict[s][m]['name'])
                             sh_funcs.append('%sss[%u] << string_%s(pStruct->%s[i]);' % (indent, index, stp_list[index]['type'], stp_list[index]['name']))
                             sh_funcs.append('%sstp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] = " + ss[%u].str() + "\\n";' % (indent, index, stp_list[index]['name'], index))
                         elif is_type(stp_list[index]['type'], 'struct'):
-                            #sh_funcs.append('/* AD */');
+                            sh_funcs.append('%s' % lineinfo.get())
                             sh_funcs.append('%sss[%u] << %spStruct->%s[i];' % (indent, index, addr_char, stp_list[index]['name']))
                             sh_funcs.append('%stmp_str = %s(%spStruct->%s[i], extra_indent);' % (indent, self._get_sh_func_name(stp_list[index]['type']), addr_char, stp_list[index]['name']))
                             if self.no_addr:
-                                sh_funcs.append('/* AEA */');
+                                sh_funcs.append('%s' % lineinfo.get())
                                 sh_funcs.append('%sstp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (addr)\\n" + tmp_str;' % (indent, index, stp_list[index]['name']))
                             else:
-                                sh_funcs.append('/* AEB */');
+                                sh_funcs.append('%s' % lineinfo.get())
                                 sh_funcs.append('%sstp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (" + ss[%u].str() + ")\\n" + tmp_str;' % (indent, index, stp_list[index]['name'], index))
                         else:
-                            #sh_funcs.append('/* AD */');
+                            sh_funcs.append('%s' % lineinfo.get())
                             addr_char = ''
                             sh_funcs.append('%sss[%u] << %spStruct->%s[i];' % (indent, index, addr_char, stp_list[index]['name']))
                             sh_funcs.append('%sstp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] = " + ss[%u].str() + "\\n";' % (indent, index, stp_list[index]['name'], index))
+                        sh_funcs.append('%s' % lineinfo.get())
                         sh_funcs.append('%sss[%u].str("");' % (indent, index))
                         indent = indent[4:]
                         sh_funcs.append('%s}' % (indent))
                         indent = indent[4:]
                         sh_funcs.append('%s}' % (indent))
                     elif (stp_list[index]['ptr']):
-                        sh_funcs.append('/* B */');
+                        sh_funcs.append('%s' % lineinfo.get())
                         sh_funcs.append('    if (pStruct->%s) {' % stp_list[index]['name'])
                         if 'pNext' == stp_list[index]['name']:
+                            sh_funcs.append('%s' % lineinfo.get())
                             sh_funcs.append('        tmp_str = dynamic_display((void*)pStruct->pNext, prefix);')
                         else:
                             if stp_list[index]['name'] in ['pImageViews', 'pBufferViews']:
                                 # TODO : This is a quick hack to handle these arrays of ptrs
+                                sh_funcs.append('%s' % lineinfo.get())
                                 sh_funcs.append('        tmp_str = %s(&pStruct->%s[0], extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name']))
                             else:
+                                sh_funcs.append('%s' % lineinfo.get())
                                 sh_funcs.append('        tmp_str = %s(pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name']))
                         sh_funcs.append('        ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name']))
                         if self.no_addr:
+                            sh_funcs.append('%s' % lineinfo.get())
                             sh_funcs.append('        stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name']))
                         else:
+                            sh_funcs.append('%s' % lineinfo.get())
                             sh_funcs.append('        stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index))
                         sh_funcs.append('        ss[%u].str("");' % (index))
                         sh_funcs.append('    }')
                         sh_funcs.append('    else')
                         sh_funcs.append('        stp_strs[%u] = "";' % index)
                     else:
-                        #sh_funcs.append('/* C */');
+                        sh_funcs.append('%s' % lineinfo.get())
                         sh_funcs.append('    tmp_str = %s(&pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name']))
                         sh_funcs.append('    ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name']))
                         if self.no_addr:
                             sh_funcs.append('    stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name']))
+                            sh_funcs.append('%s' % lineinfo.get())
                         else:
                             sh_funcs.append('    stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index))
+                            sh_funcs.append('%s' % lineinfo.get())
                         sh_funcs.append('    ss[%u].str("");' % index)
             # Now print one-line info for all data members
             index = 0
             final_str = ''
             for m in sorted(self.struct_dict[s]):
-                deref = ''
                 if not is_type(self.struct_dict[s][m]['type'], 'enum'):
                     if is_type(self.struct_dict[s][m]['type'], 'struct') and not self.struct_dict[s][m]['ptr']:
                         if self.no_addr:
+                            sh_funcs.append('%s' % lineinfo.get())
                             sh_funcs.append('    ss[%u].str("addr");' % (index))
                         else:
+                            sh_funcs.append('%s' % lineinfo.get())
                             sh_funcs.append('    ss[%u] << &pStruct->%s;' % (index, self.struct_dict[s][m]['name']))
                     elif 'bool' in self.struct_dict[s][m]['type'].lower():
+                        sh_funcs.append('%s' % lineinfo.get())
                         sh_funcs.append('    ss[%u].str(pStruct->%s ? "TRUE" : "FALSE");' % (index, self.struct_dict[s][m]['name']))
                     elif 'uint8' in self.struct_dict[s][m]['type'].lower():
+                        sh_funcs.append('%s' % lineinfo.get())
                         sh_funcs.append('    ss[%u] << (uint32_t)pStruct->%s;' % (index, self.struct_dict[s][m]['name']))
                     elif 'void' in self.struct_dict[s][m]['type'].lower() and self.struct_dict[s][m]['ptr']:
+                        sh_funcs.append('%s' % lineinfo.get())
                         sh_funcs.append('    if (StreamControl::writeAddress)')
                         sh_funcs.append('        ss[%u] << pStruct->%s;' % (index, self.struct_dict[s][m]['name']))
                         sh_funcs.append('    else')
                         sh_funcs.append('        ss[%u].str("address");' % (index))
                     else:
+                        sh_funcs.append('%s' % lineinfo.get())
                         (po, pa) = self._get_struct_print_formatted(self.struct_dict[s][m])
                         if "addr" in po: # or self.struct_dict[s][m]['ptr']:
                             sh_funcs.append('    ss[%u].str("addr");' % (index))
@@ -888,6 +905,7 @@
                 else:
                     # For an non-empty array of enums just print address w/ note that array will be displayed below
                     if self.struct_dict[s][m]['ptr']:
+                        sh_funcs.append('%s' % lineinfo.get())
                         sh_funcs.append('    if (pStruct->%s)' % (self.struct_dict[s][m]['name']))
                         sh_funcs.append('        ss[%u] << pStruct->%s << " (See individual array values below)";' % (index, self.struct_dict[s][m]['name']))
                         sh_funcs.append('    else')
@@ -901,9 +919,11 @@
             final_str = final_str[3:] # strip off the initial ' + '
             if 0 != num_stps: # Append data for any embedded structs
                 final_str += " + %s" % " + ".join(['stp_strs[%u]' % n for n in reversed(range(num_stps))])
+            sh_funcs.append('%s' % lineinfo.get())
             sh_funcs.append('    final_str = %s;' % final_str)
             sh_funcs.append('    return final_str;\n}')
         # Add function to return a string value for input void*
+        sh_funcs.append('%s' % lineinfo.get())
         sh_funcs.append("string string_convert_helper(const void* toString, const string prefix)\n{")
         sh_funcs.append("    using namespace StreamControl;")
         sh_funcs.append("    stringstream ss;")
@@ -911,6 +931,7 @@
         sh_funcs.append('    string final_str = prefix + ss.str();')
         sh_funcs.append("    return final_str;")
         sh_funcs.append("}")
+        sh_funcs.append('%s' % lineinfo.get())
         # Add function to return a string value for input uint32_t
         sh_funcs.append("string string_convert_helper(const uint32_t toString, const string prefix)\n{")
         sh_funcs.append("    using namespace StreamControl;")
@@ -919,6 +940,7 @@
         sh_funcs.append('    string final_str = prefix + ss.str();')
         sh_funcs.append("    return final_str;")
         sh_funcs.append("}")
+        sh_funcs.append('%s' % lineinfo.get())
         # Add function to dynamically print out unknown struct
         sh_funcs.append("string dynamic_display(const void* pStruct, const string prefix)\n{")
         sh_funcs.append("    // Cast to APP_INFO ptr initially just to pull sType off struct")
@@ -941,6 +963,7 @@
                     sh_funcs.append('        break;')
                 sh_funcs.append("        default:")
                 sh_funcs.append("        return NULL;")
+        sh_funcs.append('%s' % lineinfo.get())
         sh_funcs.append("    }")
         sh_funcs.append("}")
         return "\n".join(sh_funcs)