This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Replace libdw nested functions with macros, part 1.


To be compiled without gnu99 extension.

Signed-off-by: Chih-Hung Hsieh <chh@google.com>
---
 libdw/ChangeLog            |   9 ++
 libdw/cfi.c                |  73 ++++++++--------
 libdw/dwarf_getscopevar.c  |  38 +++++----
 libdw/dwarf_getsrclines.c  |  85 +++++++++---------
 libdw/libdw_visit_scopes.c | 209 +++++++++++++++++++++++++--------------------
 5 files changed, 226 insertions(+), 188 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 13beefc..13ecc1e 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,12 @@
+2015-09-14  Chih-Hung Hsieh  <chh@google.com>
+
+	* cfi.c (execute_cfi): Replace simple nested functions with macros.
+	* dwarf_getsrclines.c (read_srclines): Likewise.
+	* dwarf_getscopevar.c (dwarf_getscopevar): Move complicated
+	nested functions to file scope.
+	* dwarf_visit_scopes.c (__libdw_visit_scopes): Move recursive nested
+	functions to file scope; inline 'recurse' at its single call site.
+
 2015-09-09  Chih-Hung Hsieh  <chh@google.com>
 
 	* dwarf_macro_getsrcfiles.c (dwarf_macro_getsrcfiles): Remove
diff --git a/libdw/cfi.c b/libdw/cfi.c
index 5a6f956..d15838a 100644
--- a/libdw/cfi.c
+++ b/libdw/cfi.c
@@ -77,42 +77,43 @@ execute_cfi (Dwarf_CFI *cache,
   } while (0)
 
   Dwarf_Frame *fs = *state;
-  inline bool enough_registers (Dwarf_Word reg)
-    {
-      /* Don't allow insanely large register numbers.  268435456 registers
-	 should be enough for anybody.  And very large values might overflow
-	 the array size and offsetof calculations below.  */
-      if (unlikely (reg >= INT32_MAX / sizeof (fs->regs[0])))
-	{
-	  result = DWARF_E_INVALID_CFI;
-	  return false;
-	}
-
-      if (fs->nregs <= reg)
-	{
-	  size_t size = offsetof (Dwarf_Frame, regs[reg + 1]);
-	  Dwarf_Frame *bigger = realloc (fs, size);
-	  if (unlikely (bigger == NULL))
-	    {
-	      result = DWARF_E_NOMEM;
-	      return false;
-	    }
-	  else
-	    {
-	      eu_static_assert (reg_unspecified == 0);
-	      memset (bigger->regs + bigger->nregs, 0,
-		      (reg + 1 - bigger->nregs) * sizeof bigger->regs[0]);
-	      bigger->nregs = reg + 1;
-	      fs = bigger;
-	    }
-	}
-      return true;
-    }
-
-  inline void require_cfa_offset (void)
-  {
-    if (unlikely (fs->cfa_rule != cfa_offset))
-      fs->cfa_rule = cfa_invalid;
+#define enough_registers(_reg) \
+    ( { \
+      Dwarf_Word reg = _reg; \
+      bool has_enough = true; \
+      /* Don't allow insanely large register numbers.  268435456 registers */ \
+      /* should be enough for anybody.  And very large values might overflow */ \
+      /* the array size and offsetof calculations below.  */ \
+      if (unlikely (reg >= INT32_MAX / sizeof (fs->regs[0]))) \
+	{ \
+	  result = DWARF_E_INVALID_CFI; \
+	  has_enough = false; \
+	} \
+      else if (fs->nregs <= reg) \
+	{ \
+	  size_t size = offsetof (Dwarf_Frame, regs[reg + 1]); \
+	  Dwarf_Frame *bigger = realloc (fs, size); \
+	  if (unlikely (bigger == NULL)) \
+	    { \
+	      result = DWARF_E_NOMEM; \
+	      has_enough = false; \
+	    } \
+	  else \
+	    { \
+	      eu_static_assert (reg_unspecified == 0); \
+	      memset (bigger->regs + bigger->nregs, 0, \
+		      (reg + 1 - bigger->nregs) * sizeof bigger->regs[0]); \
+	      bigger->nregs = reg + 1; \
+	      fs = bigger; \
+	    } \
+	} \
+      has_enough; \
+    } )
+
+#define require_cfa_offset() \
+  { \
+    if (unlikely (fs->cfa_rule != cfa_offset)) \
+      fs->cfa_rule = cfa_invalid; \
   }
 
 #define register_rule(regno, r_rule, r_value) do {	\
diff --git a/libdw/dwarf_getscopevar.c b/libdw/dwarf_getscopevar.c
index eb50c0a..e59dccd 100644
--- a/libdw/dwarf_getscopevar.c
+++ b/libdw/dwarf_getscopevar.c
@@ -52,6 +52,25 @@ getattr (Dwarf_Die *die, int search_name, Dwarf_Word *value)
 						      &attr_mem), value);
 }
 
