fork(1) download
  1. case object Empty extends Regex
  2. case class Let(c: Char) extends Regex
  3. case class Con(a: Regex, b: Regex) extends Regex
  4. case class Alt(a: Regex, b: Regex) extends Regex
  5. case class Star(a: Regex) extends Regex
  6.  
  7. case class RInt(n: Int) extends Value
  8. case class RStr(s: String) extends Value
  9. case class VInt(n: Int) extends Value
  10. case class BA(f: String, l: Value) extends Value
  11.  
  12. case object I64P extends Type
  13.  
  14.  
  15. case class Label(n: Value) extends Inst
  16. case class Assign(l: Value, r: Inst) extends Inst
  17. case class Add(t: Type, v: Value, n: Int) extends Inst
  18. case class Cmp(c: Cond, t: Type, a: Value, b: Value) extends Inst
  19. case class Br1(d: Value) extends Inst
  20. case class Br2(c: Value, t: Value, e: Value) extends Inst
  21. case class Call(f: String, rt: Type, at: List[(Type, Value)]) extends Inst
  22. case class Load(t: Type, p: Value) extends Inst
  23. case class Store(vt: Type, v: Value, pt: Type, pv: Value) extends Inst
  24. case class GetElementPtr(t: Type, v: Value, i: Value) extends Inst
  25.  
  26. object Main {
  27. def nsp = RStr("sp")
  28. def nstr = RStr("str")
  29. def nmatch = RStr("match")
  30. def nmiss = RStr("miss")
  31.  
  32. def fname = "@test"
  33.  
  34. def assign(r: Inst, n: Int): (Inst, Int) = (Assign(RInt(n), r), n + 1)
  35. def mk_label(n: Int): (Inst, Int) = (Label(RInt(n)), n + 1)
  36.  
  37. def insts_of_regex(re: Regex): List[Inst] = {
  38. def loop(re: Regex, n: Int): (List[Inst], Int) = re match {
  39. case Empty => (Nil, n)
  40.  
  41. case Let(c) =>
  42. val (i1, n1) = mk_label(n)
  43. val (i2, n2) = assign(Load(I64P, nsp), n1)
  44. val (i3, n3) = assign(GetElementPtr(I8P, nstr, RInt(n1)), n2)
  45. val (i4, n4) = assign(Add(I64, RInt(n1), 1), n3)
  46. val i5 = Store(I64, RInt(n3), I64P, nsp)
  47. val (i6, n5) = assign(Load(I8P, RInt(n2)), n4)
  48. val (i7, n6) = assign(Cmp(Eq, I8, RInt(n4), VInt(c.toInt)), n5)
  49. val i8 = Br2(RInt(n5), RInt(n6), nmiss)
  50. (List(i1, i2, i3, i4, i5, i6, i7, i8), n6)
  51.  
  52. case Con(a, b) =>
  53. val (i1, n1) = loop(a, n)
  54. val (i2, n2) = loop(b, n1)
  55. (i1 ++ i2, n2)
  56.  
  57. case Alt(a, b) =>
  58. val (i1, n1) = mk_label(n)
  59. val (i2, n2) = assign(Load(I64P, nsp), n1)
  60. val (i3, _) = assign(Call(fname, I1, List((I8P, BA(fname, RInt(n2 + 1))), (I64, RInt(n1)))), n2)
  61. val (i4, n4) = loop(a, n2 + 1)
  62. val (i5, n5) = mk_label(n4)
  63. val (i6, n6) = loop(b, n5)
  64. val i7 = Br1(RInt(n6))
  65. val i8 = Br2(RInt(n2), nmatch, RInt(n5))
  66. (List(i1, i2, i3, i8) ++ i4 ++ List(i5, i7) ++ i6, n6)
  67.  
  68. case Star(Star(r)) => loop(Star(r), n)
  69.  
  70. case Star(r) =>
  71. val (i1, n1) = mk_label(n)
  72. val (i2, n2) = assign(Load(I64P, nsp), n1)
  73. val (i3, _) = assign(Call(fname, I1, List((I8P, BA(fname, RInt(n2 + 1))), (I64, RInt(n1)))), n2)
  74. val (i4, n3) = loop(r, n2 + 1)
  75. val (i5, n4) = mk_label(n3)
  76. val i6 = Br1(RInt(n))
  77. val i7 = Br2(RInt(n2), nmatch, RInt(n4))
  78. (List(i1, i2, i3, i7) ++ i4 ++ List(i5, i6), n4)
  79. }
  80.  
  81. val (i, n) = loop(re, 1)
  82. i ++ List(Label(RInt(n)), Br1(nmatch))
  83. }
  84.  
  85. def label_of_value(v: Value): String = v match {
  86. case RInt(n) => n.toString
  87. case _ => throw new Exception()
  88. }
  89.  
  90. def var_of_value(v: Value): String = v match {
  91. case RInt(n) => "%" + n
  92. case RStr(s) => "%" + s
  93. case VInt(n) => n.toString
  94. case BA(f, l) => "blockaddress(" + f + ", " + var_of_value(l) + ")"
  95. }
  96.  
  97. def pp_cond(c: Cond): String = c match {
  98. case Eq => "eq"
  99. }
  100.  
  101. def pp_type(t: Type): String = t match {
  102. case I1 => "i1"
  103. case I8 => "i8"
  104. case I8P => "i8*"
  105. case I64 => "i64"
  106. case I64P => "i64*"
  107. }
  108.  
  109. def align(t: Type): Int = t match {
  110. case I8 => 1
  111. case I8P => 8
  112. case I64 => 8
  113. case I64P => 8
  114. case I1 => throw new Exception()
  115. }
  116.  
  117. def pp_inst(i: Inst, tab: String = ""): String =
  118. tab + (i match {
  119. case Label(n) =>
  120. "\n; <label>:" + label_of_value(n)
  121. case Assign(l, r) =>
  122. var_of_value(l) + " = " + pp_inst(r)
  123. case Add(t, v, n) =>
  124. "add nsw " + pp_type(t) + " " + var_of_value(v) + ", " + n
  125. case Cmp(c, t, a, b) =>
  126. "icmp " + pp_cond(c) + " " + pp_type(t) + " " + var_of_value(a) + ", " + var_of_value(b)
  127. case Br1(d) =>
  128. "br label " + var_of_value(d)
  129. case Br2(c, t, e) =>
  130. "br i1 " + var_of_value(c) + ", label " + var_of_value(t) + ", label " + var_of_value(e)
  131. case Call(f, rt, a) =>
  132. val s = a.foldLeft("i8* %str")((x, y) => x + ", " + pp_type(y._1) + " " + var_of_value(y._2))
  133. "call " + pp_type(rt) + " " + f + "(" + s + ")"
  134. case Load(t, p) =>
  135. "load " + pp_type(t) + " " + var_of_value(p) + ", align " + align(t)
  136. case Store(vt, v, pt, pv) =>
  137. "store " + pp_type(vt) + " " + var_of_value(v) + ", " + pp_type(pt) + " " +
  138. var_of_value(pv) + ", align " + align(vt)
  139. case GetElementPtr(t, v, i) =>
  140. "getelementptr inbounds " + pp_type(t) + " " + var_of_value(v) + ", i64 " + var_of_value(i)
  141. })
  142.  
  143. def make(i: List[Inst]): String = {
  144. val s =
  145. "@.match = private unnamed_addr constant [7 x i8] c\"match\\0A\\00\", align 1\n" +
  146. "@.unmatch = private unnamed_addr constant [9 x i8] c\"unmatch\\0A\\00\", align 1\n\n" +
  147. "define i1 @test(i8* %str, i8* %l, i64 %sp_value) {\n" +
  148. " %sp = alloca i64, align 8\n" +
  149. " store i64 %sp_value, i64* %sp, align 8\n" +
  150. " %isnull = icmp eq i8* %l, null\n" +
  151. " br i1 %isnull, label %1, label %jump\n\n" +
  152. "jump:\n" +
  153. " indirectbr i8* %l, [" +
  154. i.foldRight(List[String]())((x, y) => x match {
  155. case Label(n) => ("label " + var_of_value(n)) :: y
  156. case _ => y
  157. }).mkString(", ") + "]\n"
  158.  
  159. val llvmir = i.map(pp_inst(_, " ")).foldLeft("")((x, y) => x + y + "\n")
  160.  
  161. val e =
  162. "\nmiss:\n" +
  163. " ret i1 0\n\n" +
  164. "match:\n" +
  165. " ret i1 1\n" +
  166. "}\n\n" +
  167. "define i32 @main(i32 %argc, i8** %argv) {\n" +
  168. " %arg1 = getelementptr inbounds i8** %argv, i64 1\n" +
  169. " %str = load i8** %arg1, align 8\n" +
  170. " %res = call i1 @test(i8* %str, i8* null, i64 0)\n" +
  171. " br i1 %res, label %match, label %unmatch\n\n" +
  172. "match:\n" +
  173. " call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 x i8]* @.match, i32 0, i32 0))\n" +
  174. " br label %ret\n\n" +
  175. "unmatch:\n" +
  176. " call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.unmatch, i32 0, i32 0))\n" +
  177. " br label %ret\n\n" +
  178. "ret:\n" +
  179. " ret i32 0\n" +
  180. "}\n\n" +
  181. "declare i32 @printf(i8*, ...)"
  182.  
  183. s + llvmir + e
  184. }
  185.  
  186. def main(args: Array[String]): Unit = {
  187. // aa*bb*
  188. val re1 = Con( Con(Let('a'), Star(Let('a'))), Con(Let('b'), Star(Let('b'))) )
  189. // (a|b)c
  190. val re2 = Con( Alt(Let('a'), Let('b')), Let('c') )
  191. // (a*)*a
  192. val re3 = Con(Star(Star(Let('a'))), Let('a'))
  193. // aaaa
  194. val re4 = Con( Con(Let('a'), Let('a')), Con(Let('a'), Let('a')) )
  195. // (ba*ba*)*a
  196. val re5 = Con(Star(Con(Con(Star(Let('a')), Let('b')), Star(Let('a')))), Let('a'))
  197. // sa*(ba*ba*)*a*e
  198. val re6 = Con(Con(Let('s'), Con(Con(Star(Let('a')), Star(Con(Con(Let('b'), Star(Let('a'))), Con(Let('b'), Star(Let('a')))))), Star(Let('a')))), Let('e'))
  199. // s(ab*)*e
  200. val re7 = Con(Con(Let('s'), Star(Con(Let('a'), Star(Let('b'))))), Let('e'))
  201. // ba*b
  202. val re8 = Con(Con(Let('b'), Star(Let('a'))), Let('b'))
  203.  
  204. val i = insts_of_regex(re8)
  205. println(make(i))
  206. }
  207. }
  208.  
