ir_map.mx raw

   1  package main
   2  
   3  import (
   4  	. "git.smesh.lol/moxie/pkg/types"
   5  )
   6  
   7  func (e *irEmitter) emitMakeMap(m *SSAMakeMap) {
   8  	reg := e.regName(m)
   9  	ipt := e.intptrType()
  10  	mt, _ := SafeUnderlying(m.SSAType()).(*TCMap)
  11  	keyType := "i32"
  12  	valType := "i32"
  13  	alg := "0"
  14  	if mt != nil {
  15  		keyType = e.llvmType(mt.Key)
  16  		valType = e.llvmType(mt.Elem)
  17  		if e.isStringLike(mt.Key) {
  18  			alg = "1"
  19  		}
  20  	}
  21  	keySz := e.nextReg2("mm")
  22  	e.w("  ") ; e.w(keySz) ; e.w(" = ptrtoint ptr getelementptr (")
  23  	e.w(keyType) ; e.w(", ptr null, i32 1) to ") ; e.w(ipt) ; e.w("\n")
  24  	valSz := e.nextReg2("mm")
  25  	e.w("  ") ; e.w(valSz) ; e.w(" = ptrtoint ptr getelementptr (")
  26  	e.w(valType) ; e.w(", ptr null, i32 1) to ") ; e.w(ipt) ; e.w("\n")
  27  	hint := "8"
  28  	if m.Reserve != nil {
  29  		hint = e.operand(m.Reserve)
  30  	}
  31  	e.w("  ") ; e.w(reg) ; e.w(" = call ptr @runtime.hashmapMake(")
  32  	e.w(ipt) ; e.w(" ") ; e.w(keySz) ; e.w(", ")
  33  	e.w(ipt) ; e.w(" ") ; e.w(valSz) ; e.w(", ")
  34  	e.w(ipt) ; e.w(" ") ; e.w(hint) ; e.w(", i8 ") ; e.w(alg) ; e.w(", ptr null)\n")
  35  	e.declareRuntime("runtime.hashmapMake", "ptr", ipt | ", " | ipt | ", " | ipt | ", i8")
  36  	e.scopeTrackAlloc(reg)
  37  }
  38  
  39  func (e *irEmitter) emitMapUpdate(m *SSAMapUpdate) {
  40  	ipt := e.intptrType()
  41  	mapVal := e.operand(m.Map)
  42  	keyVal := e.operand(m.Key)
  43  	valVal := e.operand(m.Value)
  44  	mapType := m.Map.SSAType()
  45  	if pt, ok := SafeUnderlying(mapType).(*Pointer); ok {
  46  		mapType = pt.Base
  47  	}
  48  	mt, _ := SafeUnderlying(mapType).(*TCMap)
  49  	keyType := "i32"
  50  	valType := "i32"
  51  	if mt != nil {
  52  		keyType = e.llvmType(mt.Key)
  53  		valType = e.llvmType(mt.Elem)
  54  	} else {
  55  		if m.Key.SSAType() != nil {
  56  			keyType = e.llvmType(m.Key.SSAType())
  57  		}
  58  		if m.Value.SSAType() != nil {
  59  			valType = e.llvmType(m.Value.SSAType())
  60  		}
  61  	}
  62  	if keyVal == "null" && keyType != "ptr" { keyVal = "zeroinitializer" }
  63  	if valVal == "null" && valType != "ptr" { valVal = "zeroinitializer" }
  64  	keyAlloca := e.nextReg2("mu")
  65  	e.w("  ") ; e.w(keyAlloca) ; e.w(" = alloca ") ; e.w(keyType) ; e.w("\n")
  66  	e.w("  store ") ; e.w(keyType) ; e.w(" ") ; e.w(keyVal) ; e.w(", ptr ") ; e.w(keyAlloca) ; e.w("\n")
  67  	valAlloca := e.nextReg2("mu")
  68  	e.w("  ") ; e.w(valAlloca) ; e.w(" = alloca ") ; e.w(valType) ; e.w("\n")
  69  	e.w("  store ") ; e.w(valType) ; e.w(" ") ; e.w(valVal) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
  70  	if mt != nil && e.isStringLike(mt.Key) {
  71  		kd := e.nextReg2("mu")
  72  		kl := e.nextReg2("mu")
  73  		kc := e.nextReg2("mu")
  74  		e.w("  ") ; e.w(kd) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 0\n")
  75  		e.w("  ") ; e.w(kl) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 1\n")
  76  		e.w("  ") ; e.w(kc) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 2\n")
  77  		e.w("  call void @runtime.hashmapContentSet(ptr ") ; e.w(mapVal)
  78  		e.w(", ptr ") ; e.w(kd)
  79  		e.w(", " | ipt | " ") ; e.w(kl)
  80  		e.w(", " | ipt | " ") ; e.w(kc)
  81  		e.w(", ptr ") ; e.w(valAlloca) ; e.w(", ptr null)\n")
  82  		e.declareRuntime("runtime.hashmapContentSet", "void", "ptr, ptr, " | ipt | ", " | ipt | ", ptr")
  83  	} else {
  84  		e.w("  call void @runtime.hashmapBinarySet(ptr ") ; e.w(mapVal)
  85  		e.w(", ptr ") ; e.w(keyAlloca)
  86  		e.w(", ptr ") ; e.w(valAlloca) ; e.w(", ptr null)\n")
  87  		e.declareRuntime("runtime.hashmapBinarySet", "void", "ptr, ptr, ptr")
  88  	}
  89  }
  90  
  91  func (e *irEmitter) emitLookup(l *SSALookup) {
  92  	reg := e.regName(l)
  93  	ipt := e.intptrType()
  94  	mapVal := e.operand(l.X)
  95  	keyVal := e.operand(l.Index)
  96  	mt, _ := SafeUnderlying(l.X.SSAType()).(*TCMap)
  97  	keyType := "i32"
  98  	valType := "i32"
  99  	if mt != nil {
 100  		keyType = e.llvmType(mt.Key)
 101  		valType = e.llvmType(mt.Elem)
 102  	} else {
 103  		if l.Index.SSAType() != nil {
 104  			keyType = e.llvmType(l.Index.SSAType())
 105  		}
 106  	}
 107  	valAlloca := e.nextReg2("ml")
 108  	e.w("  ") ; e.w(valAlloca) ; e.w(" = alloca ") ; e.w(valType) ; e.w("\n")
 109  	valSz := e.nextReg2("ml")
 110  	e.w("  ") ; e.w(valSz) ; e.w(" = ptrtoint ptr getelementptr (")
 111  	e.w(valType) ; e.w(", ptr null, i32 1) to ") ; e.w(ipt) ; e.w("\n")
 112  	if mt != nil && e.isStringLike(mt.Key) {
 113  		kd := e.nextReg2("ml")
 114  		kl := e.nextReg2("ml")
 115  		kc := e.nextReg2("ml")
 116  		e.w("  ") ; e.w(kd) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 0\n")
 117  		e.w("  ") ; e.w(kl) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 1\n")
 118  		e.w("  ") ; e.w(kc) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 2\n")
 119  		okReg := e.nextReg2("ml")
 120  		e.w("  ") ; e.w(okReg) ; e.w(" = call i1 @runtime.hashmapContentGet(ptr ") ; e.w(mapVal)
 121  		e.w(", ptr ") ; e.w(kd)
 122  		e.w(", " | ipt | " ") ; e.w(kl)
 123  		e.w(", " | ipt | " ") ; e.w(kc)
 124  		e.w(", ptr ") ; e.w(valAlloca)
 125  		e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(valSz) ; e.w(", ptr null)\n")
 126  		e.declareRuntime("runtime.hashmapContentGet", "i1", "ptr, ptr, " | ipt | ", " | ipt | ", ptr, " | ipt)
 127  		if l.CommaOk {
 128  			loaded := e.nextReg2("ml")
 129  			e.w("  ") ; e.w(loaded) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
 130  			tupType := "{" | valType | ", i1}"
 131  			t1 := e.nextReg2("ml")
 132  			e.w("  ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, ") ; e.w(valType) ; e.w(" ") ; e.w(loaded) ; e.w(", 0\n")
 133  			e.w("  ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i1 ") ; e.w(okReg) ; e.w(", 1\n")
 134  		} else {
 135  			e.w("  ") ; e.w(reg) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
 136  		}
 137  	} else {
 138  		keyAlloca := e.nextReg2("ml")
 139  		e.w("  ") ; e.w(keyAlloca) ; e.w(" = alloca ") ; e.w(keyType) ; e.w("\n")
 140  		e.w("  store ") ; e.w(keyType) ; e.w(" ") ; e.w(keyVal) ; e.w(", ptr ") ; e.w(keyAlloca) ; e.w("\n")
 141  		okReg := e.nextReg2("ml")
 142  		e.w("  ") ; e.w(okReg) ; e.w(" = call i1 @runtime.hashmapBinaryGet(ptr ") ; e.w(mapVal)
 143  		e.w(", ptr ") ; e.w(keyAlloca)
 144  		e.w(", ptr ") ; e.w(valAlloca)
 145  		e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(valSz) ; e.w(", ptr null)\n")
 146  		e.declareRuntime("runtime.hashmapBinaryGet", "i1", "ptr, ptr, ptr, " | ipt)
 147  		if l.CommaOk {
 148  			loaded := e.nextReg2("ml")
 149  			e.w("  ") ; e.w(loaded) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
 150  			tupType := "{" | valType | ", i1}"
 151  			t1 := e.nextReg2("ml")
 152  			e.w("  ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, ") ; e.w(valType) ; e.w(" ") ; e.w(loaded) ; e.w(", 0\n")
 153  			e.w("  ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i1 ") ; e.w(okReg) ; e.w(", 1\n")
 154  		} else {
 155  			e.w("  ") ; e.w(reg) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
 156  		}
 157  	}
 158  }
 159  
 160  func (e *irEmitter) isStringLike(t Type) (ok bool) {
 161  	if t == nil {
 162  		return false
 163  	}
 164  	if b, ok2 := SafeUnderlying(t).(*Basic); ok2 {
 165  		return b.Info&IsString != 0
 166  	}
 167  	return false
 168  }
 169