+inline static int
+file_matches (Dwarf_Files * files, size_t idx,
+              const char *lastfile, size_t match_file_len,
+              const char *match_file, bool *lastfile_matches)
+{
+  if (idx >= files->nfiles)
+    return false;
+  const char *file = files->info[idx].name;
+  if (file != lastfile)
+    {
+      size_t len = strlen (file);
+      *lastfile_matches = (len >= match_file_len
+                          && !memcmp (match_file, file, match_file_len)
+                          && (len == match_file_len
+                              || file[len - match_file_len - 1] == '/'));
+    }
+  return *lastfile_matches;
+}
+
 /* Search SCOPES[0..NSCOPES-1] for a variable called NAME.
    Ignore the first SKIP_SHADOWS scopes that match the name.
    If MATCH_FILE is not null, accept only declaration in that source file;
@@ -72,22 +91,6 @@ dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
   size_t match_file_len = match_file == NULL ? 0 : strlen (match_file);
   bool lastfile_matches = false;
   const char *lastfile = NULL;
-  inline bool file_matches (Dwarf_Files *files, size_t idx)
-    {
-      if (idx >= files->nfiles)
-	return false;
-
-      const char *file = files->info[idx].name;
-      if (file != lastfile)
-	{
-	  size_t len = strlen (file);
-	  lastfile_matches = (len >= match_file_len
-			      && !memcmp (match_file, file, match_file_len)
-			      && (len == match_file_len
-				  || file[len - match_file_len - 1] == '/'));
-	}
-      return lastfile_matches;
-    }
 
   /* Start with the innermost scope and move out.  */
   for (int out = 0; out < nscopes; ++out)
@@ -130,7 +133,8 @@ dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
 			|| getfiles (&scopes[out], &files) != 0)
 		      break;
 
