/red-system/targets/target-class.r

http://github.com/dockimbel/Red · R · 180 lines · 160 code · 20 blank · 0 comment · 13 complexity · a053907dbf149714a1565b53862a5603 MD5 · raw file

  1. REBOL [
  2. Title: "Red/System code emitter base object"
  3. Author: "Nenad Rakocevic"
  4. File: %target-class.r
  5. Rights: "Copyright (C) 2011 Nenad Rakocevic. All rights reserved."
  6. License: "BSD-3 - https://github.com/dockimbel/Red/blob/master/BSD-3-License.txt"
  7. ]
  8. target-class: context [
  9. target: little-endian?: struct-align: ptr-size: void-ptr: none ; TBD: document once stabilized
  10. default-align: stack-width: branch-offset-size: none ; TBD: document once stabilized
  11. on-global-prolog: none ;-- called at start of global code section
  12. on-global-epilog: none ;-- called at end of global code section
  13. on-finalize: none ;-- called after all sources are compiled
  14. on-root-level-entry: none ;-- called after a root level expression or directive is compiled
  15. emit-stack-align-prolog: none ;-- align stack on imported function calls
  16. emit-stack-align-epilog: none ;-- unwind aligned stack
  17. compiler: none ;-- just a short-cut
  18. width: none ;-- current operand width in bytes
  19. signed?: none ;-- TRUE => signed op, FALSE => unsigned op
  20. last-saved?: no ;-- TRUE => operand saved in another register
  21. verbose: 0 ;-- logs verbosity level
  22. emit-casting: emit-call-syscall: emit-call-import:
  23. emit-call-native: emit-not: emit-push: emit-pop:
  24. emit-operation: none ;-- just pre-bind word to avoid contexts issue
  25. comparison-op: [= <> < > <= >=]
  26. math-op: [+ - * / // ///]
  27. bitwise-op: [and or xor]
  28. bitshift-op: [>> << -**]
  29. opp-conditions: [
  30. ;-- condition ------ opposite condition --
  31. overflow? not-overflow?
  32. not-overflow? overflow?
  33. = <>
  34. <> =
  35. even? odd?
  36. odd? even?
  37. < >=
  38. >= <
  39. <= >
  40. > <=
  41. ]
  42. opposite?: func [cond [word!]][
  43. first select/skip opp-conditions cond 2
  44. ]
  45. power-of-2?: func [n [integer! char!]][
  46. if all [
  47. n: to integer! n
  48. positive? n
  49. zero? n - 1 and n
  50. ][
  51. to integer! log-2 n
  52. ]
  53. ]
  54. emit: func [bin [binary! char! block!]][
  55. if verbose >= 4 [print [">>>emitting code:" mold bin]]
  56. append emitter/code-buf bin
  57. ]
  58. emit-reloc-addr: func [spec [block!]][
  59. append spec/3 emitter/tail-ptr ;-- save reloc position
  60. emit void-ptr ;-- emit void addr, reloc later
  61. unless empty? emitter/chunks/queue [
  62. append/only ;-- record reloc reference
  63. second last emitter/chunks/queue
  64. back tail spec/3
  65. ]
  66. ]
  67. emit-variable: func [
  68. name [word! object!] gcode [binary!] lcode [binary! block!]
  69. /local offset
  70. ][
  71. if object? name [name: compiler/unbox name]
  72. either offset: select emitter/stack name [
  73. if any [ ;-- local variable case
  74. offset < -128
  75. offset > 127
  76. ][
  77. compiler/throw-error "#code generation error: overflow in emit-variable"
  78. ]
  79. offset: skip debase/base to-hex offset 16 3 ; @@ just to-char ??
  80. either block? lcode [
  81. emit reduce bind lcode 'offset
  82. ][
  83. emit lcode
  84. emit offset
  85. ]
  86. ][ ;-- global variable case
  87. emit gcode
  88. emit-reloc-addr emitter/symbols/:name
  89. ]
  90. ]
  91. get-width: func [operand type /local value][
  92. reduce [
  93. emitter/size-of? value: case [
  94. type [operand]
  95. 'else [
  96. value: first compiler/get-type operand
  97. either value = 'any-pointer! ['pointer!][value]
  98. ]
  99. ]
  100. value
  101. ]
  102. ]
  103. set-width: func [operand /type /local value][
  104. value: get-width operand type
  105. width: value/1
  106. signed?: emitter/signed? value/2
  107. ]
  108. with-width-of: func [value body [block!] /alt /local old][
  109. old: width
  110. set-width compiler/unbox value
  111. do body
  112. width: old
  113. if all [alt object? value][emit-casting value yes] ;-- casting for right operand
  114. ]
  115. implicit-cast: func [arg /local right-width][
  116. right-width: first get-width arg none
  117. if all [width = 4 right-width = 1][ ;-- detect byte! -> integer! implicit casting
  118. arg: make object! [action: 'type-cast type: [integer!] data: arg]
  119. emit-casting arg yes ;-- type cast right argument
  120. ]
  121. ]
  122. emit-call: func [name [word!] args [block!] sub? [logic!] /local spec fspec res][
  123. if verbose >= 3 [print [">>>calling:" mold name mold args]]
  124. fspec: select compiler/functions name
  125. spec: any [select emitter/symbols name next fspec]
  126. type: first spec
  127. switch type [
  128. syscall [
  129. emit-call-syscall args fspec
  130. ]
  131. import [
  132. emit-call-import args fspec spec
  133. ]
  134. native [
  135. emit-call-native args fspec spec
  136. ]
  137. inline [
  138. if block? args/1 [args/1: <last>] ;-- works only for unary functions
  139. do select [
  140. not [emit-not args/1]
  141. push [emit-push args/1]
  142. pop [emit-pop]
  143. ] name
  144. if name = 'not [res: compiler/get-type args/1]
  145. ]
  146. op [
  147. emit-operation name args
  148. if sub? [emitter/logic-to-integer name]
  149. unless find comparison-op name [ ;-- comparison always return a logic!
  150. res: any [
  151. ;all [object? args/1 args/1/type]
  152. all [not sub? block? args/1 compiler/last-type]
  153. compiler/get-type args/1 ;-- other ops return type of the first argument
  154. ]
  155. ]
  156. ]
  157. ]
  158. res
  159. ]
  160. ]