summary refs log blame commit diff stats
path: root/tests/run/tvarargs_vs_generic.nim
blob: 122f3e45325e2104ca78feb4d8d54875b6ae1221 (plain) (tree)
1
2
           
                                    























                                             
discard """
  output: "direct\ngeneric\ngeneric"
"""

proc withDirectType(args: string) =
  echo "direct"

proc withDirectType[T](arg: T) =
  echo "generic"

proc withOpenArray(args: openarray[string]) =
  echo "openarray"

proc withOpenArray[T](arg: T) =
  echo "generic"

proc withVarargs(args: varargs[string]) =
  echo "varargs"

proc withVarargs[T](arg: T) =
  echo "generic"

withDirectType "string"
withOpenArray "string"
withVarargs "string"
09c01e45'>^
745f1642d ^





745f1642d ^
062d7e3a3 ^
745f1642d ^

745f1642d ^





745f1642d ^


745f1642d ^


745f1642d ^



745f1642d ^
8232bd04f ^
745f1642d ^
745f1642d ^
745f1642d ^
745f1642d ^

745f1642d ^
8232bd04f ^
745f1642d ^

745f1642d ^


8232bd04f ^
745f1642d ^


745f1642d ^




745f1642d ^
1e08fff2d ^

1e08fff2d ^




8232bd04f ^
1ec5c6fdf ^
8232bd04f ^
745f1642d ^



745f1642d ^
8232bd04f ^
745f1642d ^

8232bd04f ^
745f1642d ^
745f1642d ^

745f1642d ^



745f1642d ^


1d9b88f25 ^


745f1642d ^
8232bd04f ^
745f1642d ^





745f1642d ^
abad758a7 ^
062d7e3a3 ^

abad758a7 ^



062d7e3a3 ^
abad758a7 ^


745f1642d ^


1d9b88f25 ^








































745f1642d ^


1711a60f7 ^
8232bd04f ^
745f1642d ^





















8232bd04f ^
745f1642d ^

















350396e1c ^
745f1642d ^








8232bd04f ^
745f1642d ^


745f1642d ^
350396e1c ^
8232bd04f ^
745f1642d ^
8232bd04f ^
745f1642d ^




8232bd04f ^
745f1642d ^

8232bd04f ^
745f1642d ^




8232bd04f ^
745f1642d ^


8232bd04f ^
745f1642d ^



8232bd04f ^
745f1642d ^









745f1642d ^

8232bd04f ^
745f1642d ^











8232bd04f ^
745f1642d ^


745f1642d ^



745f1642d ^


745f1642d ^


ea5fc9f20 ^


745f1642d ^
745f1642d ^

8232bd04f ^
745f1642d ^
745f1642d ^
8232bd04f ^
745f1642d ^
745f1642d ^

5dfcc4e91 ^
















745f1642d ^



745f1642d ^
8232bd04f ^
745f1642d ^
745f1642d ^
1d9b88f25 ^







745f1642d ^


745f1642d ^



745f1642d ^
8232bd04f ^


745f1642d ^

745f1642d ^

745f1642d ^




8232bd04f ^
745f1642d ^





c3067e36b ^
745f1642d ^































8232bd04f ^
745f1642d ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450








                                                   






                                                                      
                     
                          
                        
 
                                                  






                                                                   









                                                              

               



                                                        
                                 


                                     


              

                                                                                                    

                                                                                                        
                 

                                                       
                                     




                  



                                                                                                  





                                                                                    
                                       
                                            

                                           





                                                                                   


                                      


                                                                              



                                                                                                        
                                                  
                                    
               
                                                       
                              

                                                                                     
                                          
                                          

                                         


                                                                  
                                    


                                               




                                                 
           

                             




                                                         
                        
                                                               
                                  



                                                    
       
                                

                                 
                                                                                                                            
                                                                                                        

               



                                                                                                  


                                                                                                          


                        
                                                  
                           





                                                                                 
           
                            

                                       



                                                               
                            


                                             


                          








































                                                                                                                      


                                                                
                   
                                            





















                                                                           
                               

















                                             
                                        








                                                                     
                                   


                                    
                                          
                                                                   
                                        
         
                                    




                                       
                         

                                 
                                                        




                                   
                            


                               
                                                  



                                                          
                    









                                                 

                                          
                                 











                                                                   
                                         


                                             



                                       


                 


                                          


                               
              

                                                            
                                         
                               
              
                              
                          

                           
















                                                                      



                                             
         
                    
                     
                         







                                                                                      


                                                                                               



                                    
                                   


                                                                    

                               

                                                                          




                                                
                                         





                                         
                                                                        































                                                              
                               
                                
#
#
#           The Nim Compiler
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#
## code owner: Arne Döring
## e-mail: arne.doering@gmx.net