-		    if (!file_matches (files, i))
+		    if (!file_matches (files, i, lastfile, match_file_len,
+		                       match_file, &lastfile_matches))
 		      break;
 
 		    if (match_lineno > 0
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 389c824..dfa3e58 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -338,15 +338,54 @@ read_srclines (Dwarf *dbg,
 
   /* Apply the "operation advance" from a special opcode or
      DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
-  inline void advance_pc (unsigned int op_advance)
-  {
-    addr += minimum_instr_len * ((op_index + op_advance)
-				 / max_ops_per_instr);
-    op_index = (op_index + op_advance) % max_ops_per_instr;
+#define advance_pc(_op_advance) \
+  { \
+    unsigned int op_advance = _op_advance; \
+    addr += minimum_instr_len * ((op_index + op_advance) \
+            / max_ops_per_instr); \
+    op_index = (op_index + op_advance) % max_ops_per_instr; \
   }
 
   /* Process the instructions.  */
 
+  /* Set the line information.  For some fields we use bitfields,
+     so we would lose information if the encoded values are too large.
+     Check just for paranoia, and call the data "invalid" if it
+     violates our assumptions on reasonable limits for the values.  */
+#define SET(field) \
+    new_line->line.field = field; \
+    if (unlikely (new_line->line.field != field)) \
+      { \
+        add_new_line_result = true; \
+        break; \
+      }
+
+#define add_new_line(_new_line, _end_sequence) \
+  ( { \
+    struct linelist *new_line = _new_line; \
+    bool end_sequence = _end_sequence; \
+    bool add_new_line_result = false; \
+    new_line->next = linelist; \
+    new_line->sequence = nlinelist; \
+    linelist = new_line; \
+    ++nlinelist; \
+    do { \
+      SET (addr); \
+      SET (op_index); \
+      SET (file); \
+      SET (line); \
+      SET (column); \
+      SET (is_stmt); \
+      SET (basic_block); \
+      SET (end_sequence); \
+      SET (prologue_end); \
+      SET (epilogue_begin); \
+      SET (isa); \
+      SET (discriminator); \
+    } while (0); \
+    add_new_line_result; \
+  } )
+
   /* Adds a new line to the matrix.  For the first MAX_STACK_LINES
      entries just return a slot in the preallocated stack array.  */
   struct linelist llstack[MAX_STACK_LINES];
@@ -361,42 +400,6 @@ read_srclines (Dwarf *dbg,
       goto invalid_data;						\
   } while (0)
 
-  inline bool add_new_line (struct linelist *new_line, bool end_sequence)
-  {
-    new_line->next = linelist;
-    new_line->sequence = nlinelist;
-    linelist = new_line;
-    ++nlinelist;
-
-    /* Set the line information.  For some fields we use bitfields,
-       so we would lose information if the encoded values are too large.
-       Check just for paranoia, and call the data "invalid" if it
-       violates our assumptions on reasonable limits for the values.  */
-#define SET(field)							      \
-    do {								      \
-      new_line->line.field = field;					      \
-      if (unlikely (new_line->line.field != field))			      \
-	return true;						      \
-    } while (0)
-
-    SET (addr);
-    SET (op_index);
-    SET (file);
-    SET (line);
-    SET (column);
-    SET (is_stmt);
-    SET (basic_block);
-    SET (end_sequence);
-    SET (prologue_end);
-    SET (epilogue_begin);
-    SET (isa);
-    SET (discriminator);
-
-#undef SET
-
-    return false;
-  }
-
   while (linep < lineendp)
     {
       unsigned int opcode;
diff --git a/libdw/libdw_visit_scopes.c b/libdw/libdw_visit_scopes.c
index d0b5134..9970e25 100644
--- a/libdw/libdw_visit_scopes.c
+++ b/libdw/libdw_visit_scopes.c
@@ -64,104 +64,125 @@ may_have_scopes (Dwarf_Die *die)
   return false;
 }
 
-int
-__libdw_visit_scopes (depth, root, imports, previsit, postvisit, arg)
-     unsigned int depth;
-     struct Dwarf_Die_Chain *root;
-     struct Dwarf_Die_Chain *imports;
-     int (*previsit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
-     int (*postvisit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
-     void *arg;
+/* Checks the given DIE hasn't been imported yet to prevent cycles.  */
+static inline bool
+imports_contains (struct Dwarf_Die_Chain *imports, Dwarf_Die *die)
 {
-  struct Dwarf_Die_Chain child;
-  int ret;
+  for (struct Dwarf_Die_Chain *import = imports; import != NULL;
+       import = import->parent)
+    if (import->die.addr == die->addr)
+      return true;
+
+  return false;
+}
 
-  child.parent = root;
-  if ((ret = INTUSE(dwarf_child) (&root->die, &child.die)) != 0)
-    return ret < 0 ? -1 : 0; // Having zero children is legal.
+typedef struct walk_children_closure {
+  /* Parameters of __libdw_visit_scopes. */
+  unsigned int depth;
+  struct Dwarf_Die_Chain *root;
+  struct Dwarf_Die_Chain *imports;
+  int (*previsit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
+  int (*postvisit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
+  void *arg;
+  /* Return value of recursive walker. */
+  int ret;
+  /* Extra local variables for the walker. */
+  struct Dwarf_Die_Chain child;
+} walk_children_closure;
 
-  inline int recurse (void)
+static inline int
+walk_children (walk_children_closure *walker)
+{
+  do
     {
-      return __libdw_visit_scopes (depth + 1, &child, imports,
-				   previsit, postvisit, arg);
+      /* For an imported unit, it is logically as if the children of
+         that unit are siblings of the other children.  So don't do
+         a full recursion into the imported unit, but just walk the
+         children in place before moving to the next real child.  */
+      while (INTUSE(dwarf_tag) (&walker->child.die) == DW_TAG_imported_unit)
+        {
+          Dwarf_Die orig_child_die = walker->child.die;
+          Dwarf_Attribute attr_mem;
+          Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&walker->child.die,
+                                                      DW_AT_import,
+                                                      &attr_mem);
+          if (INTUSE(dwarf_formref_die) (attr, &walker->child.die) != NULL
+                && INTUSE(dwarf_child) (&walker->child.die,
+                                        &walker->child.die) == 0)
+            {
+              if (imports_contains (walker->imports, &orig_child_die))
+                {
+                  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+                  return -1;
+                }
+              struct Dwarf_Die_Chain *orig_imports = walker->imports;
+              struct Dwarf_Die_Chain import = { .die = orig_child_die,
+                                                .parent = orig_imports };
+              walker->imports = &import;
+              int result = walk_children (walker);
+              walker->imports = orig_imports;
+              if (result != DWARF_CB_OK)
+                return result;
+            }
+
+          /* Any "real" children left?  */
+          if ((walker->ret = INTUSE(dwarf_siblingof) (&orig_child_die,
+                                                      &walker->child.die)) != 0)
+          return walker->ret < 0 ? -1 : 0;
+        }
+
+      walker->child.prune = false;
+
+      /* previsit is declared NN */
+      int result = (*walker->previsit)
+            (walker->depth + 1, &walker->child, walker->arg);
+      if (result != DWARF_CB_OK)
+        return result;
+
+      if (!walker->child.prune && may_have_scopes (&walker->child.die)
+          && INTUSE(dwarf_haschildren) (&walker->child.die))
+        {
+          result = __libdw_visit_scopes (walker->depth + 1, &walker->child,
+                                         walker->imports, walker->previsit,
+                                         walker->postvisit, walker->arg);
+          if (result != DWARF_CB_OK)
+            return result;
+        }
+
+      if (walker->postvisit != NULL)
+        {
+          result = (*walker->postvisit) (walker->depth + 1, &walker->child, walker->arg);
+          if (result != DWARF_CB_OK)
+            return result;
+        }
     }
+  while ((walker->ret = INTUSE(dwarf_siblingof) (
+      &walker->child.die, &walker->child.die)) == 0);
 
-  /* Checks the given DIE hasn't been imported yet to prevent cycles.  */
-  inline bool imports_contains (Dwarf_Die *die)
-  {
-    for (struct Dwarf_Die_Chain *import = imports; import != NULL;
-	 import = import->parent)
-      if (import->die.addr == die->addr)
-	return true;
-
-    return false;
-  }
-
-  inline int walk_children ()
-  {
-    do
-      {
-	/* For an imported unit, it is logically as if the children of
-	   that unit are siblings of the other children.  So don't do
-	   a full recursion into the imported unit, but just walk the
-	   children in place before moving to the next real child.  */
-	while (INTUSE(dwarf_tag) (&child.die) == DW_TAG_imported_unit)
-	  {
-	    Dwarf_Die orig_child_die = child.die;
-	    Dwarf_Attribute attr_mem;
-	    Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child.die,
-							DW_AT_import,
-							&attr_mem);
-	    if (INTUSE(dwarf_formref_die) (attr, &child.die) != NULL
-                && INTUSE(dwarf_child) (&child.die, &child.die) == 0)
-	      {
-		if (imports_contains (&orig_child_die))
-		  {
-		    __libdw_seterrno (DWARF_E_INVALID_DWARF);
-		    return -1;
-		  }
-		struct Dwarf_Die_Chain *orig_imports = imports;
-		struct Dwarf_Die_Chain import = { .die = orig_child_die,
-						  .parent = orig_imports };
-		imports = &import;
-		int result = walk_children ();
-		imports = orig_imports;
-		if (result != DWARF_CB_OK)
-		  return result;
-	      }
-
-	    /* Any "real" children left?  */
-	    if ((ret = INTUSE(dwarf_siblingof) (&orig_child_die,
-						&child.die)) != 0)
-	      return ret < 0 ? -1 : 0;
-	  };
-
-	child.prune = false;
-
-	/* previsit is declared NN */
-	int result = (*previsit) (depth + 1, &child, arg);
-	if (result != DWARF_CB_OK)
-	  return result;
-
-	if (!child.prune && may_have_scopes (&child.die)
-	    && INTUSE(dwarf_haschildren) (&child.die))
-	  {
-	    result = recurse ();
-	    if (result != DWARF_CB_OK)
-	      return result;
-	  }
-
-	if (postvisit != NULL)
-	  {
-	    result = (*postvisit) (depth + 1, &child, arg);
-	    if (result != DWARF_CB_OK)
-	      return result;
-	  }
-      }
-    while ((ret = INTUSE(dwarf_siblingof) (&child.die, &child.die)) == 0);
-
-    return ret < 0 ? -1 : 0;
-  }
-
-  return walk_children ();
+  return walker->ret < 0 ? -1 : 0;
+}
+
+int
+__libdw_visit_scopes (
+     unsigned int depth,
+     struct Dwarf_Die_Chain *root,
+     struct Dwarf_Die_Chain *imports,
+     int (*previsit) (unsigned int depth, struct Dwarf_Die_Chain *, void *),
+     int (*postvisit) (unsigned int depth, struct Dwarf_Die_Chain *, void *),
+     void *arg)
+{
+  walk_children_closure walker = {
+    .depth = depth,
+    .root = root,
+    .imports = imports,
+    .previsit = previsit,
+    .postvisit = postvisit,
+    .arg = arg
+  };
+
+  walker.child.parent = root;
+  if ((walker.ret = INTUSE(dwarf_child) (&walker.root->die, &walker.child.die)) != 0)
+    return walker.ret < 0 ? -1 : 0; // Having zero children is legal.
+
+  return walk_children (&walker);
 }
-- 
2.6.0.rc0.131.gf624c3d


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]