Success #stdin #stdout 0.37s 322368KB
stdin
Standard input is empty
stdout
@.match   = private unnamed_addr constant [7 x i8] c"match\0A\00", align 1
@.unmatch = private unnamed_addr constant [9 x i8] c"unmatch\0A\00", align 1

define i1 @test(i8* %str, i8* %l, i64 %sp_value) {
  %sp = alloca i64, align 8
  store i64 %sp_value, i64* %sp, align 8
  %isnull = icmp eq i8* %l, null
  br i1 %isnull, label %1, label %jump

jump:
  indirectbr i8* %l, [label %1, label %7, label %10, label %16, label %17, label %23]
  
; <label>:1
  %2 = load i64* %sp, align 8
  %3 = getelementptr inbounds i8* %str, i64 %2
  %4 = add nsw i64 %2, 1
  store i64 %4, i64* %sp, align 8
  %5 = load i8* %3, align 8
  %6 = icmp eq i8 %5, 98
  br i1 %6, label %7, label %miss
  
; <label>:7
  %8 = load i64* %sp, align 8
  %9 = call i1 @test(i8* %str, i8* blockaddress(@test, %10), i64 %8)
  br i1 %9, label %match, label %17
  
; <label>:10
  %11 = load i64* %sp, align 8
  %12 = getelementptr inbounds i8* %str, i64 %11
  %13 = add nsw i64 %11, 1
  store i64 %13, i64* %sp, align 8
  %14 = load i8* %12, align 8
  %15 = icmp eq i8 %14, 97
  br i1 %15, label %16, label %miss
  
; <label>:16
  br label %7
  
; <label>:17
  %18 = load i64* %sp, align 8
  %19 = getelementptr inbounds i8* %str, i64 %18
  %20 = add nsw i64 %18, 1
  store i64 %20, i64* %sp, align 8
  %21 = load i8* %19, align 8
  %22 = icmp eq i8 %21, 98
  br i1 %22, label %23, label %miss
  
; <label>:23
  br label %match

miss:
  ret i1 0

match:
  ret i1 1
}

define i32 @main(i32 %argc, i8** %argv) {
  %arg1 = getelementptr inbounds i8** %argv, i64 1
  %str  = load i8** %arg1, align 8
  %res  = call i1 @test(i8* %str, i8* null, i64 0)
  br i1 %res, label %match, label %unmatch

match:
  call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 x i8]* @.match, i32 0, i32 0))
  br label %ret

unmatch:
  call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.unmatch, i32 0, i32 0))
  br label %ret

ret:
  ret i32 0
}

declare i32 @printf(i8*, ...)