proc align(address, alignment: BiggestInt): BiggestInt =
  result = (address + (alignment - 1)) and not (alignment - 1)

const
  ## a size is concidered "unknown" when it is an imported type from C
  ## or C++.
  szUnknownSize* = -3
  szIllegalRecursion* = -2
  szUncomputedSize* = -1

proc computeSizeAlign(conf: ConfigRef; typ: PType)

proc computeSubObjectAlign(conf: ConfigRef; n: PNode): BiggestInt =
  ## returns object alignment
  case n.kind
  of nkRecCase:
    assert(n.sons[0].kind == nkSym)
    result = computeSubObjectAlign(conf, n.sons[0])
    for i in 1 ..< sonsLen(n):
      let child = n.sons[i]
      case child.kind
      of nkOfBranch, nkElse:
        let align = computeSubObjectAlign(conf, child.lastSon)
        if align < 0:
          return align
        result = max(result, align)
      else:
        internalError(conf, "computeSubObjectAlign")
  of nkRecList:
    result = 1
    for i, child in n.sons:
      let align = computeSubObjectAlign(conf, n.sons[i])
      if align < 0:
        return align
      result = max(result, align)
  of nkSym:
    computeSizeAlign(conf, n.sym.typ)
    result = n.sym.typ.align
  else:
    result = 1

proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode,
                                      initialOffset: BiggestInt): tuple[offset, align: BiggestInt] =
  ## ``offset`` is the offset within the object, after the node has been written, no padding bytes added
  ## ``align`` maximum alignment from all sub nodes
  assert n != nil
  if n.typ != nil and n.typ.size == szIllegalRecursion:
    result.offset = szIllegalRecursion
    result.align = szIllegalRecursion
    return

  result.align = 1
  case n.kind
  of nkRecCase:
    assert(n.sons[0].kind == nkSym)
    let (kindOffset, kindAlign) = computeObjectOffsetsFoldFunction(conf, n.sons[0], initialOffset)

    var maxChildAlign: BiggestInt = 0
    for i in 1 ..< sonsLen(n):
      let child = n.sons[i]
      case child.kind
      of nkOfBranch, nkElse:
        # offset parameter cannot be known yet, it needs to know the alignment first
        let align = computeSubObjectAlign(conf, n.sons[i].lastSon)
        if align == szIllegalRecursion:
          result.offset = szIllegalRecursion
          result.align = szIllegalRecursion
          return
        if align == szUnknownSize or maxChildAlign == szUnknownSize:
          maxChildAlign = szUnknownSize
        else:
          maxChildAlign = max(maxChildAlign, align)
      else:
        internalError(conf, "computeObjectOffsetsFoldFunction(record case branch)")
    if maxChildAlign == szUnknownSize:
      result.align  = szUnknownSize
      result.offset = szUnknownSize
    else:
      # the union neds to be aligned first, before the offsets can be assigned
      let kindUnionOffset = align(kindOffset, maxChildAlign)
      var maxChildOffset: BiggestInt = 0
      for i in 1 ..< sonsLen(n):
        let (offset, align) = computeObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, kindUnionOffset)
        maxChildOffset = max(maxChildOffset, offset)
      result.align = max(kindAlign, maxChildAlign)
      result.offset = maxChildOffset
  of nkRecList:
    result.align = 1 # maximum of all member alignments
    var offset = initialOffset
    for i, child in n.sons:
      let (new_offset, align) = computeObjectOffsetsFoldFunction(conf, child, offset)
      if new_offset == szIllegalRecursion:
        result.offset = szIllegalRecursion
        result.align = szIllegalRecursion
        return
      elif new_offset == szUnknownSize or offset == szUnknownSize:
        # if anything is unknown, the rest becomes unknown as well
        offset = szUnknownSize
        result.align = szUnknownSize
      else:
        offset = new_offset
        result.align = max(result.align, align)
    # final alignment
    if offset == szUnknownSize:
      result.offset = szUnknownSize
    else:
      result.offset = align(offset, result.align)
  of nkSym:
    var size = szUnknownSize
    var align = szUnknownSize
    if n.sym.bitsize == 0: # 0 represents bitsize not set
      computeSizeAlign(conf, n.sym.typ)
      size = n.sym.typ.size.int
      align = n.sym.typ.align.int

    result.align = align
    if initialOffset == szUnknownSize or size == szUnknownSize:
      n.sym.offset = szUnknownSize
      result.offset = szUnknownSize
    else:
      n.sym.offset = align(initialOffset, align).int
      result.offset = n.sym.offset + n.sym.typ.size
  else:
    result.align = szUnknownSize
    result.offset = szUnknownSize

proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset: BiggestInt, debug: bool): BiggestInt =
  ## ``result`` is the offset within the object, after the node has been written, no padding bytes added
  case n.kind
  of nkRecCase:
    assert(n.sons[0].kind == nkSym)
    let kindOffset = computePackedObjectOffsetsFoldFunction(conf, n.sons[0], initialOffset, debug)
    # the union neds to be aligned first, before the offsets can be assigned
    let kindUnionOffset = kindOffset
    var maxChildOffset: BiggestInt = kindUnionOffset
    for i in 1 ..< sonsLen(n):
      let offset = computePackedObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, kindUnionOffset, debug)
      if offset < 0:
         result = offset
         break
      maxChildOffset = max(maxChildOffset, offset)
    result = maxChildOffset
  of nkRecList:
    result = initialOffset
    for i, child in n.sons:
      result = computePackedObjectOffsetsFoldFunction(conf, child, result, debug)
      if result == szIllegalRecursion:
        break
  of nkSym:
    var size = szUnknownSize
    if n.sym.bitsize == 0:
      computeSizeAlign(conf, n.sym.typ)
      size = n.sym.typ.size.int

    if initialOffset == szUnknownSize or size == szUnknownSize:
      n.sym.offset = szUnknownSize
      result = szUnknownSize
    else:
      n.sym.offset = int(initialOffset)
      result = initialOffset + n.sym.typ.size
  else:
    result = szUnknownSize

proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, debug: bool): tuple[offset, align: BiggestInt] =
  ## ``result`` is the offset from the larget member of the union.
  case n.kind
  of nkRecCase:
    result.offset = szUnknownSize
    result.align = szUnknownSize
    localError(conf, n.info, "Illegal use of ``case`` in union type.")
    #internalError(conf, "Illegal use of ``case`` in union type.")
  of nkRecList:
    var maxChildOffset: BiggestInt = 0
    for i, child in n.sons:
      let (offset, align) = computeUnionObjectOffsetsFoldFunction(conf, child, debug)
      if offset == szIllegalRecursion or align == szIllegalRecursion:
        result.offset = szIllegalRecursion
        result.align = szIllegalRecursion
      elif offset == szUnknownSize or align == szUnknownSize:
        result.offset = szUnknownSize
        result.align = szUnknownSize
      else:
        assert offset != szUncomputedSize
        assert align != szUncomputedSize
        result.offset = max(result.offset, offset)
        result.align = max(result.align, align)
  of nkSym:
    var size = szUnknownSize
    var align = szUnknownSize
    if n.sym.bitsize == 0: # 0 represents bitsize not set
      computeSizeAlign(conf, n.sym.typ)
      size = n.sym.typ.size.int
      align = n.sym.typ.align.int

    result.align = align
    if size == szUnknownSize:
      n.sym.offset = szUnknownSize
      result.offset = szUnknownSize
    else:
      n.sym.offset = 0
      result.offset = n.sym.typ.size
  else:
    result.offset = szUnknownSize
    result.align = szUnknownSize

