Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
  * Copyright © 2010 Intel Corporation
3
  *
4
  * Permission is hereby granted, free of charge, to any person obtaining a
5
  * copy of this software and associated documentation files (the "Software"),
6
  * to deal in the Software without restriction, including without limitation
7
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
  * and/or sell copies of the Software, and to permit persons to whom the
9
  * Software is furnished to do so, subject to the following conditions:
10
  *
11
  * The above copyright notice and this permission notice (including the next
12
  * paragraph) shall be included in all copies or substantial portions of the
13
  * Software.
14
  *
15
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
  * DEALINGS IN THE SOFTWARE.
22
  */
23
 
24
 /**
25
  * \file opt_dead_functions.cpp
26
  *
27
  * Eliminates unused functions from the linked program.
28
  */
29
 
30
 #include "ir.h"
31
 #include "ir_visitor.h"
32
 #include "ir_expression_flattening.h"
33
 #include "glsl_types.h"
34
 
35
 class signature_entry : public exec_node
36
 {
37
 public:
38
    signature_entry(ir_function_signature *sig)
39
    {
40
       this->signature = sig;
41
       this->used = false;
42
    }
43
 
44
    ir_function_signature *signature;
45
    bool used;
46
 };
47
 
48
 class ir_dead_functions_visitor : public ir_hierarchical_visitor {
49
 public:
50
    ir_dead_functions_visitor()
51
    {
52
       this->mem_ctx = ralloc_context(NULL);
53
    }
54
 
55
    ~ir_dead_functions_visitor()
56
    {
57
       ralloc_free(this->mem_ctx);
58
    }
59
 
60
    virtual ir_visitor_status visit_enter(ir_function_signature *);
61
    virtual ir_visitor_status visit_enter(ir_call *);
62
 
63
    signature_entry *get_signature_entry(ir_function_signature *var);
64
 
65
    bool (*predicate)(ir_instruction *ir);
66
 
67
    /* List of signature_entry */
68
    exec_list signature_list;
69
    void *mem_ctx;
70
 };
71
 
72
 
73
 signature_entry *
74
 ir_dead_functions_visitor::get_signature_entry(ir_function_signature *sig)
75
 {
76
    foreach_iter(exec_list_iterator, iter, this->signature_list) {
77
       signature_entry *entry = (signature_entry *)iter.get();
78
       if (entry->signature == sig)
79
	  return entry;
80
    }
81
 
82
    signature_entry *entry = new(mem_ctx) signature_entry(sig);
83
    this->signature_list.push_tail(entry);
84
    return entry;
85
 }
86
 
87
 
88
 ir_visitor_status
89
 ir_dead_functions_visitor::visit_enter(ir_function_signature *ir)
90
 {
91
    signature_entry *entry = this->get_signature_entry(ir);
92
 
93
    if (strcmp(ir->function_name(), "main") == 0) {
94
       entry->used = true;
95
    }
96
 
97
    return visit_continue;
98
 }
99
 
100
 
101
 ir_visitor_status
102
 ir_dead_functions_visitor::visit_enter(ir_call *ir)
103
 {
104
    signature_entry *entry = this->get_signature_entry(ir->get_callee());
105
 
106
    entry->used = true;
107
 
108
   return visit_continue;
109
}
110
 
111
bool
112
do_dead_functions(exec_list *instructions)
113
{
114
   ir_dead_functions_visitor v;
115
   bool progress = false;
116
 
117
   visit_list_elements(&v, instructions);
118
 
119
   /* Now that we've figured out which function signatures are used, remove
120
    * the unused ones, and remove function definitions that have no more
121
    * signatures.
122
    */
123
    foreach_iter(exec_list_iterator, iter, v.signature_list) {
124
      signature_entry *entry = (signature_entry *)iter.get();
125
 
126
      if (!entry->used) {
127
	 entry->signature->remove();
128
	 delete entry->signature;
129
	 progress = true;
130
      }
131
      delete(entry);
132
   }
133
 
134
   /* We don't just do this above when we nuked a signature because of
135
    * const pointers.
136
    */
137
   foreach_iter(exec_list_iterator, iter, *instructions) {
138
      ir_instruction *ir = (ir_instruction *)iter.get();
139
      ir_function *func = ir->as_function();
140
 
141
      if (func && func->signatures.is_empty()) {
142
	 /* At this point (post-linking), the symbol table is no
143
	  * longer in use, so not removing the function from the
144
	  * symbol table should be OK.
145
	  */
146
	 func->remove();
147
	 delete func;
148
	 progress = true;
149
      }
150
   }
151
 
152
   return progress;
153
}