dealloc_freelist.ll.bak raw

   1  ; Scope-based memory management runtime.
   2  ; alloc uses calloc with 16-byte magic header.
   3  ; free checks magic before freeing.
   4  ; Scope tracking via linked list with save points.
   5  ; sliceGrow does NOT free old buffers - scope system handles lifetime.
   6  
   7  target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
   8  target triple = "x86_64-unknown-linux-musleabihf"
   9  
  10  @runtime.zeroSizedAlloc = external hidden global i8
  11  
  12  declare ptr @calloc(i64, i64)
  13  declare void @free(ptr)
  14  declare ptr @realloc(ptr, i64)
  15  
  16  declare hidden void @runtime.runtimePanic(ptr, i64, i64, ptr)
  17  @.str.oom = hidden constant [13 x i8] c"out of memory"
  18  
  19  define hidden noalias nonnull ptr @runtime.alloc(i64 %size, ptr %layout, ptr %context) #0 {
  20  entry:
  21    %isz = icmp eq i64 %size, 0
  22    br i1 %isz, label %zero, label %nonzero
  23  zero:
  24    ret ptr @runtime.zeroSizedAlloc
  25  nonzero:
  26    %aligned = add i64 %size, 15
  27    %size16 = and i64 %aligned, -16
  28    %total = add i64 %size16, 16
  29    %base = call ptr @calloc(i64 1, i64 %total)
  30    %ok = icmp ne ptr %base, null
  31    br i1 %ok, label %done, label %oom
  32  oom:
  33    call void @runtime.runtimePanic(ptr @.str.oom, i64 13, i64 13, ptr undef)
  34    unreachable
  35  done:
  36    store i64 -6872988504188559820, ptr %base, align 8
  37    %user = getelementptr i8, ptr %base, i64 16
  38    ret ptr %user
  39  }
  40  
  41  define hidden void @runtime.free(ptr %ptr, ptr %context) {
  42  entry:
  43    %isnil = icmp eq ptr %ptr, null
  44    br i1 %isnil, label %done, label %check
  45  check:
  46    %base = getelementptr i8, ptr %ptr, i64 -16
  47    %magic = load i64, ptr %base, align 8
  48    %is_ours = icmp eq i64 %magic, -6872988504188559820
  49    br i1 %is_ours, label %dofree, label %done
  50  dofree:
  51    store i64 0, ptr %base, align 8
  52    call void @free(ptr %base)
  53    br label %done
  54  done:
  55    ret void
  56  }
  57  
  58  define hidden ptr @runtime.realloc(ptr %ptr, i64 %size) {
  59  entry:
  60    %base = getelementptr i8, ptr %ptr, i64 -16
  61    %aligned = add i64 %size, 15
  62    %size16 = and i64 %aligned, -16
  63    %total = add i64 %size16, 16
  64    %p = call ptr @realloc(ptr %base, i64 %total)
  65    %user = getelementptr i8, ptr %p, i64 16
  66    ret ptr %user
  67  }
  68  
  69  define hidden void @runtime.hashmapDestroy(ptr %m, ptr %context) {
  70  entry:
  71    %isnil = icmp eq ptr %m, null
  72    br i1 %isnil, label %done, label %destroy
  73  destroy:
  74    %bucketsPtr = load ptr, ptr %m, align 8
  75    %hasBuckets = icmp ne ptr %bucketsPtr, null
  76    br i1 %hasBuckets, label %freeBuckets, label %freeMap
  77  freeBuckets:
  78    %keySizePtr = getelementptr i8, ptr %m, i64 24
  79    %keySize = load i64, ptr %keySizePtr, align 8
  80    %valSizePtr = getelementptr i8, ptr %m, i64 32
  81    %valSize = load i64, ptr %valSizePtr, align 8
  82    %ks8 = mul i64 %keySize, 8
  83    %vs8 = mul i64 %valSize, 8
  84    %bs1 = add i64 16, %ks8
  85    %bucketSize = add i64 %bs1, %vs8
  86    %bitsPtr = getelementptr i8, ptr %m, i64 40
  87    %bits8 = load i8, ptr %bitsPtr, align 1
  88    %bits = zext i8 %bits8 to i64
  89    %numBuckets = shl i64 1, %bits
  90    br label %bucketLoop
  91  bucketLoop:
  92    %i = phi i64 [ 0, %freeBuckets ], [ %inext, %bucketDone ]
  93    %idone = icmp uge i64 %i, %numBuckets
  94    br i1 %idone, label %freeBucketArray, label %processBucket
  95  processBucket:
  96    %off = mul i64 %bucketSize, %i
  97    %bucket = getelementptr i8, ptr %bucketsPtr, i64 %off
  98    %overflowPtr = getelementptr i8, ptr %bucket, i64 8
  99    %overflow = load ptr, ptr %overflowPtr, align 8
 100    br label %overflowLoop
 101  overflowLoop:
 102    %ov = phi ptr [ %overflow, %processBucket ], [ %ovNext, %freeOverflow ]
 103    %ovDone = icmp eq ptr %ov, null
 104    br i1 %ovDone, label %bucketDone, label %freeOverflow
 105  freeOverflow:
 106    %ovNextPtr = getelementptr i8, ptr %ov, i64 8
 107    %ovNext = load ptr, ptr %ovNextPtr, align 8
 108    call void @runtime.free(ptr %ov, ptr undef)
 109    br label %overflowLoop
 110  bucketDone:
 111    %inext = add i64 %i, 1
 112    br label %bucketLoop
 113  freeBucketArray:
 114    call void @runtime.free(ptr %bucketsPtr, ptr undef)
 115    br label %freeMap
 116  freeMap:
 117    call void @runtime.free(ptr %m, ptr undef)
 118    br label %done
 119  done:
 120    ret void
 121  }
 122  
 123  declare hidden void @runtime.memmove(ptr, ptr, i64, ptr)
 124  declare hidden void @runtime.negativeShiftPanic(ptr)
 125  declare hidden i32 @"math/bits.Len"(i32, ptr)
 126  declare hidden ptr @"(internal/gclayout.Layout).AsPtr"(i64, ptr)
 127  
 128  define hidden { ptr, i64, i64 } @runtime.sliceGrow(ptr %oldBuf, i64 %oldLen, i64 %oldCap, i64 %newCap, i64 %elemSize, ptr %context) #1 {
 129  entry:
 130    %fits = icmp uge i64 %oldCap, %newCap
 131    br i1 %fits, label %no_grow, label %grow
 132  no_grow:
 133    %r0 = insertvalue { ptr, i64, i64 } zeroinitializer, ptr %oldBuf, 0
 134    %r1 = insertvalue { ptr, i64, i64 } %r0, i64 %oldLen, 1
 135    %r2 = insertvalue { ptr, i64, i64 } %r1, i64 %oldCap, 2
 136    ret { ptr, i64, i64 } %r2
 137  grow:
 138    %tr = trunc i64 %newCap to i32
 139    %bits = call i32 @"math/bits.Len"(i32 %tr, ptr undef)
 140    %neg = icmp slt i32 %bits, 0
 141    br i1 %neg, label %shift_throw, label %shift_ok
 142  shift_ok:
 143    %overflow = icmp uge i32 %bits, 64
 144    %ext = zext i32 %bits to i64
 145    %shifted = shl i64 1, %ext
 146    %roundCap = select i1 %overflow, i64 0, i64 %shifted
 147    %small = icmp ult i64 %elemSize, 8
 148    br i1 %small, label %set_layout, label %do_alloc
 149  set_layout:
 150    %lay = call ptr @"(internal/gclayout.Layout).AsPtr"(i64 3, ptr undef)
 151    br label %do_alloc
 152  do_alloc:
 153    %layout = phi ptr [ null, %shift_ok ], [ %lay, %set_layout ]
 154    %totalSz = mul i64 %roundCap, %elemSize
 155    %buf = call ptr @runtime.alloc(i64 %totalSz, ptr %layout, ptr undef)
 156    %hasData = icmp ugt i64 %oldLen, 0
 157    br i1 %hasData, label %copy, label %ret
 158  copy:
 159    %copySz = mul i64 %oldLen, %elemSize
 160    call void @runtime.memmove(ptr %buf, ptr %oldBuf, i64 %copySz, ptr undef)
 161    br label %ret
 162  ret:
 163    %s0 = insertvalue { ptr, i64, i64 } zeroinitializer, ptr %buf, 0
 164    %s1 = insertvalue { ptr, i64, i64 } %s0, i64 %oldLen, 1
 165    %s2 = insertvalue { ptr, i64, i64 } %s1, i64 %roundCap, 2
 166    ret { ptr, i64, i64 } %s2
 167  shift_throw:
 168    call void @runtime.negativeShiftPanic(ptr undef)
 169    unreachable
 170  }
 171  
 172  define void @runtime._panic(ptr %msg) {
 173    call void @runtime.runtimePanic(ptr %msg, i64 0, i64 0, ptr null)
 174    unreachable
 175  }
 176  
 177  define void @runtime._panicstr({ ptr, i64, i64 } %s) {
 178    %p = extractvalue { ptr, i64, i64 } %s, 0
 179    %l = extractvalue { ptr, i64, i64 } %s, 1
 180    %c = extractvalue { ptr, i64, i64 } %s, 2
 181    call void @runtime.runtimePanic(ptr %p, i64 %l, i64 %c, ptr null)
 182    unreachable
 183  }
 184  
 185  define void @syscall.runtime_entersyscall() { ret void }
 186  define void @syscall.runtime_exitsyscall() { ret void }
 187  
 188  @environ = external global ptr
 189  declare i64 @strlen(ptr)
 190  declare i32 @setenv(ptr, ptr, i32)
 191  
 192  define hidden { ptr, i64, i64 } @syscall.runtime_envs(ptr %context) {
 193  entry:
 194    %ep = load ptr, ptr @environ, align 8
 195    %isnil = icmp eq ptr %ep, null
 196    br i1 %isnil, label %empty, label %count
 197  count:
 198    br label %loop
 199  loop:
 200    %p = phi ptr [ %ep, %count ], [ %nextp, %next ]
 201    %n = phi i64 [ 0, %count ], [ %n1, %next ]
 202    %cur = load ptr, ptr %p, align 8
 203    %done = icmp eq ptr %cur, null
 204    br i1 %done, label %build, label %next
 205  next:
 206    %n1 = add i64 %n, 1
 207    %nextp = getelementptr ptr, ptr %p, i64 1
 208    br label %loop
 209  build:
 210    %sz = mul i64 %n, 24
 211    %buf = call ptr @runtime.alloc(i64 %sz, ptr null, ptr null)
 212    br label %fill
 213  fill:
 214    %i = phi i64 [ 0, %build ], [ %i1, %fillnext ]
 215    %idone = icmp uge i64 %i, %n
 216    br i1 %idone, label %retlbl, label %fillbody
 217  fillbody:
 218    %envp = getelementptr ptr, ptr %ep, i64 %i
 219    %str = load ptr, ptr %envp, align 8
 220    %slen = call i64 @strlen(ptr %str)
 221    %slot = getelementptr { ptr, i64, i64 }, ptr %buf, i64 %i
 222    store ptr %str, ptr %slot, align 8
 223    %lenp = getelementptr i8, ptr %slot, i64 8
 224    store i64 %slen, ptr %lenp, align 8
 225    %capp = getelementptr i8, ptr %slot, i64 16
 226    store i64 %slen, ptr %capp, align 8
 227    br label %fillnext
 228  fillnext:
 229    %i1 = add i64 %i, 1
 230    br label %fill
 231  retlbl:
 232    %r0 = insertvalue { ptr, i64, i64 } zeroinitializer, ptr %buf, 0
 233    %r1 = insertvalue { ptr, i64, i64 } %r0, i64 %n, 1
 234    %r2 = insertvalue { ptr, i64, i64 } %r1, i64 %n, 2
 235    ret { ptr, i64, i64 } %r2
 236  empty:
 237    ret { ptr, i64, i64 } zeroinitializer
 238  }
 239  
 240  define void @syscall.runtimeSetenv({ ptr, i64, i64 } %k, { ptr, i64, i64 } %v, ptr %context) {
 241    %kptr = extractvalue { ptr, i64, i64 } %k, 0
 242    %vptr = extractvalue { ptr, i64, i64 } %v, 0
 243    %1 = call i32 @setenv(ptr %kptr, ptr %vptr, i32 1)
 244    ret void
 245  }
 246  
 247  define { i64, i64, i64 } @"internal/runtime/syscall.Syscall6"(i64 %num, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6) {
 248    %1 = call { i64, i64 } asm sideeffect "syscall", "={rax},={rdx},{rax},{rdi},{rsi},{rdx},{r10},{r8},{r9},~{rcx},~{r11},~{memory}"(i64 %num, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6)
 249    %r1 = extractvalue { i64, i64 } %1, 0
 250    %r2 = extractvalue { i64, i64 } %1, 1
 251    %ret1 = insertvalue { i64, i64, i64 } undef, i64 %r1, 0
 252    %ret2 = insertvalue { i64, i64, i64 } %ret1, i64 %r2, 1
 253    %ret3 = insertvalue { i64, i64, i64 } %ret2, i64 0, 2
 254    ret { i64, i64, i64 } %ret3
 255  }
 256  
 257  ; scopePush: push allocation onto scope list.
 258  ; Node layout: {ptr payload, ptr next} (16 bytes)
 259  define hidden void @runtime.scopePush(ptr %payload, ptr %headSlot) {
 260  entry:
 261    %isnil = icmp eq ptr %payload, null
 262    br i1 %isnil, label %done, label %push
 263  push:
 264    %node = call ptr @calloc(i64 1, i64 16)
 265    %ok = icmp ne ptr %node, null
 266    br i1 %ok, label %fill, label %done
 267  fill:
 268    store ptr %payload, ptr %node, align 8
 269    %nextSlot = getelementptr i8, ptr %node, i64 8
 270    %oldHead = load ptr, ptr %headSlot, align 8
 271    store ptr %oldHead, ptr %nextSlot, align 8
 272    store ptr %node, ptr %headSlot, align 8
 273    br label %done
 274  done:
 275    ret void
 276  }
 277  
 278  ; scopeFreeTo: walk from head, free each payload+node, stop at sentinel.
 279  define hidden ptr @runtime.scopeFreeTo(ptr %head, ptr %sentinel) {
 280  entry:
 281    br label %loop
 282  loop:
 283    %cur = phi ptr [ %head, %entry ], [ %next, %freeself ]
 284    %atEnd = icmp eq ptr %cur, %sentinel
 285    br i1 %atEnd, label %ret, label %checknull
 286  checknull:
 287    %isnull = icmp eq ptr %cur, null
 288    br i1 %isnull, label %ret, label %freenode
 289  freenode:
 290    %payload = load ptr, ptr %cur, align 8
 291    %nextSlot = getelementptr i8, ptr %cur, i64 8
 292    %next0 = load ptr, ptr %nextSlot, align 8
 293    %paynil = icmp eq ptr %payload, null
 294    br i1 %paynil, label %freeself, label %freepay
 295  freepay:
 296    call void @runtime.free(ptr %payload, ptr undef)
 297    br label %freeself
 298  freeself:
 299    %next = phi ptr [ %next0, %freenode ], [ %next0, %freepay ]
 300    call void @free(ptr %cur)
 301    br label %loop
 302  ret:
 303    ret ptr %sentinel
 304  }
 305  
 306  ; scopeRelocate: move allocation from inner scope to outer scope.
 307  define hidden void @runtime.scopeRelocate(ptr %payload, ptr %headSlot, ptr %saveSlot) {
 308  entry:
 309    %isnil = icmp eq ptr %payload, null
 310    br i1 %isnil, label %done, label %start
 311  start:
 312    %saved = load ptr, ptr %saveSlot, align 8
 313    %head = load ptr, ptr %headSlot, align 8
 314    %headIsSave = icmp eq ptr %head, %saved
 315    br i1 %headIsSave, label %done, label %headnullchk
 316  headnullchk:
 317    %headNull = icmp eq ptr %head, null
 318    br i1 %headNull, label %done, label %checkhead
 319  checkhead:
 320    %headPay = load ptr, ptr %head, align 8
 321    %headMatch = icmp eq ptr %headPay, %payload
 322    br i1 %headMatch, label %unlinkhead, label %search
 323  unlinkhead:
 324    %headNext = getelementptr i8, ptr %head, i64 8
 325    %hn = load ptr, ptr %headNext, align 8
 326    store ptr %hn, ptr %headSlot, align 8
 327    %savIsNull = icmp eq ptr %saved, null
 328    br i1 %savIsNull, label %insertnull, label %insertafter
 329  insertnull:
 330    store ptr null, ptr %headNext, align 8
 331    store ptr %head, ptr %saveSlot, align 8
 332    br label %done
 333  insertafter:
 334    %savNext = getelementptr i8, ptr %saved, i64 8
 335    %sn = load ptr, ptr %savNext, align 8
 336    store ptr %sn, ptr %headNext, align 8
 337    store ptr %head, ptr %savNext, align 8
 338    br label %done
 339  search:
 340    br label %sloop
 341  sloop:
 342    %prev = phi ptr [ %head, %search ], [ %scur, %snext ]
 343    %prevNextSlot = getelementptr i8, ptr %prev, i64 8
 344    %scur = load ptr, ptr %prevNextSlot, align 8
 345    %curDone = icmp eq ptr %scur, %saved
 346    br i1 %curDone, label %done, label %schecknull
 347  schecknull:
 348    %curNull = icmp eq ptr %scur, null
 349    br i1 %curNull, label %done, label %smatch
 350  smatch:
 351    %curPay = load ptr, ptr %scur, align 8
 352    %curMatch = icmp eq ptr %curPay, %payload
 353    br i1 %curMatch, label %unlinkmid, label %snext
 354  snext:
 355    br label %sloop
 356  unlinkmid:
 357    %curNextSlot = getelementptr i8, ptr %scur, i64 8
 358    %cn = load ptr, ptr %curNextSlot, align 8
 359    store ptr %cn, ptr %prevNextSlot, align 8
 360    %savIsNull2 = icmp eq ptr %saved, null
 361    br i1 %savIsNull2, label %insertnull2, label %insertafter2
 362  insertnull2:
 363    store ptr null, ptr %curNextSlot, align 8
 364    store ptr %scur, ptr %saveSlot, align 8
 365    br label %done
 366  insertafter2:
 367    %savNext2 = getelementptr i8, ptr %saved, i64 8
 368    %sn2 = load ptr, ptr %savNext2, align 8
 369    store ptr %sn2, ptr %curNextSlot, align 8
 370    store ptr %scur, ptr %savNext2, align 8
 371    br label %done
 372  done:
 373    ret void
 374  }
 375  
 376  ; scopeEscapeReturn: null out payload so scopeFreeTo won't free it.
 377  define hidden void @runtime.scopeEscapeReturn(ptr %payload, ptr %headSlot) {
 378  entry:
 379    %isnil = icmp eq ptr %payload, null
 380    br i1 %isnil, label %done, label %start
 381  start:
 382    %head = load ptr, ptr %headSlot, align 8
 383    br label %loop
 384  loop:
 385    %cur = phi ptr [ %head, %start ], [ %next, %nomatch ]
 386    %curnil = icmp eq ptr %cur, null
 387    br i1 %curnil, label %done, label %check
 388  check:
 389    %curPay = load ptr, ptr %cur, align 8
 390    %match = icmp eq ptr %curPay, %payload
 391    br i1 %match, label %nullify, label %nomatch
 392  nullify:
 393    store ptr null, ptr %cur, align 8
 394    br label %done
 395  nomatch:
 396    %nextSlot = getelementptr i8, ptr %cur, i64 8
 397    %next = load ptr, ptr %nextSlot, align 8
 398    br label %loop
 399  done:
 400    ret void
 401  }
 402  
 403  attributes #0 = { noinline nounwind allockind("alloc,zeroed") allocsize(0) uwtable(sync) "alloc-family"="runtime.alloc" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" }
 404  attributes #1 = { noinline nounwind uwtable(sync) "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" }
 405