proc computeSizeAlign(conf: ConfigRef; typ: PType) =
  ## computes and sets ``size`` and ``align`` members of ``typ``
  assert typ != nil
  let hasSize = typ.size != szUncomputedSize
  let hasAlign = typ.align != szUncomputedSize

  if hasSize and hasAlign:
    # nothing to do, size and align already computed
    return

  # This function can only calculate both, size and align at the same time.
  # If one of them is already set this value is stored here and reapplied
  let revertSize = typ.size
  let revertAlign = typ.align
  defer:
    if hasSize:
      typ.size = revertSize
    if hasAlign:
      typ.align = revertAlign

  if typ.size == szIllegalRecursion or typ.align == szIllegalRecursion:
    # we are already computing the size of the type
    # --> illegal recursion in type
    return

  # mark computation in progress
  typ.size = szIllegalRecursion
  typ.align = szIllegalRecursion

  var maxAlign, sizeAccum, length: BiggestInt

  var tk = typ.kind
  case tk
  of tyProc:
    if typ.callConv == ccClosure:
      typ.size = 2 * conf.target.ptrSize
    else:
      typ.size = conf.target.ptrSize
    typ.align = int16(conf.target.ptrSize)

  of tyNil:
    typ.size = conf.target.ptrSize
    typ.align = int16(conf.target.ptrSize)

  of tyString:
    if conf.selectedGC == gcDestructors:
      typ.size = conf.target.ptrSize * 2
    else:
      typ.size = conf.target.ptrSize
    typ.align = int16(conf.target.ptrSize)

  of tyCString, tySequence, tyPtr, tyRef, tyVar, tyLent, tyOpenArray:
    let base = typ.lastSon
    if base == typ:
      # this is not the correct location to detect ``type A = ptr A``
      typ.size = szIllegalRecursion
      typ.align = szIllegalRecursion
      return

    typ.align = int16(conf.target.ptrSize)
    if typ.kind == tySequence and conf.selectedGC == gcDestructors:
      typ.size = conf.target.ptrSize * 2
    else:
      typ.size = conf.target.ptrSize

  of tyArray:
    computeSizeAlign(conf, typ.sons[1])
    let elemSize = typ.sons[1].size
    if elemSize < 0:
      typ.size = elemSize
      typ.align = int16(elemSize)
    else:
      typ.size = lengthOrd(conf, typ.sons[0]) * elemSize
      typ.align = typ.sons[1].align

  of tyUncheckedArray:
    let base = typ.lastSon
    computeSizeAlign(conf, base)
    typ.size = szUnknownSize
    typ.align = base.align
  of tyEnum:
    if firstOrd(conf, typ) < 0:
      typ.size = 4              # use signed int32
      typ.align = 4
    else:
      length = lastOrd(conf, typ)   # BUGFIX: use lastOrd!
      if length + 1 < `shl`(1, 8):
        typ.size = 1
        typ.align = 1
      elif length + 1 < `shl`(1, 16):
        typ.size = 2
        typ.align = 2
      elif length + 1 < `shl`(BiggestInt(1), 32):
        typ.size = 4
        typ.align = 4
      else:
        typ.size = 8
        typ.align = 8
  of tySet:
    if typ.sons[0].kind == tyGenericParam:
      typ.size = szUncomputedSize
      typ.align = szUncomputedSize # in original version this was 1
    else:
      length = lengthOrd(conf, typ.sons[0])
      if length <= 8:
        typ.size = 1
      elif length <= 16:
        typ.size = 2
      elif length <= 32:
        typ.size = 4
      elif length <= 64:
        typ.size = 8
      elif align(length, 8) mod 8 == 0:
        typ.size = align(length, 8) div 8
      else:
        typ.size = align(length, 8) div 8 + 1
    typ.align = int16(typ.size)
  of tyRange:
    computeSizeAlign(conf, typ.sons[0])
    typ.size = typ.sons[0].size
    typ.align = typ.sons[0].align
  of tyTuple:
    maxAlign = 1
    sizeAccum = 0
    for i in countup(0, sonsLen(typ) - 1):
      let child = typ.sons[i]
      computeSizeAlign(conf, child)
      if child.size < 0:
        typ.size = child.size
        typ.align = child.align
        return
      maxAlign = max(maxAlign, child.align)
      sizeAccum = align(sizeAccum, child.align) + child.size
    typ.size = align(sizeAccum, maxAlign)
    typ.align = int16(maxAlign)
  of tyObject:
    var headerSize: BiggestInt
    var headerAlign: int16
    if typ.sons[0] != nil:
      # compute header size
      if conf.cmd == cmdCompileToCpp:
        # if the target is C++ the members of this type are written
        # into the padding byets at the end of the parent type. At the
        # moment it is not supported to calculate that.
        headerSize = szUnknownSize
        headerAlign = szUncomputedSize
      else:
        var st = typ.sons[0]
        while st.kind in skipPtrs:
          st = st.sons[^1]
        computeSizeAlign(conf, st)
        if st.size == szIllegalRecursion:
          typ.size = st.size
          typ.align = st.align
          return
        headerSize = st.size
        headerAlign = st.align
    elif isObjectWithTypeFieldPredicate(typ):
      # this branch is taken for RootObj
      headerSize = conf.target.intSize
      headerAlign = conf.target.intSize.int16
    else:
      headerSize = 0
      headerAlign = 1
    let (offset, align) =
      if tfUnion in typ.flags:
        if tfPacked in typ.flags:
          let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo()
          localError(conf, info, "type may not be packed and union at the same time.")
          (BiggestInt(szUnknownSize), BiggestInt(szUnknownSize))
        else:
          computeUnionObjectOffsetsFoldFunction(conf, typ.n, false)
      elif tfPacked in typ.flags:
        (computePackedObjectOffsetsFoldFunction(conf, typ.n, headerSize, false), BiggestInt(1))
      else:
        computeObjectOffsetsFoldFunction(conf, typ.n, headerSize)
    if offset == szIllegalRecursion:
      typ.size = szIllegalRecursion
      typ.align = szIllegalRecursion
      return
    if offset == szUnknownSize or (
        typ.sym != nil and
        typ.sym.flags * {sfCompilerProc, sfImportc} == {sfImportc}):
      typ.size = szUnknownSize
      typ.align = szUnknownSize
      return
    # header size is already in size from computeObjectOffsetsFoldFunction
    # maxAlign is probably not changed at all from headerAlign
    if tfPacked in typ.flags:
      typ.size = offset
      typ.align = 1
    else:
      typ.align = int16(max(align, headerAlign))
      typ.size = align(offset, typ.align)
  of tyInferred:
    if typ.len > 1:
      computeSizeAlign(conf, typ.lastSon)
      typ.size = typ.lastSon.size
      typ.align = typ.lastSon.align

  of tyGenericInst, tyDistinct, tyGenericBody, tyAlias, tySink, tyOwned:
    computeSizeAlign(conf, typ.lastSon)
    typ.size = typ.lastSon.size
    typ.align = typ.lastSon.align

  of tyTypeClasses:
    if typ.isResolvedUserTypeClass:
      computeSizeAlign(conf, typ.lastSon)
      typ.size = typ.lastSon.size
      typ.align = typ.lastSon.align
    else:
      typ.size = szUncomputedSize
      typ.align = szUncomputedSize

  of tyTypeDesc:
    computeSizeAlign(conf, typ.base)
    typ.size = typ.base.size
    typ.align = typ.base.align

  of tyForward:
    # is this really illegal recursion, or maybe just unknown?
    typ.size = szIllegalRecursion
    typ.align = szIllegalRecursion

  of tyStatic:
    if typ.n != nil:
      computeSizeAlign(conf, typ.lastSon)
      typ.size = typ.lastSon.size
      typ.align = typ.lastSon.align
    else:
      typ.size = szUncomputedSize
      typ.align = szUncomputedSize
  else:
    typ.size = szUncomputedSize
    typ.align = szUncomputedSize