isl_basic_set_opt: avoid invalid access on error path
[platform/upstream/isl.git] / isl_reordering.c
1 /*
2  * Copyright 2010      INRIA Saclay
3  *
4  * Use of this software is governed by the MIT license
5  *
6  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8  * 91893 Orsay, France
9  */
10
11 #include <isl_ctx_private.h>
12 #include <isl_space_private.h>
13 #include <isl_reordering.h>
14
15 __isl_give isl_reordering *isl_reordering_alloc(isl_ctx *ctx, int len)
16 {
17         isl_reordering *exp;
18
19         exp = isl_alloc(ctx, struct isl_reordering,
20                         sizeof(struct isl_reordering) + (len - 1) * sizeof(int));
21         if (!exp)
22                 return NULL;
23
24         exp->ref = 1;
25         exp->len = len;
26         exp->dim = NULL;
27
28         return exp;
29 }
30
31 __isl_give isl_reordering *isl_reordering_copy(__isl_keep isl_reordering *exp)
32 {
33         if (!exp)
34                 return NULL;
35
36         exp->ref++;
37         return exp;
38 }
39
40 __isl_give isl_reordering *isl_reordering_dup(__isl_keep isl_reordering *r)
41 {
42         int i;
43         isl_reordering *dup;
44
45         if (!r)
46                 return NULL;
47
48         dup = isl_reordering_alloc(r->dim->ctx, r->len);
49         if (!dup)
50                 return NULL;
51
52         dup->dim = isl_space_copy(r->dim);
53         if (!dup->dim)
54                 return isl_reordering_free(dup);
55         for (i = 0; i < dup->len; ++i)
56                 dup->pos[i] = r->pos[i];
57
58         return dup;
59 }
60
61 __isl_give isl_reordering *isl_reordering_cow(__isl_take isl_reordering *r)
62 {
63         if (!r)
64                 return NULL;
65
66         if (r->ref == 1)
67                 return r;
68         r->ref--;
69         return isl_reordering_dup(r);
70 }
71
72 void *isl_reordering_free(__isl_take isl_reordering *exp)
73 {
74         if (!exp)
75                 return NULL;
76
77         if (--exp->ref > 0)
78                 return NULL;
79
80         isl_space_free(exp->dim);
81         free(exp);
82         return NULL;
83 }
84
85 /* Construct a reordering that maps the parameters of "alignee"
86  * to the corresponding parameters in a new dimension specification
87  * that has the parameters of "aligner" first, followed by
88  * any remaining parameters of "alignee" that do not occur in "aligner".
89  */
90 __isl_give isl_reordering *isl_parameter_alignment_reordering(
91         __isl_keep isl_space *alignee, __isl_keep isl_space *aligner)
92 {
93         int i, j;
94         isl_reordering *exp;
95
96         if (!alignee || !aligner)
97                 return NULL;
98
99         exp = isl_reordering_alloc(alignee->ctx, alignee->nparam);
100         if (!exp)
101                 return NULL;
102
103         exp->dim = isl_space_copy(aligner);
104
105         for (i = 0; i < alignee->nparam; ++i) {
106                 isl_id *id_i;
107                 id_i = isl_space_get_dim_id(alignee, isl_dim_param, i);
108                 if (!id_i)
109                         isl_die(alignee->ctx, isl_error_invalid,
110                                 "cannot align unnamed parameters", goto error);
111                 for (j = 0; j < aligner->nparam; ++j) {
112                         isl_id *id_j;
113                         id_j = isl_space_get_dim_id(aligner, isl_dim_param, j);
114                         isl_id_free(id_j);
115                         if (id_i == id_j)
116                                 break;
117                 }
118                 if (j < aligner->nparam) {
119                         exp->pos[i] = j;
120                         isl_id_free(id_i);
121                 } else {
122                         int pos;
123                         pos = isl_space_dim(exp->dim, isl_dim_param);
124                         exp->dim = isl_space_add_dims(exp->dim, isl_dim_param, 1);
125                         exp->dim = isl_space_set_dim_id(exp->dim,
126                                                 isl_dim_param, pos, id_i);
127                         exp->pos[i] = pos;
128                 }
129         }
130
131         if (!exp->dim)
132                 return isl_reordering_free(exp);
133         return exp;
134 error:
135         isl_reordering_free(exp);
136         return NULL;
137 }
138
139 __isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp,
140         unsigned extra)
141 {
142         int i;
143         isl_reordering *res;
144         int offset;
145
146         if (!exp)
147                 return NULL;
148         if (extra == 0)
149                 return exp;
150
151         offset = isl_space_dim(exp->dim, isl_dim_all) - exp->len;
152         res = isl_reordering_alloc(exp->dim->ctx, exp->len + extra);
153         if (!res)
154                 goto error;
155         res->dim = isl_space_copy(exp->dim);
156         for (i = 0; i < exp->len; ++i)
157                 res->pos[i] = exp->pos[i];
158         for (i = exp->len; i < res->len; ++i)
159                 res->pos[i] = offset + i;
160
161         isl_reordering_free(exp);
162
163         return res;
164 error:
165         isl_reordering_free(exp);
166         return NULL;
167 }
168
169 __isl_give isl_reordering *isl_reordering_extend_space(
170         __isl_take isl_reordering *exp, __isl_take isl_space *dim)
171 {
172         isl_reordering *res;
173
174         if (!exp || !dim)
175                 goto error;
176
177         res = isl_reordering_extend(isl_reordering_copy(exp),
178                                     isl_space_dim(dim, isl_dim_all) - exp->len);
179         res = isl_reordering_cow(res);
180         if (!res)
181                 goto error;
182         isl_space_free(res->dim);
183         res->dim = isl_space_replace(dim, isl_dim_param, exp->dim);
184
185         isl_reordering_free(exp);
186
187         if (!res->dim)
188                 return isl_reordering_free(res);
189
190         return res;
191 error:
192         isl_reordering_free(exp);
193         isl_space_free(dim);
194         return NULL;
195 }
196
197 void isl_reordering_dump(__isl_keep isl_reordering *exp)
198 {
199         int i;
200
201         for (i = 0; i < exp->len; ++i)
202                 fprintf(stderr, "%d -> %d; ", i, exp->pos[i]);
203         fprintf(stderr, "\n");
204 }