PageRenderTime 61ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/R/types.R

http://github.com/duncantl/RLLVMCompile
R | 330 lines | 249 code | 54 blank | 27 comment | 81 complexity | a6d526cb9ce2b8439dd83e959ab54f75 MD5 | raw file
  1. getTypes =
  2. function(obj, env, elementType = FALSE, .useFloat = env$.useFloat)
  3. {
  4. if(is(obj, "integer"))
  5. Int32Type
  6. else if(is(obj, "numeric")) {
  7. if(.useFloat) FloatType else DoubleType
  8. } else if(is.character(obj)) {
  9. StringType
  10. } else if(is.name(obj)) {
  11. id = as.character(obj)
  12. ans = if(id %in% names(env$.dimensionedTypes))
  13. env$.dimensionedTypes[[id]]
  14. else if(id %in% names(env$.types))
  15. env$.types[[ id ]]
  16. else if(id %in% names(env$.module)) {
  17. getTypes(getGlobalVariable(env$.module, id), env)
  18. } else
  19. # look in additional environments if necessary.
  20. getVariableType(id)
  21. if(elementType)
  22. getTypeOfElement(ans)
  23. else
  24. ans
  25. } else if(is.call(obj)) {
  26. # temporarily deal with x[ expr ]
  27. if(obj[[1]] == as.name("[")) # XXX not in any way general And doesn't handle vectors being returned.
  28. return(getTypes(obj[[2]], env, TRUE, .useFloat))
  29. fun = as.character(obj[[1]])
  30. if(fun == "(")
  31. return(getTypes(obj[[2]], env, .useFloat = .useFloat))
  32. if(fun %in% names(env$.functionInfo))
  33. return( get(fun, env$.functionInfo)$returnType )
  34. else if(fun %in% names(env$.builtInRoutines)) {
  35. return(env$.builtInRoutines[[fun]][[1]])
  36. }
  37. else if(fun %in% names(FunctionTypeInfo))
  38. return(getFunctionTypeInfo(fun, obj, env, elementType, FunctionTypeInfo, .useFloat = .useFloat))
  39. else if(fun %in% c("+", "-", "*")) {
  40. argTypes = lapply(obj[-1], getTypes, env)
  41. #XXX Make the following more general and more comprehensive test
  42. if(any(sapply(argTypes, function(x) sameType(x, DoubleType))))
  43. return(if(.useFloat) FloatType else DoubleType)
  44. else
  45. return(argTypes[[1]])
  46. }
  47. getDataType(obj, env)
  48. } else if(is(obj, "GlobalVariable"))
  49. getElementType(Rllvm::getType(obj))
  50. else if(is(obj, "Value"))
  51. Rllvm::getType(obj)
  52. else {
  53. stop("Can't determine type for ", class(obj))
  54. }
  55. }
  56. getVariableType =
  57. #
  58. # See getVariable() in utils.R and synchronize/merge
  59. #
  60. function(name, constants = ConstantInfo)
  61. {
  62. # if(name %in% names(constants))
  63. v = find(name)
  64. if(length(v) == 0)
  65. stop("cannot find variable ", name)
  66. mapRTypeToLLVM(class(get(name, v[1])))
  67. }
  68. getFunctionTypeInfo =
  69. function(funName, call, env, elementType = FALSE, info = FunctionTypeInfo, .useFloat = FALSE)
  70. {
  71. i = info[[funName]]
  72. ans = i$"return"
  73. if(is.character(ans))
  74. mapRTypeToLLVM(ans, .useFloat)
  75. else
  76. ans
  77. }
  78. mapRTypeToLLVM =
  79. function(name, .useFloat = FALSE)
  80. {
  81. switch(name,
  82. "numeric" = if(.useFloat) FloatType else DoubleType,
  83. "single" = FloatType,
  84. "integer" = Int32Type,
  85. stop("don't know mapping from ", name, " to LLVM"))
  86. }
  87. getMathOpType =
  88. # Convenience function for checking types in math ops: if types are
  89. # same, return the common type; if not, return DoubleType (as this
  90. # will be what we should coerce to).
  91. function(types, values = NULL)
  92. {
  93. if(length(types) == 1)
  94. return(types[[1]])
  95. if(sameType(types[[1]], types[[2]]))
  96. return(types[[1]])
  97. rawTypes = lapply(types, function(x) if(is(x, "Type")) x@ref else x)
  98. # if( identical(rawtypes[[1]], rawtypes[[2]]) )
  99. # return(types[[1]])
  100. ints = c(Int1Type@ref, Int8Type@ref, Int16Type@ref, Int32Type@ref)
  101. i = match(rawTypes, ints)
  102. if(!any(is.na(i)))
  103. return(ints[[ max(i) ]])
  104. i = match(rawTypes, c(Int32Type@ref, DoubleType@ref))
  105. if(!any(is.na(i)))
  106. return(DoubleType)
  107. i = match(rawTypes, c(Int8Type@ref, StringType@ref))
  108. if(all(!is.na(i))) {
  109. if(length(values)) {
  110. isChar = sapply(values, function(x) is.character(x) && nchar(x) == 1)
  111. if(any(isChar))
  112. return(Int8Type)
  113. return(StringType)
  114. }
  115. }
  116. }
  117. getTypeOfElement =
  118. #
  119. # Given a pointer type or an array type, return the type of the underlying element.
  120. #
  121. function(type)
  122. {
  123. if(is(type, "RMatrixType"))
  124. return(type@elType)
  125. if(is(type, "SEXPType"))
  126. return(switch(class(type),
  127. INTSXPType = Int32Type,
  128. LGLSXPType = Int32Type,
  129. REALSXPType = DoubleType,
  130. STRSXPType = StringType,
  131. VECSXP = getSEXPType(),
  132. stop("don't know element type of this SEXP")))
  133. if(isPointerType(type))
  134. return(getElementType(type))
  135. if (identical(type, DoublePtrType))
  136. return(DoubleType)
  137. else if (identical(type, Int32PtrType))
  138. return(Int32Type)
  139. else if (identical(type, FloatPtrType))
  140. return(FloatType)
  141. else
  142. stop("This type is not yet implemented.")
  143. }
  144. # There is an S4 generic getType in llvm. Why not provide methods for that
  145. getDataType =
  146. function(val, env, call = NULL)
  147. UseMethod("getDataType")
  148. getDataType.AsIs =
  149. function(val, env, call = NULL)
  150. {
  151. #XXX guessType from Rllvm
  152. Rllvm:::guessType(val)
  153. }
  154. getDataType.character =
  155. function(val, env, call = NULL)
  156. {
  157. ty = if(val %in% names(env$.types))
  158. env$.types[[val]]
  159. else if(val %in% names(env$.localVarTypes))
  160. env$.localVarTypes[[val]]
  161. else {
  162. # look it up in the module.
  163. var = env$.module[[ val ]]
  164. if(is.null(var))
  165. return(NULL)
  166. getElementType(getType(var))
  167. }
  168. typeFromMetadata(ty, val, env)
  169. }
  170. typeFromMetadata =
  171. function(ty, id, env)
  172. {
  173. if(is(ty, "StringType"))
  174. return(StringType)
  175. #XXXX Use the newer INTSXPType rather than the metadata, at least first. This will automatically happen
  176. # if the metadata is not found. But still should just return it unless the metadata is very different.
  177. if(sameType(ty, SEXPType)) {
  178. # Try to get more specific SEXP type by looking in the module's metadata.
  179. md = getMetadata(env$.module, id)
  180. if(!is.null(md)) {
  181. ty = as(md[[1]][[1]], "character")
  182. ty = gsub('[!"]', "", gsub("^metadata ", "", ty)) # the "metadata " is from LLVM 3.5
  183. return(get(ty, globalenv(), inherits = TRUE))
  184. }
  185. }
  186. ty
  187. }
  188. getDataType.integer =
  189. function(val, env, call = NULL)
  190. {
  191. Int32Type
  192. }
  193. getDataType.name =
  194. function(val, env, call = NULL)
  195. getDataType(as.character(val), env, call)
  196. getDataType.ConstantInt =
  197. function(val, env, call = NULL)
  198. {
  199. Int32Type
  200. }
  201. getDataType.ConstantFP =
  202. function(val, env, call = NULL)
  203. {
  204. DoubleType
  205. }
  206. #getDataType.LoadInst =
  207. getDataType.StoreInst = getDataType.Value =
  208. getDataType.BinaryOperator =
  209. function(val, env, call = NULL)
  210. {
  211. ty = Rllvm::getType(val)
  212. if(sameType(ty, SEXPType)) {
  213. # try to make this more specific to the R type.
  214. if(is.call(call) && as.character(call[[1]]) %in% RewrittenRoutineNames) {
  215. # These need to be in the function rather than outside as they will be null pointers until Rllvm is loaded.
  216. ConstructorTypes = list(
  217. numeric = REALSXPType,
  218. double = REALSXPType,
  219. integer = INTSXPType,
  220. logical = LGLSXPType,
  221. character = STRSXPType,
  222. list = VECSXPType
  223. )
  224. ty = ConstructorTypes[[as.character(call[[1]])]]
  225. }
  226. }
  227. ty
  228. }
  229. getDataType.call =
  230. function(val, env, call = NULL)
  231. {
  232. fun = as.character(val[[1]])
  233. if(fun %in% MathOps) { #XXXX
  234. types = lapply(val[-1], getTypes, env)
  235. return(getMathOpType(types))
  236. }
  237. mod = env$.module
  238. if(fun %in% names(mod) && is( f <- mod[[fun]], "Function")) {
  239. return(getReturnType(f))
  240. }
  241. #XXX Builtin types that we know about.
  242. warning("can't tell type of call ", paste(deparse(val), collapse = " "))
  243. NULL
  244. }
  245. getDataType.default =
  246. function(val, env, call = NULL)
  247. {
  248. # return(getTypes(val, env))
  249. if(length(val) == 1)
  250. mapRTypeToLLVM(class(val))
  251. else {
  252. warning("getDataType for ", class(val), ": default method")
  253. NULL
  254. }
  255. }
  256. getRVectorFunFromScalar =
  257. function(scalarType)
  258. {
  259. rtypes = lapply(c(Int32Type, DoubleType, Int8Type), getTypeID)
  260. # types = list(INTSXPType, REALSXPType, LGLSXPType)
  261. types = list("integer", "numeric", "logical")
  262. i = match(getTypeID(scalarType), rtypes)
  263. if(is.na(i))
  264. stop("need to match R type for")
  265. types[[i]]
  266. }
  267. getRVectorTypeFromScalar =
  268. function(scalarType)
  269. {
  270. rtypes = lapply(c(Int32Type, DoubleType, Int8Type), getTypeID)
  271. types = list(INTSXPType, REALSXPType, LGLSXPType)
  272. i = match(getTypeID(scalarType), rtypes)
  273. if(is.na(i))
  274. stop("need to match R type for")
  275. types[[i]]
  276. }