Mercurial > projects > ddmd
annotate dmd/TypeFunction.d @ 157:b7b61140701d
* added all missing default cases in switch statements
+ Lexer.getDocComment
+ Lexer.combineComments
author | trass3r |
---|---|
date | Thu, 16 Sep 2010 01:34:10 +0200 |
parents | fe2e1b93e88f |
children | e3afd1303184 |
rev | line source |
---|---|
0 | 1 module dmd.TypeFunction; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.TypeNext; |
5 import dmd.TypeSArray; | |
6 import dmd.TypeArray; | |
123 | 7 import dmd.TemplateTupleParameter; |
0 | 8 import dmd.ArrayTypes; |
9 import dmd.LINK; | |
10 import dmd.StructDeclaration; | |
11 import dmd.TypeStruct; | |
12 import dmd.Global; | |
13 import dmd.STC; | |
14 import dmd.MOD; | |
73 | 15 import dmd.PROT; |
123 | 16 import dmd.TypeIdentifier; |
17 import dmd.TemplateParameter; | |
129 | 18 import dmd.TypeInfoFunctionDeclaration; |
123 | 19 import dmd.Tuple; |
0 | 20 import dmd.Type; |
21 import dmd.Loc; | |
22 import dmd.Scope; | |
23 import dmd.Identifier; | |
24 import dmd.OutBuffer; | |
25 import dmd.HdrGenState; | |
26 import dmd.CppMangleState; | |
27 import dmd.TypeInfoDeclaration; | |
28 import dmd.MATCH; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
29 import dmd.Parameter; |
0 | 30 import dmd.Expression; |
31 import dmd.RET; | |
32 import dmd.TY; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
33 import dmd.TRUST; |
0 | 34 import dmd.Util; |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
35 import dmd.FuncDeclaration; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
36 import dmd.Dsymbol; |
135 | 37 import dmd.TypeTuple; |
123 | 38 import dmd.TemplateInstance : isTuple; |
0 | 39 |
40 import dmd.backend.TYPE; | |
41 import dmd.backend.PARAM; | |
42 import dmd.backend.Util; | |
43 import dmd.backend.TYM; | |
44 import dmd.backend.TF; | |
45 import dmd.backend.mTY; | |
46 | |
47 import core.stdc.stdlib; | |
48 import core.stdc.string; | |
49 | |
129 | 50 import std.stdio; |
51 | |
0 | 52 class TypeFunction : TypeNext |
53 { | |
54 // .next is the return type | |
55 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
56 Parameters parameters; // function parameters |
0 | 57 int varargs; // 1: T t, ...) style for variable number of arguments |
58 // 2: T t ...) style for variable number of arguments | |
59 bool isnothrow; // true: nothrow | |
60 bool ispure; // true: pure | |
61 bool isproperty; // can be called without parentheses | |
62 bool isref; // true: returns a reference | |
63 LINK linkage; // calling convention | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
64 TRUST trust; // level of trust |
135 | 65 Expressions fargs; // function arguments |
0 | 66 |
67 int inuse; | |
68 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
69 this(Parameters parameters, Type treturn, int varargs, LINK linkage) |
0 | 70 { |
71 super(TY.Tfunction, treturn); | |
72 | |
73 //if (!treturn) *(char*)0=0; | |
74 // assert(treturn); | |
75 assert(0 <= varargs && varargs <= 2); | |
76 this.parameters = parameters; | |
77 this.varargs = varargs; | |
78 this.linkage = linkage; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
79 this.trust = TRUSTdefault; |
0 | 80 } |
81 | |
72 | 82 override Type syntaxCopy() |
0 | 83 { |
84 Type treturn = next ? next.syntaxCopy() : null; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
85 auto params = Parameter.arraySyntaxCopy(parameters); |
0 | 86 TypeFunction t = new TypeFunction(params, treturn, varargs, linkage); |
87 t.mod = mod; | |
88 t.isnothrow = isnothrow; | |
89 t.ispure = ispure; | |
90 t.isproperty = isproperty; | |
91 t.isref = isref; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
92 t.trust = trust; |
135 | 93 t.fargs = fargs; |
0 | 94 |
95 return t; | |
96 } | |
97 | |
98 version (DumbClone) { | |
99 } else { | |
100 final TypeFunction cloneTo(TypeFunction t) | |
101 { | |
102 super.cloneTo(t); | |
103 | |
104 // these 3 should be set by ctor | |
105 assert(t.parameters is null); | |
106 assert(t.varargs == varargs); | |
107 assert(t.linkage == linkage); | |
108 | |
109 t.isnothrow = isnothrow; | |
110 t.ispure = ispure; | |
111 t.isproperty = isproperty; | |
112 t.isref = isref; | |
113 t.inuse = inuse; | |
114 | |
115 if (parameters) | |
116 { | |
117 t.parameters = parameters.copy(); | |
129 | 118 foreach (arg; parameters) |
0 | 119 { |
120 Argument cpy = arg.clone(); | |
129 | 121 t.parameters[i] = cpy; |
0 | 122 } |
123 } | |
124 | |
125 return t; | |
126 } | |
127 | |
128 TypeFunction clone() | |
129 { | |
129 | 130 assert(this.classinfo is TypeFunction.classinfo); |
0 | 131 return cloneTo(new TypeFunction(null, next, varargs, linkage)); |
132 } | |
133 } | |
72 | 134 override Type semantic(Loc loc, Scope sc) |
0 | 135 { |
136 if (deco) // if semantic() already run | |
137 { | |
138 //printf("already done\n"); | |
139 return this; | |
140 } | |
141 //printf("TypeFunction.semantic() this = %p\n", this); | |
135 | 142 //printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", toChars(), sc->stc, fargs); |
0 | 143 |
144 /* Copy in order to not mess up original. | |
145 * This can produce redundant copies if inferring return type, | |
146 * as semantic() will get called again on this. | |
147 */ | |
148 | |
129 | 149 TypeFunction tf = cloneThis(this); |
0 | 150 |
151 if (sc.stc & STC.STCpure) | |
152 tf.ispure = true; | |
153 if (sc.stc & STC.STCnothrow) | |
154 tf.isnothrow = true; | |
155 if (sc.stc & STC.STCref) | |
156 tf.isref = true; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
157 if (sc.stc & STCsafe) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
158 tf.trust = TRUST.TRUSTsafe; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
159 if (sc.stc & STCtrusted) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
160 tf.trust = TRUST.TRUSTtrusted; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
161 if (sc.stc & STCproperty) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
162 tf.isproperty = true; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
163 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
164 tf.linkage = sc.linkage; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
165 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
166 /* If the parent is @safe, then this function defaults to safe |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
167 * too. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
168 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
169 if (tf.trust == TRUST.TRUSTdefault) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
170 for (Dsymbol p = sc.func; p; p = p.toParent2()) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
171 { FuncDeclaration fd = p.isFuncDeclaration(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
172 if (fd) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
173 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
174 if (fd.isSafe()) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
175 tf.trust = TRUST.TRUSTsafe; // default to @safe |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
176 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
177 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
178 } |
0 | 179 |
135 | 180 bool wildreturn = false; |
0 | 181 if (tf.next) |
182 { | |
183 tf.next = tf.next.semantic(loc,sc); | |
96 | 184 version(SARRAYVALUE) {} else |
185 { | |
0 | 186 if (tf.next.toBasetype().ty == TY.Tsarray) |
129 | 187 { |
188 error(loc, "functions cannot return static array %s", tf.next.toChars()); | |
0 | 189 tf.next = Type.terror; |
190 } | |
96 | 191 } |
0 | 192 if (tf.next.toBasetype().ty == TY.Tfunction) |
129 | 193 { |
194 error(loc, "functions cannot return a function"); | |
0 | 195 tf.next = Type.terror; |
196 } | |
197 if (tf.next.toBasetype().ty == TY.Ttuple) | |
129 | 198 { |
199 error(loc, "functions cannot return a tuple"); | |
0 | 200 tf.next = Type.terror; |
201 } | |
202 if (tf.next.isauto() && !(sc.flags & SCOPE.SCOPEctor)) | |
129 | 203 error(loc, "functions cannot return scope %s", tf.next.toChars()); |
135 | 204 if (tf.next.toBasetype().ty == TY.Tvoid) |
205 tf.isref = false; // rewrite "ref void" as just "void" | |
206 if (tf.next.isWild()) | |
207 wildreturn = true; | |
208 } | |
0 | 209 |
135 | 210 bool wildparams = false; |
211 bool wildsubparams = false; | |
0 | 212 if (tf.parameters) |
73 | 213 { |
214 /* Create a scope for evaluating the default arguments for the parameters | |
215 */ | |
216 Scope argsc = sc.push(); | |
217 argsc.stc = STCundefined; // don't inherit storage class | |
218 argsc.protection = PROT.PROTpublic; | |
219 | |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
220 size_t dim = Parameter.dim(tf.parameters); |
0 | 221 |
222 for (size_t i = 0; i < dim; i++) | |
135 | 223 { auto fparam = Parameter.getNth(tf.parameters, i); |
0 | 224 |
225 tf.inuse++; | |
135 | 226 fparam.type = fparam.type.semantic(loc, argsc); |
0 | 227 if (tf.inuse == 1) tf.inuse--; |
228 | |
135 | 229 fparam.type = fparam.type.addStorageClass(fparam.storageClass); |
0 | 230 |
135 | 231 if (fparam.storageClass & (STC.STCauto | STC.STCalias | STC.STCstatic)) |
0 | 232 { |
135 | 233 if (!fparam.type) |
0 | 234 continue; |
235 } | |
236 | |
135 | 237 Type t = fparam.type.toBasetype(); |
0 | 238 |
135 | 239 if (fparam.storageClass & (STC.STCout | STC.STCref | STC.STClazy)) |
0 | 240 { |
96 | 241 //if (t.ty == TY.Tsarray) |
242 //error(loc, "cannot have out or ref parameter of type %s", t.toChars()); | |
135 | 243 if (fparam.storageClass & STC.STCout && fparam.type.mod & (STCconst | STCimmutable)) |
96 | 244 error(loc, "cannot have const or immutabl out parameter of type %s", t.toChars()); |
0 | 245 } |
135 | 246 if (!(fparam.storageClass & STC.STClazy) && t.ty == TY.Tvoid) |
247 error(loc, "cannot have parameter of type %s", fparam.type.toChars()); | |
0 | 248 |
135 | 249 if (t.isWild()) |
250 { | |
251 wildparams = true; | |
252 if (tf.next && !wildreturn) | |
253 error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')"); | |
254 } | |
255 else if (!wildsubparams && t.hasWild()) | |
256 wildsubparams = true; | |
0 | 257 |
135 | 258 if (fparam.defaultArg) |
259 { | |
260 fparam.defaultArg = fparam.defaultArg.semantic(argsc); | |
261 fparam.defaultArg = resolveProperties(argsc, fparam.defaultArg); | |
262 fparam.defaultArg = fparam.defaultArg.implicitCastTo(argsc, fparam.type); | |
263 } | |
264 | |
265 /* If fparam turns out to be a tuple, the number of parameters may | |
0 | 266 * change. |
267 */ | |
268 if (t.ty == TY.Ttuple) | |
135 | 269 { |
270 // Propagate storage class from tuple parameters to their element-parameters. | |
271 auto tt = cast(TypeTuple)t; | |
272 if (tt.arguments) | |
273 { | |
274 auto tdim = tt.arguments.dim; | |
275 foreach (narg; tt.arguments) | |
276 { | |
277 narg.storageClass = fparam.storageClass; | |
278 } | |
279 } | |
280 | |
281 /* Reset number of parameters, and back up one to do this fparam again, | |
282 * now that it is the first element of a tuple | |
283 */ | |
284 dim = Parameter.dim(tf.parameters); | |
0 | 285 i--; |
135 | 286 continue; |
0 | 287 } |
135 | 288 |
289 /* Resolve "auto ref" storage class to be either ref or value, | |
290 * based on the argument matching the parameter | |
291 */ | |
292 if (fparam.storageClass & STC.STCauto) | |
293 { | |
294 if (fargs && i < fargs.dim) | |
295 { | |
296 auto farg = fargs[i]; | |
297 if (farg.isLvalue()) | |
298 {} // ref parameter | |
299 else | |
300 fparam.storageClass &= ~STC.STCref; // value parameter | |
301 } | |
302 else | |
303 error(loc, "auto can only be used for template function parameters"); | |
304 } | |
0 | 305 } |
73 | 306 argsc.pop(); |
0 | 307 } |
135 | 308 |
309 if (wildreturn && !wildparams) | |
310 error(loc, "inout on return means inout must be on a parameter as well for %s", toChars()); | |
311 if (wildsubparams && wildparams) | |
312 error(loc, "inout must be all or none on top level for %s", toChars()); | |
313 | |
0 | 314 if (tf.next) |
315 tf.deco = tf.merge().deco; | |
316 | |
317 if (tf.inuse) | |
318 { error(loc, "recursive type"); | |
319 tf.inuse = 0; | |
320 return terror; | |
321 } | |
322 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
323 if (tf.isproperty && (tf.varargs || Parameter.dim(tf.parameters) > 1)) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
324 error(loc, "properties can only have zero or one parameter"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
325 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
326 if (tf.varargs == 1 && tf.linkage != LINK.LINKd && Parameter.dim(tf.parameters) == 0) |
0 | 327 error(loc, "variadic functions with non-D linkage must have at least one parameter"); |
328 | |
329 /* Don't return merge(), because arg identifiers and default args | |
330 * can be different | |
331 * even though the types match | |
332 */ | |
333 return tf; | |
334 } | |
335 | |
72 | 336 override void toDecoBuffer(OutBuffer buf, int flag) |
0 | 337 { |
338 ubyte mc; | |
339 | |
340 //printf("TypeFunction.toDecoBuffer() this = %p %s\n", this, toChars()); | |
341 //static int nest; if (++nest == 50) *(char*)0=0; | |
342 if (inuse) | |
343 { | |
344 inuse = 2; // flag error to caller | |
345 return; | |
346 } | |
347 inuse++; | |
135 | 348 MODtoDecoBuffer(buf, mod); |
0 | 349 switch (linkage) |
350 { | |
351 case LINK.LINKd: mc = 'F'; break; | |
352 case LINK.LINKc: mc = 'U'; break; | |
353 case LINK.LINKwindows: mc = 'W'; break; | |
354 case LINK.LINKpascal: mc = 'V'; break; | |
355 case LINK.LINKcpp: mc = 'R'; break; | |
157
b7b61140701d
* added all missing default cases in switch statements
trass3r
parents:
148
diff
changeset
|
356 default: |
b7b61140701d
* added all missing default cases in switch statements
trass3r
parents:
148
diff
changeset
|
357 writef("linkage: %d\n", linkage); |
b7b61140701d
* added all missing default cases in switch statements
trass3r
parents:
148
diff
changeset
|
358 assert(false, "ICE: undefined linkage occured"); |
0 | 359 } |
360 buf.writeByte(mc); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
361 if (ispure || isnothrow || isproperty || isref || trust) |
0 | 362 { |
363 if (ispure) | |
364 buf.writestring("Na"); | |
365 if (isnothrow) | |
366 buf.writestring("Nb"); | |
367 if (isref) | |
368 buf.writestring("Nc"); | |
369 if (isproperty) | |
370 buf.writestring("Nd"); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
371 switch (trust) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
372 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
373 case TRUST.TRUSTtrusted: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
374 buf.writestring("Ne"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
375 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
376 case TRUST.TRUSTsafe: |
135 | 377 buf.writestring("Nf"); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
378 break; |
132
c494af1dba80
Fixes for dmd 2.037
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
131
diff
changeset
|
379 default: |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
380 } |
0 | 381 } |
382 // Write argument types | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
383 Parameter.argsToDecoBuffer(buf, parameters); |
0 | 384 //if (buf.data[buf.offset - 1] == '@') halt(); |
385 buf.writeByte('Z' - varargs); // mark end of arg list | |
79 | 386 assert(next); |
0 | 387 next.toDecoBuffer(buf); |
388 inuse--; | |
389 } | |
390 | |
72 | 391 override void toCBuffer(OutBuffer buf, Identifier ident, HdrGenState* hgs) |
0 | 392 { |
393 //printf("TypeFunction.toCBuffer() this = %p\n", this); | |
394 string p = null; | |
395 | |
396 if (inuse) | |
397 { | |
398 inuse = 2; // flag error to caller | |
399 return; | |
400 } | |
401 inuse++; | |
402 | |
403 /* Use 'storage class' style for attributes | |
404 */ | |
135 | 405 if (mod) |
406 { | |
407 MODtoBuffer(buf, mod); | |
408 buf.writeByte(' '); | |
409 } | |
0 | 410 |
411 if (ispure) | |
412 buf.writestring("pure "); | |
413 if (isnothrow) | |
414 buf.writestring("nothrow "); | |
415 if (isproperty) | |
416 buf.writestring("@property "); | |
417 if (isref) | |
418 buf.writestring("ref "); | |
419 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
420 switch (trust) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
421 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
422 case TRUST.TRUSTtrusted: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
423 buf.writestring("@trusted "); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
424 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
425 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
426 case TRUST.TRUSTsafe: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
427 buf.writestring("@safe "); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
428 break; |
148 | 429 |
430 default: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
431 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
432 |
0 | 433 if (next && (!ident || ident.toHChars2() == ident.toChars())) |
434 next.toCBuffer2(buf, hgs, MODundefined); | |
435 if (hgs.ddoc != 1) | |
436 { | |
437 switch (linkage) | |
438 { | |
439 case LINKd: p = null; break; | |
73 | 440 case LINKc: p = " C"; break; |
441 case LINKwindows: p = " Windows"; break; | |
442 case LINKpascal: p = " Pascal"; break; | |
443 case LINKcpp: p = " C++"; break; | |
0 | 444 default: |
445 assert(0); | |
446 } | |
447 } | |
448 | |
449 if (!hgs.hdrgen && p) | |
450 buf.writestring(p); | |
451 if (ident) | |
452 { | |
453 buf.writeByte(' '); | |
454 buf.writestring(ident.toHChars2()); | |
455 } | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
456 Parameter.argsToCBuffer(buf, hgs, parameters, varargs); |
0 | 457 inuse--; |
458 } | |
459 | |
72 | 460 override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) |
0 | 461 { |
462 //printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref); | |
463 string p; | |
464 | |
465 if (inuse) | |
466 { | |
467 inuse = 2; // flag error to caller | |
468 return; | |
469 } | |
470 | |
471 inuse++; | |
472 if (next) | |
473 next.toCBuffer2(buf, hgs, MODundefined); | |
474 | |
475 if (hgs.ddoc != 1) | |
476 { | |
477 switch (linkage) | |
478 { | |
479 case LINKd: p = null; break; | |
480 case LINKc: p = "C "; break; | |
481 case LINKwindows: p = "Windows "; break; | |
482 case LINKpascal: p = "Pascal "; break; | |
483 case LINKcpp: p = "C++ "; break; | |
484 default: assert(0); | |
485 } | |
486 } | |
487 | |
488 if (!hgs.hdrgen && p) | |
489 buf.writestring(p); | |
490 buf.writestring(" function"); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
491 Parameter.argsToCBuffer(buf, hgs, parameters, varargs); |
0 | 492 |
493 /* Use postfix style for attributes | |
494 */ | |
495 if (mod != this.mod) | |
496 { | |
497 modToBuffer(buf); | |
498 } | |
499 | |
500 if (ispure) | |
501 buf.writestring(" pure"); | |
502 if (isnothrow) | |
503 buf.writestring(" nothrow"); | |
504 if (isproperty) | |
505 buf.writestring(" @property"); | |
506 if (isref) | |
507 buf.writestring(" ref"); | |
508 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
509 switch (trust) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
510 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
511 case TRUSTtrusted: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
512 buf.writestring(" @trusted"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
513 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
514 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
515 case TRUSTsafe: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
516 buf.writestring(" @safe"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
517 break; |
143 | 518 |
519 default: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
520 } |
0 | 521 inuse--; |
522 } | |
523 | |
72 | 524 override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) |
0 | 525 { |
123 | 526 //printf("TypeFunction.deduceType()\n"); |
527 //printf("\tthis = %d, ", ty); print(); | |
528 //printf("\ttparam = %d, ", tparam.ty); tparam.print(); | |
529 | |
530 // Extra check that function characteristics must match | |
531 if (tparam && tparam.ty == Tfunction) | |
532 { | |
533 TypeFunction tp = cast(TypeFunction)tparam; | |
534 if (varargs != tp.varargs || | |
535 linkage != tp.linkage) | |
536 return MATCHnomatch; | |
537 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
538 size_t nfargs = Parameter.dim(this.parameters); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
539 size_t nfparams = Parameter.dim(tp.parameters); |
123 | 540 |
541 /* See if tuple match | |
542 */ | |
543 if (nfparams > 0 && nfargs >= nfparams - 1) | |
544 { | |
545 /* See if 'A' of the template parameter matches 'A' | |
546 * of the type of the last function parameter. | |
547 */ | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
548 auto fparam = Parameter.getNth(tp.parameters, nfparams - 1); |
123 | 549 assert(fparam); |
550 assert(fparam.type); | |
551 if (fparam.type.ty != Tident) | |
552 goto L1; | |
553 TypeIdentifier tid = cast(TypeIdentifier)fparam.type; | |
554 if (tid.idents.dim) | |
555 goto L1; | |
556 | |
557 /* Look through parameters to find tuple matching tid.ident | |
558 */ | |
559 size_t tupi = 0; | |
560 for (; 1; tupi++) | |
561 { | |
562 if (tupi == parameters.dim) | |
563 goto L1; | |
564 TemplateParameter t = parameters[tupi]; | |
565 TemplateTupleParameter tup = t.isTemplateTupleParameter(); | |
566 if (tup && tup.ident.equals(tid.ident)) | |
567 break; | |
568 } | |
569 | |
570 /* The types of the function arguments [nfparams - 1 .. nfargs] | |
571 * now form the tuple argument. | |
572 */ | |
573 int tuple_dim = nfargs - (nfparams - 1); | |
574 | |
575 /* See if existing tuple, and whether it matches or not | |
576 */ | |
577 Object o = dedtypes[tupi]; | |
578 if (o) | |
579 { | |
580 // Existing deduced argument must be a tuple, and must match | |
581 Tuple t = isTuple(o); | |
582 if (!t || t.objects.dim != tuple_dim) | |
583 return MATCHnomatch; | |
584 for (size_t i = 0; i < tuple_dim; i++) | |
585 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
586 auto arg = Parameter.getNth(this.parameters, nfparams - 1 + i); |
123 | 587 if (!arg.type.equals(t.objects[i])) |
588 return MATCHnomatch; | |
589 } | |
590 } | |
591 else | |
592 { // Create new tuple | |
593 Tuple t = new Tuple(); | |
594 t.objects.setDim(tuple_dim); | |
595 for (size_t i = 0; i < tuple_dim; i++) | |
596 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
597 auto arg = Parameter.getNth(this.parameters, nfparams - 1 + i); |
123 | 598 t.objects[i] = arg.type; |
599 } | |
600 dedtypes[tupi] = t; | |
601 } | |
602 nfparams--; // don't consider the last parameter for type deduction | |
603 goto L2; | |
604 } | |
605 | |
606 L1: | |
607 if (nfargs != nfparams) | |
608 return MATCHnomatch; | |
609 L2: | |
610 for (size_t i = 0; i < nfparams; i++) | |
611 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
612 auto a = Parameter.getNth(this.parameters, i); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
613 auto ap = Parameter.getNth(tp.parameters, i); |
123 | 614 if (a.storageClass != ap.storageClass || |
615 !a.type.deduceType(sc, ap.type, parameters, dedtypes)) | |
616 return MATCHnomatch; | |
617 } | |
618 } | |
619 return Type.deduceType(sc, tparam, parameters, dedtypes); | |
0 | 620 } |
621 | |
72 | 622 override TypeInfoDeclaration getTypeInfoDeclaration() |
0 | 623 { |
129 | 624 return new TypeInfoFunctionDeclaration(this); |
0 | 625 } |
626 | |
72 | 627 override Type reliesOnTident() |
0 | 628 { |
135 | 629 size_t dim = Parameter.dim(parameters); |
630 for (size_t i = 0; i < dim; i++) | |
631 { | |
632 auto fparam = Parameter.getNth(parameters, i); | |
633 Type t = fparam.type.reliesOnTident(); | |
634 if (t) | |
635 return t; | |
636 } | |
637 return next ? next.reliesOnTident() : null; | |
0 | 638 } |
639 | |
640 version (CPP_MANGLE) { | |
641 void toCppMangle(OutBuffer buf, CppMangleState* cms) | |
642 { | |
643 assert(false); | |
644 } | |
645 } | |
646 | |
647 /*************************** | |
648 * Examine function signature for parameter p and see if | |
649 * p can 'escape' the scope of the function. | |
650 */ | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
651 bool parameterEscapes(Parameter p) |
0 | 652 { |
653 /* Scope parameters do not escape. | |
654 * Allow 'lazy' to imply 'scope' - | |
655 * lazy parameters can be passed along | |
656 * as lazy parameters to the next function, but that isn't | |
657 * escaping. | |
658 */ | |
659 if (p.storageClass & (STC.STCscope | STC.STClazy)) | |
660 return false; | |
661 | |
662 if (ispure) | |
663 { /* With pure functions, we need only be concerned if p escapes | |
664 * via any return statement. | |
665 */ | |
666 Type tret = nextOf().toBasetype(); | |
667 if (!isref && !tret.hasPointers()) | |
668 { /* The result has no references, so p could not be escaping | |
669 * that way. | |
670 */ | |
671 return false; | |
672 } | |
673 } | |
674 | |
675 /* Assume it escapes in the absence of better information. | |
676 */ | |
677 return true; | |
678 } | |
679 | |
680 /******************************** | |
681 * 'args' are being matched to function 'this' | |
682 * Determine match level. | |
683 * Returns: | |
684 * MATCHxxxx | |
685 */ | |
686 MATCH callMatch(Expression ethis, Expressions args) | |
687 { | |
688 //printf("TypeFunction.callMatch() %s\n", toChars()); | |
689 MATCH match = MATCH.MATCHexact; // assume exact match | |
135 | 690 bool exactwildmatch = false; |
691 bool wildmatch = false; | |
0 | 692 |
693 if (ethis) | |
694 { | |
695 Type t = ethis.type; | |
696 if (t.toBasetype().ty == TY.Tpointer) | |
697 t = t.toBasetype().nextOf(); // change struct* to struct | |
698 | |
699 if (t.mod != mod) | |
700 { | |
135 | 701 if (MODimplicitConv(t.mod, mod)) |
0 | 702 match = MATCH.MATCHconst; |
703 else | |
704 return MATCH.MATCHnomatch; | |
705 } | |
706 } | |
707 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
708 size_t nparams = Parameter.dim(parameters); |
0 | 709 size_t nargs = args ? args.dim : 0; |
710 if (nparams == nargs) { | |
711 ; | |
712 } else if (nargs > nparams) | |
713 { | |
714 if (varargs == 0) | |
715 goto Nomatch; // too many args; no match | |
716 match = MATCH.MATCHconvert; // match ... with a "conversion" match level | |
717 } | |
718 | |
719 for (size_t u = 0; u < nparams; u++) | |
720 { | |
721 MATCH m; | |
722 Expression arg; | |
723 | |
724 // BUG: what about out and ref? | |
725 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
726 auto p = Parameter.getNth(parameters, u); |
0 | 727 assert(p); |
728 if (u >= nargs) | |
729 { | |
730 if (p.defaultArg) | |
731 continue; | |
732 if (varargs == 2 && u + 1 == nparams) | |
733 goto L1; | |
734 goto Nomatch; // not enough arguments | |
735 } | |
736 | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
96
diff
changeset
|
737 arg = cast(Expression)args[u]; |
0 | 738 assert(arg); |
96 | 739 // writef("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars()); |
740 | |
0 | 741 |
742 // Non-lvalues do not match ref or out parameters | |
96 | 743 if (p.storageClass & (STC.STCref | STC.STCout)) |
744 { | |
745 if (!arg.isLvalue()) | |
746 goto Nomatch; | |
747 } | |
748 | |
749 if (p.storageClass & STCref) | |
750 { | |
135 | 751 /* Don't allow static arrays to be passed to mutable references |
96 | 752 * to static arrays if the argument cannot be modified. |
753 */ | |
754 Type targb = arg.type.toBasetype(); | |
755 Type tparb = p.type.toBasetype(); | |
756 //writef("%s\n", targb.toChars()); | |
757 //writef("%s\n", tparb.toChars()); | |
758 if (targb.nextOf() && tparb.ty == Tsarray && | |
135 | 759 !MODimplicitConv(targb.nextOf().mod, tparb.nextOf().mod)) |
96 | 760 goto Nomatch; |
761 } | |
0 | 762 |
763 if (p.storageClass & STC.STClazy && p.type.ty == TY.Tvoid && arg.type.ty != TY.Tvoid) | |
764 m = MATCH.MATCHconvert; | |
765 else | |
135 | 766 { |
0 | 767 m = arg.implicitConvTo(p.type); |
135 | 768 if (p.type.isWild()) |
769 { | |
770 if (m == MATCHnomatch) | |
771 { | |
772 m = arg.implicitConvTo(p.type.constOf()); | |
773 if (m == MATCHnomatch) | |
774 m = arg.implicitConvTo(p.type.sharedConstOf()); | |
775 if (m != MATCHnomatch) | |
776 wildmatch = true; // mod matched to wild | |
777 } | |
778 else | |
779 exactwildmatch = true; // wild matched to wild | |
780 | |
781 /* If both are allowed, then there could be more than one | |
782 * binding of mod to wild, leaving a gaping type hole. | |
783 */ | |
784 if (wildmatch && exactwildmatch) | |
785 m = MATCHnomatch; | |
786 } | |
787 } | |
788 | |
0 | 789 //printf("\tm = %d\n", m); |
790 if (m == MATCH.MATCHnomatch) // if no match | |
791 { | |
792 L1: | |
793 if (varargs == 2 && u + 1 == nparams) // if last varargs param | |
794 { | |
795 Type tb = p.type.toBasetype(); | |
796 TypeSArray tsa; | |
797 long sz; | |
798 | |
799 switch (tb.ty) | |
800 { | |
801 case TY.Tsarray: | |
802 tsa = cast(TypeSArray)tb; | |
803 sz = tsa.dim.toInteger(); | |
804 if (sz != nargs - u) | |
805 goto Nomatch; | |
806 case TY.Tarray: | |
807 { | |
808 TypeArray ta = cast(TypeArray)tb; | |
809 for (; u < nargs; u++) | |
810 { | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
96
diff
changeset
|
811 arg = cast(Expression)args[u]; |
0 | 812 assert(arg); |
813 static if (true) { | |
814 /* If lazy array of delegates, | |
815 * convert arg(s) to delegate(s) | |
816 */ | |
817 Type tret = p.isLazyArray(); | |
818 if (tret) | |
819 { | |
820 if (ta.next.equals(arg.type)) | |
821 { | |
822 m = MATCH.MATCHexact; | |
823 } | |
824 else | |
825 { | |
826 m = arg.implicitConvTo(tret); | |
827 if (m == MATCH.MATCHnomatch) | |
828 { | |
829 if (tret.toBasetype().ty == TY.Tvoid) | |
830 m = MATCH.MATCHconvert; | |
831 } | |
832 } | |
833 } | |
834 else | |
835 m = arg.implicitConvTo(ta.next); | |
836 } else { | |
837 m = arg.implicitConvTo(ta.next); | |
838 } | |
839 if (m == MATCH.MATCHnomatch) | |
840 goto Nomatch; | |
841 | |
842 if (m < match) | |
843 match = m; | |
844 } | |
845 goto Ldone; | |
846 } | |
847 | |
848 case TY.Tclass: | |
849 // Should see if there's a constructor match? | |
850 // Or just leave it ambiguous? | |
851 goto Ldone; | |
852 | |
853 default: | |
854 goto Nomatch; | |
855 } | |
856 } | |
857 | |
858 goto Nomatch; | |
859 } | |
860 | |
861 if (m < match) | |
862 match = m; // pick worst match | |
863 } | |
864 | |
865 Ldone: | |
866 //printf("match = %d\n", match); | |
867 return match; | |
868 | |
869 Nomatch: | |
870 //printf("no match\n"); | |
871 return MATCH.MATCHnomatch; | |
872 } | |
873 | |
96 | 874 override type* toCtype() |
0 | 875 { |
876 if (ctype) { | |
877 return ctype; | |
878 } | |
879 | |
880 type* t; | |
881 if (true) | |
882 { | |
883 param_t* paramtypes; | |
884 tym_t tyf; | |
885 type* tp; | |
886 | |
887 paramtypes = null; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
888 size_t nparams = Parameter.dim(parameters); |
0 | 889 for (size_t i = 0; i < nparams; i++) |
890 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
891 auto arg = Parameter.getNth(parameters, i); |
0 | 892 tp = arg.type.toCtype(); |
893 if (arg.storageClass & (STC.STCout | STC.STCref)) | |
894 { | |
895 // C doesn't have reference types, so it's really a pointer | |
896 // to the parameter type | |
897 tp = type_allocn(TYM.TYref, tp); | |
898 } | |
899 param_append_type(¶mtypes,tp); | |
900 } | |
901 tyf = totym(); | |
902 t = type_alloc(tyf); | |
903 t.Tflags |= TF.TFprototype; | |
904 if (varargs != 1) | |
905 t.Tflags |= TF.TFfixed; | |
906 ctype = t; | |
907 t.Tnext = next.toCtype(); | |
908 t.Tnext.Tcount++; | |
909 t.Tparamtypes = paramtypes; | |
910 } | |
911 ctype = t; | |
912 return t; | |
913 } | |
914 | |
915 /*************************** | |
916 * Determine return style of function - whether in registers or | |
917 * through a hidden pointer to the caller's stack. | |
918 */ | |
96 | 919 RET retStyle() |
0 | 920 { |
921 //printf("TypeFunction.retStyle() %s\n", toChars()); | |
95 | 922 version (DMDV2) |
923 { | |
0 | 924 if (isref) |
925 return RET.RETregs; // returns a pointer | |
926 } | |
927 | |
928 Type tn = next.toBasetype(); | |
95 | 929 Type tns = tn; |
930 ulong sz = tn.size(); | |
0 | 931 |
95 | 932 version(SARRAYVALUE) |
933 { | |
934 if (tn.ty == Tsarray) | |
935 { | |
936 do | |
937 { | |
938 tns = tns.nextOf().toBasetype(); | |
939 } while (tns.ty == Tsarray); | |
940 if (tns.ty != Tstruct) | |
941 { | |
942 if (global.params.isLinux && linkage != LINKd) | |
943 {} | |
944 else | |
945 { | |
946 switch (sz) | |
947 { case 1: | |
948 case 2: | |
949 case 4: | |
950 case 8: | |
96 | 951 return RET.RETregs; // return small structs in regs |
952 // (not 3 byte structs!) | |
95 | 953 default: |
954 break; | |
955 } | |
956 } | |
96 | 957 return RET.RETstack; |
95 | 958 } |
959 } | |
960 } | |
961 if (tns.ty == TY.Tstruct) | |
0 | 962 { |
963 StructDeclaration sd = (cast(TypeStruct)tn).sym; | |
964 if (global.params.isLinux && linkage != LINK.LINKd) { | |
965 ; | |
966 } | |
95 | 967 ///version (DMDV2) { // TODO: |
968 else if (sd.dtor || sd.cpctor) | |
969 { | |
0 | 970 } |
971 ///} | |
972 else | |
973 { | |
95 | 974 switch (sz) |
0 | 975 { |
976 case 1: | |
977 case 2: | |
978 case 4: | |
979 case 8: | |
980 return RET.RETregs; // return small structs in regs | |
981 // (not 3 byte structs!) | |
982 default: | |
983 break; | |
984 } | |
985 } | |
986 return RET.RETstack; | |
987 } | |
988 else if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) && | |
989 linkage == LINK.LINKc && | |
990 tn.iscomplex()) | |
991 { | |
992 if (tn.ty == TY.Tcomplex32) | |
993 return RET.RETregs; // in EDX:EAX, not ST1:ST0 | |
994 else | |
995 return RET.RETstack; | |
996 } | |
997 else | |
998 return RET.RETregs; | |
999 } | |
1000 | |
72 | 1001 override TYM totym() |
0 | 1002 { |
1003 TYM tyf; | |
1004 | |
1005 //printf("TypeFunction.totym(), linkage = %d\n", linkage); | |
1006 switch (linkage) | |
1007 { | |
1008 case LINK.LINKwindows: | |
1009 tyf = (varargs == 1) ? TYM.TYnfunc : TYM.TYnsfunc; | |
1010 break; | |
1011 | |
1012 case LINK.LINKpascal: | |
1013 tyf = (varargs == 1) ? TYM.TYnfunc : TYM.TYnpfunc; | |
1014 break; | |
1015 | |
1016 case LINK.LINKc: | |
1017 tyf = TYM.TYnfunc; | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
1018 version (POSIX) {///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS |
0 | 1019 if (retStyle() == RET.RETstack) |
1020 tyf = TYM.TYhfunc; | |
1021 } | |
1022 break; | |
1023 | |
1024 case LINK.LINKd: | |
1025 tyf = (varargs == 1) ? TYM.TYnfunc : TYM.TYjfunc; | |
1026 break; | |
1027 | |
1028 case LINK.LINKcpp: | |
1029 tyf = TYM.TYnfunc; | |
1030 break; | |
1031 | |
1032 default: | |
1033 writef("linkage = %d\n", linkage); | |
1034 assert(0); | |
1035 } | |
1036 version (DMDV2) { | |
1037 if (isnothrow) | |
1038 tyf |= mTY.mTYnothrow; | |
1039 } | |
1040 return tyf; | |
1041 } | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
1042 } |