1 ============================================== 2 llvm-rs-cc: Compiler for Renderscript language 3 ============================================== 4 5 6 Introduction 7 ------------ 8 9 llvm-rs-cc compiles a program in the Renderscript language to generate the 10 following files: 11 12 * Bitcode file. Note that the bitcode here denotes the LLVM (Low-Level 13 Virtual Machine) bitcode representation, which will be consumed on 14 an Android device by libbcc (in 15 platform/frameworks/compile/libbcc.git) to generate device-specific 16 executables. 17 18 * Reflected APIs for Java. As a result, Android's Java developers can 19 invoke those APIs from their code. 20 21 Note that although Renderscript is C99-like, we enhance it with several 22 distinct, effective features for Android programming. We will use 23 some examples to illustrate these features. 24 25 llvm-rs-cc is run on the host and performs many aggressive optimizations. 26 As a result, libbcc on the device can be lightweight and focus on 27 machine-dependent code generation for some input bitcode. 28 29 llvm-rs-cc is a driver on top of libslang. The architecture of 30 libslang and libbcc is depicted in the following figure:: 31 32 libslang libbcc 33 | \ | 34 | \ | 35 clang llvm 36 37 38 Usage 39 ----- 40 41 * *-o $(PRIVATE_RS_OUTPUT_DIR)/res/raw* 42 43 This option specifies the directory for outputting a .bc file. 44 45 * *-p $(PRIVATE_RS_OUTPUT_DIR)/src* 46 47 The option *-p* denotes the directory for outputting the reflected Java files. 48 49 * *-d $(PRIVATE_RS_OUTPUT_DIR)* 50 51 This option *-d* sets the directory for writing dependence information. 52 53 * *-MD* 54 55 Note that *-MD* will tell llvm-rs-cc to output dependence information. 56 57 * *-a $(EXTRA_TARGETS)* 58 59 Specifies additional target dependencies. 60 61 Example Command 62 --------------- 63 64 First:: 65 66 $ cd <Android_Root_Directory> 67 68 Using frameworks/base/tests/RenderScriptTests/Fountain as a simple app in both 69 Java and Renderscript, we can find the following command line in the build 70 log:: 71 72 $ out/host/linux-x86/bin/llvm-rs-cc \ 73 -o out/target/common/obj/APPS/Fountain_intermediates/src/renderscript/res/raw \ 74 -p out/target/common/obj/APPS/Fountain_intermediates/src/renderscript/src \ 75 -d out/target/common/obj/APPS/Fountain_intermediates/src/renderscript \ 76 -a out/target/common/obj/APPS/Fountain_intermediates/src/RenderScript.stamp \ 77 -MD \ 78 -I frameworks/base/libs/rs/scriptc \ 79 -I external/clang/lib/Headers \ 80 frameworks/base/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs 81 82 This command will generate: 83 84 * **fountain.bc** 85 86 * **ScriptC_fountain.java** 87 88 * **ScriptField_Point.java** 89 90 The **Script\*.java** files above will be documented below. 91 92 93 Example Program: fountain.rs 94 ---------------------------- 95 96 fountain.rs is in the Renderscript language, which is based on the standard 97 C99. However, llvm-rs-cc goes beyond "clang -std=c99" and provides the 98 following important features: 99 100 1. Pragma 101 --------- 102 103 * *#pragma rs java_package_name([PACKAGE_NAME])* 104 105 The ScriptC_[SCRIPT_NAME].java has to be packaged so that Java 106 developers can invoke those APIs. 107 108 To do that, a Renderscript programmer should specify the package name, so 109 that llvm-rs-cc knows the package expression and hence the directory 110 for outputting ScriptC_[SCRIPT_NAME].java. 111 112 In fountain.rs, we have:: 113 114 #pragma rs java_package_name(com.android.fountain) 115 116 In ScriptC_fountain.java, we have:: 117 118 package com.android.fountain 119 120 Note that the ScriptC_fountain.java will be generated inside 121 ./com/android/fountain/. 122 123 * #pragma version(1) 124 125 This pragma is for evolving the language. Currently we are at 126 version 1 of the language. 127 128 129 2. Basic Reflection: Export Variables and Functions 130 --------------------------------------------------- 131 132 llvm-rs-cc automatically exports the "externalizable and defined" functions and 133 variables to Android's Java side. That is, scripts are accessible from 134 Java. 135 136 For instance, for:: 137 138 int foo = 0; 139 140 In ScriptC_fountain.java, llvm-rs-cc will reflect the following methods:: 141 142 void set_foo(int v)... 143 144 int get_foo()... 145 146 This access takes the form of generated classes which provide access 147 to the functions and global variables within a script. In summary, 148 global variables and functions within a script that are not declared 149 static will generate get, set, or invoke methods. This provides a way 150 to set the data within a script and call its functions. 151 152 Take the addParticles function in fountain.rs as an example:: 153 154 void addParticles(int rate, float x, float y, int index, bool newColor) { 155 ... 156 } 157 158 llvm-rs-cc will genearte ScriptC_fountain.java as follows:: 159 160 void invoke_addParticles(int rate, float x, float y, 161 int index, bool newColor) { 162 ... 163 } 164 165 166 3. Export User-Defined Structs 167 ------------------------------ 168 169 In fountain.rs, we have:: 170 171 typedef struct __attribute__((packed, aligned(4))) Point { 172 float2 delta; 173 float2 position; 174 uchar4 color; 175 } Point_t; 176 177 Point_t *point; 178 179 llvm-rs-cc generates one ScriptField*.java file for each user-defined 180 struct. In this case, llvm-rs-cc will reflect two files, 181 ScriptC_fountain.java and ScriptField_Point.java. 182 183 Note that when the type of an exportable variable is a structure, Renderscript 184 developers should avoid using anonymous structs. This is because llvm-rs-cc 185 uses the struct name to identify the file, instead of the typedef name. 186 187 For the generated Java files, using ScriptC_fountain.java as an 188 example we also have:: 189 190 void bind_point(ScriptField_Point v) 191 192 This binds your object with the allocated memory. 193 194 You can bind the struct(e.g., Point), using the setter and getter 195 methods in ScriptField_Point.java. 196 197 After binding, you can access the object with this method:: 198 199 ScriptField_Point get_point() 200 201 In ScriptField_Point_s.java:: 202 203 ... 204 // Copying the Item, which is the object that stores every 205 // fields of struct, to the *index*\-th entry of byte array. 206 // 207 // In general, this method would not be invoked directly 208 // but is used to implement the setter. 209 void copyToArray(Item i, int index) 210 211 // The setter of Item array, 212 // index: the index of the Item array 213 // copyNow: If true, it will be copied to the *index*\-th entry 214 // of byte array. 215 void set(Item i, int index, boolean copyNow) 216 217 // The getter of Item array, which gets the *index*-th element 218 // of byte array. 219 Item get(int index) 220 221 set_delta(int index, Float2 v, boolean copyNow) 222 223 // The following is the individual setters and getters of 224 // each field of a struct. 225 public void set_delta(int index, Float2 v, boolean copyNow) 226 public void set_position(int index, Float2 v, boolean copyNow) 227 public void set_color(int index, Short4 v, boolean copyNow) 228 public Float2 get_delta(int index) 229 public Float2 get_position(int index) 230 public Short4 get_color(int index) 231 232 // Copying all Item array to byte array (i.e., memory allocation). 233 void copyAll() 234 ... 235 236 237 4. Summary of the Java Reflection above 238 --------------------------------------- 239 240 This section summarizes the high-level design of Renderscript's reflection. 241 242 * In terms of a script's global functions, they can be called from Java. 243 These calls operate asynchronously and no assumptions should be made 244 on whether a function called will have actually completed operation. If it 245 is necessary to wait for a function to complete, the Java application 246 may call the runtime finish() method, which will wait for all the script 247 threads to complete pending operations. A few special functions can also 248 exist: 249 250 * The function **init** (if present) will be called once after the script 251 is loaded. This is useful to initialize data or anything else the 252 script may need before it can be used. The init function may not depend 253 on globals initialized from Java as it will be called before these 254 can be initialized. The function signature for init must be:: 255 256 void init(void); 257 258 * The function **root** is a special function for graphics. This function 259 will be called when a script must redraw its contents. No 260 assumptions should be made as to when this function will be 261 called. It will only be called if the script is bound as a graphics root. 262 Calls to this function will be synchronized with data updates and 263 other invocations from Java. Thus the script will not change due 264 to external influence in the middle of running **root**. The return value 265 indicates to the runtime when the function should be called again to 266 redraw in the future. A return value of 0 indicates that no 267 redraw is necessary until something changes on the Java side. Any 268 positive integer indicates a time in milliseconds that the runtime should 269 wait before calling root again to render another frame. The function 270 signature for a graphics root functions is as follows:: 271 272 int root(void); 273 274 * It is also possible to create a purely compute-based **root** function. 275 Such a function has the following signature:: 276 277 void root(const T1 *in, T2 *out, const T3 *usrData, uint32_t x, uint32_t y); 278 279 T1, T2, and T3 represent any supported Renderscript type. Any parameters 280 above can be omitted, although at least one of in/out must be present. 281 If both in and out are present, root must only be invoked with types of 282 the same exact dimensionality (i.e. matching X and Y values for dimension). 283 This root function is accessible through the Renderscript language 284 construct **forEach**. We also reflect a Java version to access this 285 function as **forEach_root** (for API levels of 14+). An example of this 286 can be seen in the Android SDK sample for HelloCompute. 287 288 * The function **.rs.dtor** is a function that is sometimes generated by 289 llvm-rs-cc. This function cleans up any global variable that contains 290 (or is) a reference counted Renderscript object type (such as an 291 rs_allocation, rs_font, or rs_script). This function will be invoked 292 implicitly by the Renderscript runtime during script teardown. 293 294 * In terms of a script's global data, global variables can be written 295 from Java. The Java instance will cache the value or object set and 296 provide return methods to retrieve this value. If a script updates 297 the value, this update will not propagate back to the Java class. 298 Initializers, if present, will also initialize the cached Java value. 299 This provides a convenient way to declare constants within a script and 300 make them accessible to the Java runtime. If the script declares a 301 variable const, only the get methods will be generated. 302 303 Globals within a script are considered local to the script. They 304 cannot be accessed by other scripts and are in effect always 'static' 305 in the traditional C sense. Static here is used to control if 306 accessors are generated. Static continues to mean *not 307 externally visible* and thus prevents the generation of 308 accessors. Globals are persistent across invocations of a script and 309 thus may be used to hold data from run to run. 310 311 Globals of two types may be reflected into the Java class. The first 312 type is basic non-pointer types. Types defined in rs_types.rsh may also be 313 used. For the non-pointer class, get and set methods are generated for 314 Java. Globals of single pointer types behave differently. These may 315 use more complex types. Simple structures composed of the types in 316 rs_types.rsh may also be used. These globals generate bind points in 317 Java. If the type is a structure they also generate an appropriate 318 **Field** class that is used to pack and unpack the contents of the 319 structure. Binding an allocation in Java effectively sets the 320 pointer in the script. Bind points marked const indicate to the 321 runtime that the script will not modify the contents of an allocation. 322 This may allow the runtime to make more effective use of threads. 323 324 325 5. Vector Types 326 --------------- 327 328 Vector types such as float2, float4, and uint4 are included to support 329 vector processing in environments where the processors provide vector 330 instructions. 331 332 On non-vector systems the same code will continue to run but without 333 the performance advantage. Function overloading is also supported. 334 This allows the runtime to support vector version of the basic math 335 routines without the need for special naming. For instance, 336 337 * *float sin(float);* 338 339 * *float2 sin(float2);* 340 341 * *float3 sin(float3);* 342 343 * *float4 sin(float4);* 344