From 26250471b46a68204711f037f33790bfb4ba37c7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 23 Nov 2012 11:47:00 +0100 Subject: [PATCH 01/81] fix socket.h --- system/include/sys/socket.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/include/sys/socket.h b/system/include/sys/socket.h index c50a37868e158..10ba5ce8a653d 100644 --- a/system/include/sys/socket.h +++ b/system/include/sys/socket.h @@ -38,8 +38,8 @@ extern "C" { #define SHUT_RDWR 2 typedef unsigned int sa_family_t; -#define AF_INET 1000 -#define AF_INET6 6000 +#define AF_INET 1 +#define AF_INET6 6 struct sockaddr { sa_family_t sa_family; From e75bf36fab5f47905395503bda466dfa3693096b Mon Sep 17 00:00:00 2001 From: Tobias Weibel Date: Tue, 4 Dec 2012 10:55:04 +0100 Subject: [PATCH 02/81] Ignore generated files src/relooper.js[.raw.js] for git --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 7a0f2f78c08ef..eaaa4ed59fa0a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ *~ *.bc +# Ignore generated files +src/relooper.js +src/relooper.js.raw.js From 6e00c50f6d3e1d183d2792990819d82cc3009222 Mon Sep 17 00:00:00 2001 From: Michael Riss Date: Wed, 16 Jan 2013 21:12:31 +0100 Subject: [PATCH 03/81] Added the gluOrtho2D function. Signed-off-by: Michael Riss --- AUTHORS | 2 +- src/library_gl.js | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 04dfc10da4012..9399a4f8ccf4f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -44,4 +44,4 @@ a license to everyone to use it as detailed in LICENSE.) * Dominic Wong * Alan Kligman (copyright owned by Mozilla Foundation) * Anthony Liot - +* Michael Riß diff --git a/src/library_gl.js b/src/library_gl.js index 267a61858c9f7..f6793dc9d7e51 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -2462,7 +2462,11 @@ var LibraryGL = { {{{ makeSetValue('objZ', '0', 'result[2]', 'double') }}}; return 1 /* GL_TRUE */; - } + }, + + gluOrtho2D: function(left, right, bottom, top) { + _glOrtho(left, right, bottom, top, -1, 1); + }, }; // Simple pass-through functions. Starred ones have return values. [X] ones have X in the C name but not in the JS name From f6b6853cc0369ccdaf762c35e338d59bc69675f5 Mon Sep 17 00:00:00 2001 From: Michael Riss Date: Wed, 16 Jan 2013 22:52:32 +0100 Subject: [PATCH 04/81] - remove erroneous, trailing comma at the end of the previously added gluOrtho2D function - fix my AUTHORS name Signed-off-by: Michael Riss --- AUTHORS | 2 +- src/library_gl.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 9399a4f8ccf4f..d4e80f3fba354 100644 --- a/AUTHORS +++ b/AUTHORS @@ -44,4 +44,4 @@ a license to everyone to use it as detailed in LICENSE.) * Dominic Wong * Alan Kligman (copyright owned by Mozilla Foundation) * Anthony Liot -* Michael Riß +* Michael Riss diff --git a/src/library_gl.js b/src/library_gl.js index f6793dc9d7e51..2a6ec92fb8698 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -2466,7 +2466,7 @@ var LibraryGL = { gluOrtho2D: function(left, right, bottom, top) { _glOrtho(left, right, bottom, top, -1, 1); - }, + } }; // Simple pass-through functions. Starred ones have return values. [X] ones have X in the C name but not in the JS name From cf98c88f01717d0d5b350f2f33293a421893b247 Mon Sep 17 00:00:00 2001 From: Martin von Gagern Date: Sat, 9 Feb 2013 01:18:02 +0100 Subject: [PATCH 05/81] Avoid some errors which are reported for LDC output of a simple program. --- src/parseTools.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parseTools.js b/src/parseTools.js index e081d0decaddb..a076c862e3e26 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -166,6 +166,7 @@ function getBits(type) { } if (isStructType(type)) { var typeData = Types.types[type]; + if (typeData === undefined) return 0; return typeData.flatSize*8; } return 0; @@ -577,7 +578,7 @@ function cleanOutTokens(filterOut, tokens, indexes) { if (typeof indexes !== 'object') indexes = [indexes]; for (var i = indexes.length-1; i >=0; i--) { var index = indexes[i]; - while (tokens[index].text in filterOut) { + while (index < tokens.length && tokens[index].text in filterOut) { tokens.splice(index, 1); } } From 608f5622ca10722e2597e1302d5aaea0568889a4 Mon Sep 17 00:00:00 2001 From: Martin von Gagern Date: Sat, 9 Feb 2013 02:34:39 +0100 Subject: [PATCH 06/81] Skip named metadata lines. --- src/modules.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules.js b/src/modules.js index 695abbe76e132..5b48b305759d5 100644 --- a/src/modules.js +++ b/src/modules.js @@ -90,6 +90,7 @@ var Debugging = { lines[i] = ';'; continue; } + if (line[0] == '!') skipLine = true; lines[i] = skipLine ? ';' : line; } From 85b34c5c91a6448a191709c2071125dfbc9716d9 Mon Sep 17 00:00:00 2001 From: Martin von Gagern Date: Wed, 6 Mar 2013 01:43:46 +0100 Subject: [PATCH 07/81] Adding myself to AUTHORS. --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index b1003dbd3b3f3..f0dcb43c363c9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -48,4 +48,4 @@ a license to everyone to use it as detailed in LICENSE.) * Jasper St. Pierre * Manuel Schölling * Bruce Mitchener, Jr. - +* Martin von Gagern From 654d4dd001de4a1c69c19ed16ac3a427423d179f Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Wed, 6 Mar 2013 17:25:59 +0700 Subject: [PATCH 08/81] -fcatch-undefined-behavior is deprecated. Use -fsanitize=undefined. --- tests/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index 5adafddd2891d..695cd23c548db 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -8743,7 +8743,7 @@ class Test { return 0; } ''') - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-fcatch-undefined-behavior']).communicate() + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-fsanitize=undefined']).communicate() self.assertContained('hello, world!', run_js(os.path.join(self.get_dir(), 'a.out.js'))) def test_unaligned_memory(self): From 4180b3ac7e779f7101791b3f9ca3860bc16e1e15 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 3 Feb 2013 11:59:53 +0100 Subject: [PATCH 09/81] Emit correct code for setjmp() calls when in UNALIGNED_MEMORY mode makeSetValue() returns multiple statements when in UNALIGNED_MEMORY mode and thus have to be separated by commas in this context. --- AUTHORS | 1 + src/library.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 296d4150b87a8..0741022f01cbd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -52,4 +52,5 @@ a license to everyone to use it as detailed in LICENSE.) * Roger Braun * Vladimir Vukicevic (copyright owned by Mozilla Foundation) * Lorant Pinter +* Tobias Doerffel diff --git a/src/library.js b/src/library.js index a5166c72cdc29..8220f78044a61 100644 --- a/src/library.js +++ b/src/library.js @@ -6188,7 +6188,7 @@ LibraryManager.library = { setjmp__inline: function(env) { // Save the label - return '(tempInt = setjmpId++, mySetjmpIds[tempInt] = 1, setjmpLabels[tempInt] = label,' + makeSetValue(env, '0', 'tempInt', 'i32') + ', 0)'; + return '(tempInt = setjmpId++, mySetjmpIds[tempInt] = 1, setjmpLabels[tempInt] = label,' + makeSetValue(env, '0', 'tempInt', 'i32', undefined, undefined, undefined, undefined, ',') + ', 0)'; }, longjmp: function(env, value) { From a094e001caf56feae979d259e746bf1c0f4c0d46 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Thu, 7 Mar 2013 14:09:40 -0500 Subject: [PATCH 10/81] Fix debug prints in tools/cache.py --- tools/cache.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/cache.py b/tools/cache.py index e7908fba1e508..13a53fe901ba3 100644 --- a/tools/cache.py +++ b/tools/cache.py @@ -73,7 +73,8 @@ def get(self, shortkey, keys): try: data = cPickle.loads(zlib.decompress(open(cachename).read())) except Exception, e: - if DEBUG_CACHE: print >> sys.stderr, 'jcache decompress/unpickle error:', e + if self.debug: print >> sys.stderr, 'jcache decompress/unpickle error:', e + return if len(data) != 2: if self.debug: print >> sys.stderr, 'jcache error in get' return @@ -96,7 +97,7 @@ def set(self, shortkey, keys, value): f.write(zlib.compress(cPickle.dumps([keys, value]))) f.close() except Exception, e: - if DEBUG_CACHE: print >> sys.stderr, 'jcache compress/pickle error:', e + if self.debug: print >> sys.stderr, 'jcache compress/pickle error:', e return # for i in range(len(keys)): # open(cachename + '.key' + str(i), 'w').write(keys[i]) From 0e074d8e6690bc4a6f6ed869bca1c0fbb5091682 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 11:39:09 -0800 Subject: [PATCH 11/81] gl whitespace cleanup --- src/library_gl.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 4977d2e9fd5e0..ce5da3d4e02b3 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -211,11 +211,11 @@ var LibraryGL = { GL.resetBufferBinding = false; for (var i = 0; i < GL.maxVertexAttribs; ++i) { if (!GL.enabledClientBuffers[i] || !GL.clientBuffers[i]) continue; - + GL.resetBufferBinding = true; - + var cb = GL.clientBuffers[i]; - + var buf = Module.ctx.createBuffer(); Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, buf); Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, From c5172f9b41103c195260b4de96cba6b119b924c2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 11:40:30 -0800 Subject: [PATCH 12/81] gl comments --- src/library_gl.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/library_gl.js b/src/library_gl.js index ce5da3d4e02b3..e9ac76cfef211 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -2849,6 +2849,8 @@ var LibraryGL = { glShadeModel: function() { Runtime.warnOnce('TODO: glShadeModel') }, + // GLES2 emulation + glVertexAttribPointer__sig: 'viiiiii', glVertexAttribPointer: function(index, size, type, normalized, stride, ptr) { #if FULL_ES2 @@ -2921,11 +2923,13 @@ var LibraryGL = { }, // signatures of simple pass-through functions, see later + glActiveTexture__sig: 'vi', glCheckFramebufferStatus__sig: 'ii', glRenderbufferStorage__sig: 'viiii', // Open GLES1.1 compatibility + glGenFramebuffersOES : 'glGenFramebuffers', glGenRenderbuffersOES : 'glGenRenderbuffers', glBindFramebufferOES : 'glBindFramebuffer', From bb5e246ad4cf178a05960ac577de7359a2f6257a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 12:43:29 -0800 Subject: [PATCH 13/81] fix FULL_ES2 bug with not taking into account 'first' in glDrawArrays --- src/library_gl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library_gl.js b/src/library_gl.js index e9ac76cfef211..5aabc1065c522 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -2883,7 +2883,7 @@ var LibraryGL = { glDrawArrays: function(mode, first, count) { #if FULL_ES2 // bind any client-side buffers - GL.preDrawHandleClientVertexAttribBindings(count); + GL.preDrawHandleClientVertexAttribBindings(first + count); #endif Module.ctx.drawArrays(mode, first, count); From 1a06c9d75566fc3d0cf10f94cfc274e9728b3501 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 12:46:11 -0800 Subject: [PATCH 14/81] add test for animation in FULL_ES2 --- tests/hello_world_gles_full.c | 742 ++++++++++++++++++++++++++++++++++ tests/runner.py | 20 +- 2 files changed, 754 insertions(+), 8 deletions(-) create mode 100644 tests/hello_world_gles_full.c diff --git a/tests/hello_world_gles_full.c b/tests/hello_world_gles_full.c new file mode 100644 index 0000000000000..cca6650601b25 --- /dev/null +++ b/tests/hello_world_gles_full.c @@ -0,0 +1,742 @@ +/* + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Ported to GLES2. + * Kristian Høgsberg + * May 3, 2010 + * + * Improve GLES2 port: + * * Refactor gear drawing. + * * Use correct normals for surfaces. + * * Improve shader. + * * Use perspective projection transformation. + * * Add FPS count. + * * Add comments. + * Alexandros Frantzis + * Jul 13, 2010 + */ + +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#define STRIPS_PER_TOOTH 7 +#define VERTICES_PER_TOOTH 34 +#define GEAR_VERTEX_STRIDE 6 + +#ifndef HAVE_BUILTIN_SINCOS +#define sincos _sincos +static void +sincos (double a, double *s, double *c) +{ + *s = sin (a); + *c = cos (a); +} +#endif + +/** + * Struct describing the vertices in triangle strip + */ +struct vertex_strip { + /** The first vertex in the strip */ + GLint first; + /** The number of consecutive vertices in the strip after the first */ + GLint count; +}; + +/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */ +typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE]; + +/** + * Struct representing a gear. + */ +struct gear { + /** The array of vertices comprising the gear */ + GearVertex *vertices; + /** The number of vertices comprising the gear */ + int nvertices; + /** The array of triangle strips comprising the gear */ + struct vertex_strip *strips; + /** The number of triangle strips comprising the gear */ + int nstrips; + /** The Vertex Buffer Object holding the vertices in the graphics card */ + GLuint vbo; +}; + +/** The view rotation [x, y, z] */ +static GLfloat view_rot[3] = { 20.0, 30.0, 0.0 }; +/** The gears */ +static struct gear *gear1, *gear2, *gear3; +/** The current gear rotation angle */ +static GLfloat angle = 0.0; +/** The location of the shader uniforms */ +static GLuint ModelViewProjectionMatrix_location, + NormalMatrix_location, + LightSourcePosition_location, + MaterialColor_location; +/** The projection matrix */ +static GLfloat ProjectionMatrix[16]; +/** The direction of the directional light for the scene */ +static const GLfloat LightSourcePosition[4] = { 5.0, 5.0, 10.0, 1.0}; + +/** + * Fills a gear vertex. + * + * @param v the vertex to fill + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coortinate + * @param n pointer to the normal table + * + * @return the operation error code + */ +static GearVertex * +vert(GearVertex *v, GLfloat x, GLfloat y, GLfloat z, GLfloat n[3]) +{ + v[0][0] = x; + v[0][1] = y; + v[0][2] = z; + v[0][3] = n[0]; + v[0][4] = n[1]; + v[0][5] = n[2]; + + return v + 1; +} + +/** + * Create a gear wheel. + * + * @param inner_radius radius of hole at center + * @param outer_radius radius at center of teeth + * @param width width of gear + * @param teeth number of teeth + * @param tooth_depth depth of tooth + * + * @return pointer to the constructed struct gear + */ +static struct gear * +create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, + GLint teeth, GLfloat tooth_depth) +{ + GLfloat r0, r1, r2; + GLfloat da; + GearVertex *v; + struct gear *gear; + double s[5], c[5]; + GLfloat normal[3]; + int cur_strip = 0; + int i; + + /* Allocate memory for the gear */ + gear = malloc(sizeof *gear); + if (gear == NULL) + return NULL; + + /* Calculate the radii used in the gear */ + r0 = inner_radius; + r1 = outer_radius - tooth_depth / 2.0; + r2 = outer_radius + tooth_depth / 2.0; + + da = 2.0 * M_PI / teeth / 4.0; + + /* Allocate memory for the triangle strip information */ + gear->nstrips = STRIPS_PER_TOOTH * teeth; + gear->strips = calloc(gear->nstrips, sizeof (*gear->strips)); + + /* Allocate memory for the vertices */ + gear->vertices = calloc(VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices)); + v = gear->vertices; + + for (i = 0; i < teeth; i++) { + /* Calculate needed sin/cos for varius angles */ + sincos(i * 2.0 * M_PI / teeth, &s[0], &c[0]); + sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]); + sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]); + sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]); + sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]); + + /* A set of macros for making the creation of the gears easier */ +#define GEAR_POINT(r, da) { (r) * c[(da)], (r) * s[(da)] } +#define SET_NORMAL(x, y, z) do { \ + normal[0] = (x); normal[1] = (y); normal[2] = (z); \ +} while(0) + +#define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal) + +#define START_STRIP do { \ + gear->strips[cur_strip].first = v - gear->vertices; \ +} while(0); + +#define END_STRIP do { \ + int _tmp = (v - gear->vertices); \ + gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \ + cur_strip++; \ +} while (0) + +#define QUAD_WITH_NORMAL(p1, p2) do { \ + SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0); \ + v = GEAR_VERT(v, (p1), -1); \ + v = GEAR_VERT(v, (p1), 1); \ + v = GEAR_VERT(v, (p2), -1); \ + v = GEAR_VERT(v, (p2), 1); \ +} while(0) + + struct point { + GLfloat x; + GLfloat y; + }; + + /* Create the 7 points (only x,y coords) used to draw a tooth */ + struct point p[7] = { + GEAR_POINT(r2, 1), // 0 + GEAR_POINT(r2, 2), // 1 + GEAR_POINT(r1, 0), // 2 + GEAR_POINT(r1, 3), // 3 + GEAR_POINT(r0, 0), // 4 + GEAR_POINT(r1, 4), // 5 + GEAR_POINT(r0, 4), // 6 + }; + + /* Front face */ + START_STRIP; + SET_NORMAL(0, 0, 1.0); + v = GEAR_VERT(v, 0, +1); + v = GEAR_VERT(v, 1, +1); + v = GEAR_VERT(v, 2, +1); + v = GEAR_VERT(v, 3, +1); + v = GEAR_VERT(v, 4, +1); + v = GEAR_VERT(v, 5, +1); + v = GEAR_VERT(v, 6, +1); + END_STRIP; + + /* Inner face */ + START_STRIP; + QUAD_WITH_NORMAL(4, 6); + END_STRIP; + + /* Back face */ + START_STRIP; + SET_NORMAL(0, 0, -1.0); + v = GEAR_VERT(v, 6, -1); + v = GEAR_VERT(v, 5, -1); + v = GEAR_VERT(v, 4, -1); + v = GEAR_VERT(v, 3, -1); + v = GEAR_VERT(v, 2, -1); + v = GEAR_VERT(v, 1, -1); + v = GEAR_VERT(v, 0, -1); + END_STRIP; + + /* Outer face */ + START_STRIP; + QUAD_WITH_NORMAL(0, 2); + END_STRIP; + + START_STRIP; + QUAD_WITH_NORMAL(1, 0); + END_STRIP; + + START_STRIP; + QUAD_WITH_NORMAL(3, 1); + END_STRIP; + + START_STRIP; + QUAD_WITH_NORMAL(5, 3); + END_STRIP; + } + + gear->nvertices = (v - gear->vertices); + + /* Store the vertices in a vertex buffer object (VBO) */ + glGenBuffers(1, &gear->vbo); + glBindBuffer(GL_ARRAY_BUFFER, gear->vbo); + glBufferData(GL_ARRAY_BUFFER, gear->nvertices * sizeof(GearVertex), + gear->vertices, GL_STATIC_DRAW); + + return gear; +} + +/** + * Multiplies two 4x4 matrices. + * + * The result is stored in matrix m. + * + * @param m the first matrix to multiply + * @param n the second matrix to multiply + */ +static void +multiply(GLfloat *m, const GLfloat *n) +{ + GLfloat tmp[16]; + const GLfloat *row, *column; + div_t d; + int i, j; + + for (i = 0; i < 16; i++) { + tmp[i] = 0; + d = div(i, 4); + row = n + d.quot * 4; + column = m + d.rem; + for (j = 0; j < 4; j++) + tmp[i] += row[j] * column[j * 4]; + } + memcpy(m, &tmp, sizeof tmp); +} + +/** + * Rotates a 4x4 matrix. + * + * @param[in,out] m the matrix to rotate + * @param angle the angle to rotate + * @param x the x component of the direction to rotate to + * @param y the y component of the direction to rotate to + * @param z the z component of the direction to rotate to + */ +static void +rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + double s, c; + + sincos(angle, &s, &c); + GLfloat r[16] = { + x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0, + x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0, + x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0, + 0, 0, 0, 1 + }; + + multiply(m, r); +} + + +/** + * Translates a 4x4 matrix. + * + * @param[in,out] m the matrix to translate + * @param x the x component of the direction to translate to + * @param y the y component of the direction to translate to + * @param z the z component of the direction to translate to + */ +static void +translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }; + + multiply(m, t); +} + +/** + * Creates an identity 4x4 matrix. + * + * @param m the matrix make an identity matrix + */ +static void +identity(GLfloat *m) +{ + GLfloat t[16] = { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + }; + + memcpy(m, t, sizeof(t)); +} + +/** + * Transposes a 4x4 matrix. + * + * @param m the matrix to transpose + */ +static void +transpose(GLfloat *m) +{ + GLfloat t[16] = { + m[0], m[4], m[8], m[12], + m[1], m[5], m[9], m[13], + m[2], m[6], m[10], m[14], + m[3], m[7], m[11], m[15]}; + + memcpy(m, t, sizeof(t)); +} + +/** + * Inverts a 4x4 matrix. + * + * This function can currently handle only pure translation-rotation matrices. + * Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118 + * for an explanation. + */ +static void +invert(GLfloat *m) +{ + GLfloat t[16]; + identity(t); + + // Extract and invert the translation part 't'. The inverse of a + // translation matrix can be calculated by negating the translation + // coordinates. + t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14]; + + // Invert the rotation part 'r'. The inverse of a rotation matrix is + // equal to its transpose. + m[12] = m[13] = m[14] = 0; + transpose(m); + + // inv(m) = inv(r) * inv(t) + multiply(m, t); +} + +/** + * Calculate a perspective projection transformation. + * + * @param m the matrix to save the transformation in + * @param fovy the field of view in the y direction + * @param aspect the view aspect ratio + * @param zNear the near clipping plane + * @param zFar the far clipping plane + */ +void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) +{ + GLfloat tmp[16]; + identity(tmp); + + double sine, cosine, cotangent, deltaZ; + GLfloat radians = fovy / 2 * M_PI / 180; + + deltaZ = zFar - zNear; + sincos(radians, &sine, &cosine); + + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) + return; + + cotangent = cosine / sine; + + tmp[0] = cotangent / aspect; + tmp[5] = cotangent; + tmp[10] = -(zFar + zNear) / deltaZ; + tmp[11] = -1; + tmp[14] = -2 * zNear * zFar / deltaZ; + tmp[15] = 0; + + memcpy(m, tmp, sizeof(tmp)); +} + +/** + * Draws a gear. + * + * @param gear the gear to draw + * @param transform the current transformation matrix + * @param x the x position to draw the gear at + * @param y the y position to draw the gear at + * @param angle the rotation angle of the gear + * @param color the color of the gear + */ +static void +draw_gear(struct gear *gear, GLfloat *transform, + GLfloat x, GLfloat y, GLfloat angle, const GLfloat color[4]) +{ + GLfloat model_view[16]; + GLfloat normal_matrix[16]; + GLfloat model_view_projection[16]; + + /* Translate and rotate the gear */ + memcpy(model_view, transform, sizeof (model_view)); + translate(model_view, x, y, 0); + rotate(model_view, 2 * M_PI * angle / 360.0, 0, 0, 1); + + /* Create and set the ModelViewProjectionMatrix */ + memcpy(model_view_projection, ProjectionMatrix, sizeof(model_view_projection)); + multiply(model_view_projection, model_view); + + glUniformMatrix4fv(ModelViewProjectionMatrix_location, 1, GL_FALSE, + model_view_projection); + + /* + * Create and set the NormalMatrix. It's the inverse transpose of the + * ModelView matrix. + */ + memcpy(normal_matrix, model_view, sizeof (normal_matrix)); + invert(normal_matrix); + transpose(normal_matrix); + glUniformMatrix4fv(NormalMatrix_location, 1, GL_FALSE, normal_matrix); + + /* Set the gear color */ + glUniform4fv(MaterialColor_location, 1, color); + + /* Set the vertex buffer object to use */ + glBindBuffer(GL_ARRAY_BUFFER, 0); + + /* Set up the position of the attributes in the vertex buffer object */ + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, + 6 * sizeof(GLfloat), *gear->vertices); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, + 6 * sizeof(GLfloat), ((float*)*gear->vertices) + 3*4); + /* Enable the attributes */ + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + + /* Draw the triangle strips that comprise the gear */ + int n; + for (n = 0; n < gear->nstrips; n++) + glDrawArrays(GL_TRIANGLE_STRIP, gear->strips[n].first, gear->strips[n].count); + + /* Disable the attributes */ + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(0); +} + +/** + * Draws the gears. + */ +static void +gears_draw(void) +{ + const static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; + const static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; + const static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; + GLfloat transform[16]; + identity(transform); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* Translate and rotate the view */ + translate(transform, 0, 0, -20); + rotate(transform, 2 * M_PI * view_rot[0] / 360.0, 1, 0, 0); + rotate(transform, 2 * M_PI * view_rot[1] / 360.0, 0, 1, 0); + rotate(transform, 2 * M_PI * view_rot[2] / 360.0, 0, 0, 1); + + /* Draw the gears */ + draw_gear(gear1, transform, -3.0, -2.0, angle, red); + draw_gear(gear2, transform, 3.1, -2.0, -2 * angle - 9.0, green); + draw_gear(gear3, transform, -3.1, 4.2, -2 * angle - 25.0, blue); + + glutSwapBuffers(); +} + +/** + * Handles a new window size or exposure. + * + * @param width the window width + * @param height the window height + */ +static void +gears_reshape(int width, int height) +{ + /* Update the projection matrix */ + perspective(ProjectionMatrix, 60.0, width / (float)height, 1.0, 1024.0); + + /* Set the viewport */ + glViewport(0, 0, (GLint) width, (GLint) height); +} + +/** + * Handles special glut events. + * + * @param special the event to handle. + */ +static void +gears_special(int special, int crap, int morecrap) +{ + switch (special) { + case GLUT_KEY_LEFT: + view_rot[1] += 5.0; + break; + case GLUT_KEY_RIGHT: + view_rot[1] -= 5.0; + break; + case GLUT_KEY_UP: + view_rot[0] += 5.0; + break; + case GLUT_KEY_DOWN: + view_rot[0] -= 5.0; + break; + case GLUT_KEY_F11: + glutFullScreen(); + break; + } +} + +static void +gears_idle(void) +{ + static int frames = 0; + static double tRot0 = -1.0, tRate0 = -1.0; + double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; + + if (tRot0 < 0.0) + tRot0 = t; + dt = t - tRot0; + tRot0 = t; + + /* advance rotation for next frame */ + angle += 70.0 * dt; /* 70 degrees per second */ + if (angle > 3600.0) + angle -= 3600.0; + + glutPostRedisplay(); + frames++; + + if (tRate0 < 0.0) + tRate0 = t; + if (t - tRate0 >= 5.0) { + GLfloat seconds = t - tRate0; + GLfloat fps = frames / seconds; + printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, + fps); + tRate0 = t; + frames = 0; + } +} + +static const char vertex_shader[] = +"attribute vec3 position;\n" +"attribute vec3 normal;\n" +"\n" +"uniform mat4 ModelViewProjectionMatrix;\n" +"uniform mat4 NormalMatrix;\n" +"uniform vec4 LightSourcePosition;\n" +"uniform vec4 MaterialColor;\n" +"\n" +"varying vec4 Color;\n" +"\n" +"void main(void)\n" +"{\n" +" // Transform the normal to eye coordinates\n" +" vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n" +"\n" +" // The LightSourcePosition is actually its direction for directional light\n" +" vec3 L = normalize(LightSourcePosition.xyz);\n" +"\n" +" // Multiply the diffuse value by the vertex color (which is fixed in this case)\n" +" // to get the actual color that we will use to draw this vertex with\n" +" float diffuse = max(dot(N, L), 0.0);\n" +" Color = diffuse * MaterialColor;\n" +"\n" +" // Transform the position to clip coordinates\n" +" gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n" +"}"; + +static const char fragment_shader[] = +"#ifdef GL_ES\n" +"precision mediump float;\n" +"#endif\n" +"varying vec4 Color;\n" +"\n" +"void main(void)\n" +"{\n" +" gl_FragColor = Color;\n" +"}"; + +static void +gears_init(void) +{ + GLuint v, f, program; + const char *p; + char msg[512]; + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + /* Compile the vertex shader */ + p = vertex_shader; + v = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(v, 1, &p, NULL); + glCompileShader(v); + glGetShaderInfoLog(v, sizeof msg, NULL, msg); + printf("vertex shader info: %s\n", msg); + + /* Compile the fragment shader */ + p = fragment_shader; + f = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(f, 1, &p, NULL); + glCompileShader(f); + glGetShaderInfoLog(f, sizeof msg, NULL, msg); + printf("fragment shader info: %s\n", msg); + + /* Create and link the shader program */ + program = glCreateProgram(); + glAttachShader(program, v); + glAttachShader(program, f); + glBindAttribLocation(program, 0, "position"); + glBindAttribLocation(program, 1, "normal"); + + glLinkProgram(program); + glGetProgramInfoLog(program, sizeof msg, NULL, msg); + printf("info: %s\n", msg); + + /* Enable the shaders */ + glUseProgram(program); + + /* Get the locations of the uniforms so we can access them */ + ModelViewProjectionMatrix_location = glGetUniformLocation(program, "ModelViewProjectionMatrix"); + NormalMatrix_location = glGetUniformLocation(program, "NormalMatrix"); + LightSourcePosition_location = glGetUniformLocation(program, "LightSourcePosition"); + MaterialColor_location = glGetUniformLocation(program, "MaterialColor"); + + /* Set the LightSourcePosition uniform which is constant throught the program */ + glUniform4fv(LightSourcePosition_location, 1, LightSourcePosition); + + /* make the gears */ + gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7); + gear2 = create_gear(0.5, 2.0, 2.0, 10, 0.7); + gear3 = create_gear(1.3, 2.0, 0.5, 10, 0.7); +} + +int +main(int argc, char *argv[]) +{ + /* Initialize the window */ + glutInit(&argc, argv); + glutInitWindowSize(300, 300); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); + + glutCreateWindow("es2gears"); + + /* Set up glut callback functions */ + glutIdleFunc (gears_idle); + glutReshapeFunc(gears_reshape); + glutDisplayFunc(gears_draw); + glutSpecialFunc(gears_special); + + /* Initialize the gears */ + gears_init(); + + glutMainLoop(); + + return 0; +} diff --git a/tests/runner.py b/tests/runner.py index 7e3c73b0bbe91..e70664010a2fc 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -10837,14 +10837,18 @@ def test_glgears(self): self.run_browser('something.html', 'You should see animating gears.', '/report_result?0') def test_glgears_animation(self): - for emulation in [0, 1]: - print emulation - Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html', - '-DHAVE_BUILTIN_SINCOS', '-s', 'GL_TESTING=1', - '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')] + - (['-s', 'FORCE_GL_EMULATION=1'] if emulation else [])).communicate() - self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true') - assert ('var GLEmulation' in open(self.in_dir('something.html')).read()) == emulation, "emulation code should be added when asked for" + for full_es2 in [0, 1]: + for emulation in [0, 1]: + if full_es2 and emulation: continue + print full_es2, emulation + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles%s.c' % ('' if not full_es2 else '_full')), '-o', 'something.html', + '-DHAVE_BUILTIN_SINCOS', '-s', 'GL_TESTING=1', + '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')] + + (['-s', 'FORCE_GL_EMULATION=1'] if emulation else []) + + (['-s', 'FULL_ES2=1'] if full_es2 else []), + ).communicate() + self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true') + assert ('var GLEmulation' in open(self.in_dir('something.html')).read()) == emulation, "emulation code should be added when asked for" def test_glgears_bad(self): # Make sure that OpenGL ES is not available if typed arrays are not used From d56cfae83a486f4bdb70c48c56bf053e33e1a778 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 12:49:02 -0800 Subject: [PATCH 15/81] optimize out creation of new JS objects in each glVertexAttribPointer call in FULL_ES2 --- src/library_gl.js | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 5aabc1065c522..6ba42a3839a06 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -21,7 +21,6 @@ var LibraryGL = { #if FULL_ES2 clientBuffers: [], - enabledClientBuffers: [], #endif currArrayBuffer: 0, currElementArrayBuffer: 0, @@ -210,12 +209,11 @@ var LibraryGL = { preDrawHandleClientVertexAttribBindings: function(count) { GL.resetBufferBinding = false; for (var i = 0; i < GL.maxVertexAttribs; ++i) { - if (!GL.enabledClientBuffers[i] || !GL.clientBuffers[i]) continue; + var cb = GL.clientBuffers[i]; + if (!cb.enabled) continue; GL.resetBufferBinding = true; - var cb = GL.clientBuffers[i]; - var buf = Module.ctx.createBuffer(); Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, buf); Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, @@ -239,6 +237,11 @@ var LibraryGL = { if (!Module.useWebGL) return; // an app might link both gl and 2d backends GL.maxVertexAttribs = Module.ctx.getParameter(Module.ctx.MAX_VERTEX_ATTRIBS); +#if FULL_ES2 + for (var i = 0; i < GL.maxVertexAttribs; i++) { + GL.clientBuffers[i] = { enabled: false, size: 0, type: 0, normalized: 0, stride: 0, ptr: 0 }; + } +#endif GL.compressionExt = Module.ctx.getExtension('WEBGL_compressed_texture_s3tc') || Module.ctx.getExtension('MOZ_WEBGL_compressed_texture_s3tc') || @@ -612,7 +615,7 @@ var LibraryGL = { glGetVertexAttribfv: function(index, pname, params) { #if FULL_ES2 - if (GL.clientBuffers[index]) { + if (GL.clientBuffers[index].enabled) { Module.printErr("glGetVertexAttribfv on client-side array: not supported, bad data returned"); } #endif @@ -628,7 +631,7 @@ var LibraryGL = { glGetVertexAttribiv: function(index, pname, params) { #if FULL_ES2 - if (GL.clientBuffers[index]) { + if (GL.clientBuffers[index].enabled) { Module.printErr("glGetVertexAttribiv on client-side array: not supported, bad data returned"); } #endif @@ -644,7 +647,7 @@ var LibraryGL = { glGetVertexAttribPointerv: function(index, pname, pointer) { #if FULL_ES2 - if (GL.clientBuffers[index]) { + if (GL.clientBuffers[index].enabled) { Module.printErr("glGetVertexAttribPointer on client-side array: not supported, bad data returned"); } #endif @@ -2854,12 +2857,19 @@ var LibraryGL = { glVertexAttribPointer__sig: 'viiiiii', glVertexAttribPointer: function(index, size, type, normalized, stride, ptr) { #if FULL_ES2 + var cb = GL.clientBuffers[index]; +#if ASSERTIONS + assert(cb, index); +#endif if (!GL.currArrayBuffer) { - GL.clientBuffers[index] = { size: size, type: type, normalized: normalized, stride: stride, ptr: ptr }; + cb.size = size; + cb.type = type; + cb.normalized = normalized; + cb.stride = stride; + cb.ptr = ptr; return; } - - GL.clientBuffers[index] = null; + cb.enabled = false; #endif Module.ctx.vertexAttribPointer(index, size, type, normalized, stride, ptr); }, @@ -2867,7 +2877,11 @@ var LibraryGL = { glEnableVertexAttribArray__sig: 'vi', glEnableVertexAttribArray: function(index) { #if FULL_ES2 - GL.enabledClientBuffers[index] = true; + var cb = GL.clientBuffers[index]; +#if ASSERTIONS + assert(cb, index); +#endif + cb.enabled = true; #endif Module.ctx.enableVertexAttribArray(index); }, @@ -2875,7 +2889,11 @@ var LibraryGL = { glDisableVertexAttribArray__sig: 'vi', glDisableVertexAttribArray: function(index) { #if FULL_ES2 - GL.enabledClientBuffers[index] = false; + var cb = GL.clientBuffers[index]; +#if ASSERTIONS + assert(cb, index); +#endif + cb.enabled = false; #endif Module.ctx.disableVertexAttribArray(index); }, From be863c59c1f682b35e181f46a80a7689ddd13f30 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 15:08:50 -0800 Subject: [PATCH 16/81] refactor gl temporary buffer code --- src/library_gl.js | 140 ++++++++++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 68 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 6ba42a3839a06..12ec0a12fa5bd 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -58,6 +58,65 @@ var LibraryGL = { return ret; }, + // Temporary buffers + MAX_TEMP_BUFFER_SIZE: {{{ GL_MAX_TEMP_BUFFER_SIZE }}}, + tempBufferIndexLookup: null, + tempVertexBuffers: null, + tempIndexBuffers: null, + tempQuadIndexBuffer: null, + + generateTempBuffers: function(quads) { + this.tempBufferIndexLookup = new Uint8Array(this.MAX_TEMP_BUFFER_SIZE+1); + this.tempVertexBuffers = []; + this.tempIndexBuffers = []; + var last = -1, curr = -1; + var size = 1; + for (var i = 0; i <= this.MAX_TEMP_BUFFER_SIZE; i++) { + if (i > size) { + size <<= 1; + } + if (size != last) { + curr++; + this.tempVertexBuffers[curr] = Module.ctx.createBuffer(); + Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.tempVertexBuffers[curr]); + Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW); + Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null); + this.tempIndexBuffers[curr] = Module.ctx.createBuffer(); + Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempIndexBuffers[curr]); + Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW); + Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null); + last = size; + } + this.tempBufferIndexLookup[i] = curr; + } + + if (quads) { + // GL_QUAD indexes can be precalculated + this.tempQuadIndexBuffer = Module.ctx.createBuffer(); + Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempQuadIndexBuffer); + var numIndexes = this.MAX_TEMP_BUFFER_SIZE >> 1; + var quadIndexes = new Uint16Array(numIndexes); + var i = 0, v = 0; + while (1) { + quadIndexes[i++] = v; + if (i >= numIndexes) break; + quadIndexes[i++] = v+1; + if (i >= numIndexes) break; + quadIndexes[i++] = v+2; + if (i >= numIndexes) break; + quadIndexes[i++] = v; + if (i >= numIndexes) break; + quadIndexes[i++] = v+2; + if (i >= numIndexes) break; + quadIndexes[i++] = v+3; + if (i >= numIndexes) break; + v += 4; + } + Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, quadIndexes, Module.ctx.STATIC_DRAW); + Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null); + } + }, + // Linear lookup in one of the tables (buffers, programs, etc.). TODO: consider using a weakmap to make this faster, if it matters scan: function(table, object) { for (var item in table) { @@ -208,6 +267,7 @@ var LibraryGL = { preDrawHandleClientVertexAttribBindings: function(count) { GL.resetBufferBinding = false; + for (var i = 0; i < GL.maxVertexAttribs; ++i) { var cb = GL.clientBuffers[i]; if (!cb.enabled) continue; @@ -1696,62 +1756,6 @@ var LibraryGL = { this.modifiedClientAttributes = true; }, - // Temporary buffers - MAX_TEMP_BUFFER_SIZE: {{{ GL_MAX_TEMP_BUFFER_SIZE }}}, - tempBufferIndexLookup: null, - tempVertexBuffers: null, - tempIndexBuffers: null, - tempQuadIndexBuffer: null, - - generateTempBuffers: function() { - this.tempBufferIndexLookup = new Uint8Array(this.MAX_TEMP_BUFFER_SIZE+1); - this.tempVertexBuffers = []; - this.tempIndexBuffers = []; - var last = -1, curr = -1; - var size = 1; - for (var i = 0; i <= this.MAX_TEMP_BUFFER_SIZE; i++) { - if (i > size) { - size <<= 1; - } - if (size != last) { - curr++; - this.tempVertexBuffers[curr] = Module.ctx.createBuffer(); - Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.tempVertexBuffers[curr]); - Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW); - Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null); - this.tempIndexBuffers[curr] = Module.ctx.createBuffer(); - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempIndexBuffers[curr]); - Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW); - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null); - last = size; - } - this.tempBufferIndexLookup[i] = curr; - } - // GL_QUAD indexes can be precalculated - this.tempQuadIndexBuffer = Module.ctx.createBuffer(); - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempQuadIndexBuffer); - var numIndexes = this.MAX_TEMP_BUFFER_SIZE >> 1; - var quadIndexes = new Uint16Array(numIndexes); - var i = 0, v = 0; - while (1) { - quadIndexes[i++] = v; - if (i >= numIndexes) break; - quadIndexes[i++] = v+1; - if (i >= numIndexes) break; - quadIndexes[i++] = v+2; - if (i >= numIndexes) break; - quadIndexes[i++] = v; - if (i >= numIndexes) break; - quadIndexes[i++] = v+2; - if (i >= numIndexes) break; - quadIndexes[i++] = v+3; - if (i >= numIndexes) break; - v += 4; - } - Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, quadIndexes, Module.ctx.STATIC_DRAW); - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null); - }, - // Renderers addRendererComponent: function(name, size, type) { if (!this.rendererComponents[name]) { @@ -1972,8 +1976,8 @@ var LibraryGL = { if (!GL.currArrayBuffer) { var start = GL.immediate.firstVertex*GL.immediate.stride; var end = GL.immediate.lastVertex*GL.immediate.stride; - assert(end <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too much vertex data'); - arrayBuffer = GL.immediate.tempVertexBuffers[GL.immediate.tempBufferIndexLookup[end]]; + assert(end <= GL.MAX_TEMP_BUFFER_SIZE, 'too much vertex data'); + arrayBuffer = GL.tempVertexBuffers[GL.tempBufferIndexLookup[end]]; // TODO: consider using the last buffer we bound, if it was larger. downside is larger buffer, but we might avoid rebinding and preparing } else { arrayBuffer = GL.currArrayBuffer; @@ -2164,12 +2168,12 @@ var LibraryGL = { this.rendererCache = this.rendererCacheItemTemplate.slice(); // Buffers for data - this.tempData = new Float32Array(this.MAX_TEMP_BUFFER_SIZE >> 2); - this.indexData = new Uint16Array(this.MAX_TEMP_BUFFER_SIZE >> 1); + this.tempData = new Float32Array(GL.MAX_TEMP_BUFFER_SIZE >> 2); + this.indexData = new Uint16Array(GL.MAX_TEMP_BUFFER_SIZE >> 1); this.vertexDataU8 = new Uint8Array(this.tempData.buffer); - this.generateTempBuffers(); + GL.generateTempBuffers(true); this.clientColor = new Float32Array([1, 1, 1, 1]); }, @@ -2212,7 +2216,7 @@ var LibraryGL = { #if ASSERTIONS Runtime.warnOnce('Unpacking/restriding attributes, this is not fast'); #endif - if (!GL.immediate.restrideBuffer) GL.immediate.restrideBuffer = _malloc(GL.immediate.MAX_TEMP_BUFFER_SIZE); + if (!GL.immediate.restrideBuffer) GL.immediate.restrideBuffer = _malloc(GL.MAX_TEMP_BUFFER_SIZE); start = GL.immediate.restrideBuffer; #if ASSERTIONS assert(start % 4 == 0); @@ -2227,7 +2231,7 @@ var LibraryGL = { bytes += size; } #if ASSERTIONS - assert(count*bytes <= GL.immediate.MAX_TEMP_BUFFER_SIZE); + assert(count*bytes <= GL.MAX_TEMP_BUFFER_SIZE); #endif // copy out the data (we need to know the stride for that, and define attribute.pointer for (var i = 0; i < attributes.length; i++) { @@ -2301,8 +2305,8 @@ var LibraryGL = { } if (!GL.currElementArrayBuffer) { // If no element array buffer is bound, then indices is a literal pointer to clientside data - assert(numProvidedIndexes << 1 <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (a)'); - var indexBuffer = GL.immediate.tempIndexBuffers[GL.immediate.tempBufferIndexLookup[numProvidedIndexes << 1]]; + assert(numProvidedIndexes << 1 <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (a)'); + var indexBuffer = GL.tempIndexBuffers[GL.tempBufferIndexLookup[numProvidedIndexes << 1]]; Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, indexBuffer); Module.ctx.bufferSubData(Module.ctx.ELEMENT_ARRAY_BUFFER, 0, {{{ makeHEAPView('U16', 'ptr', 'ptr + (numProvidedIndexes << 1)') }}}); ptr = 0; @@ -2317,8 +2321,8 @@ var LibraryGL = { ptr = GL.immediate.firstVertex*3; var numQuads = numVertexes / 4; numIndexes = numQuads * 6; // 0 1 2, 0 2 3 pattern - assert(ptr + (numIndexes << 1) <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (b)'); - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempQuadIndexBuffer); + assert(ptr + (numIndexes << 1) <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (b)'); + Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, GL.tempQuadIndexBuffer); emulatedElementArrayBuffer = true; } @@ -2372,7 +2376,7 @@ var LibraryGL = { GL.immediate.vertexData[GL.immediate.vertexCounter++] = y; GL.immediate.vertexData[GL.immediate.vertexCounter++] = z || 0; #if ASSERTIONS - assert(GL.immediate.vertexCounter << 2 < GL.immediate.MAX_TEMP_BUFFER_SIZE); + assert(GL.immediate.vertexCounter << 2 < GL.MAX_TEMP_BUFFER_SIZE); #endif GL.immediate.addRendererComponent(GL.immediate.VERTEX, 3, Module.ctx.FLOAT); }, From 1951e2b8039e5744567059ce58050bf8201df2c2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 15:19:35 -0800 Subject: [PATCH 17/81] use temp buffers in FULL_ES2 array buffers --- src/library_gl.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 12ec0a12fa5bd..84bb10d9509e0 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -265,19 +265,33 @@ var LibraryGL = { return size * typeSize * count; }, + usedTempBuffers: [], + preDrawHandleClientVertexAttribBindings: function(count) { GL.resetBufferBinding = false; + var used = GL.usedTempBuffers; + used.length = 0; + for (var i = 0; i < GL.maxVertexAttribs; ++i) { var cb = GL.clientBuffers[i]; if (!cb.enabled) continue; GL.resetBufferBinding = true; - var buf = Module.ctx.createBuffer(); + var size = GL.calcBufLength(cb.size, cb.type, cb.stride, count); + var index = GL.tempBufferIndexLookup[size]; + var buf; + do { +#if ASSERTIONS + assert(index < GL.tempVertexBuffers.length); +#endif + buf = GL.tempVertexBuffers[index++]; + } while (used.indexOf(buf) >= 0); + used.push(buf); Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, buf); Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, - HEAPU8.subarray(cb.ptr, cb.ptr + GL.calcBufLength(cb.size, cb.type, cb.stride, count)), + HEAPU8.subarray(cb.ptr, cb.ptr + size), Module.ctx.DYNAMIC_DRAW); Module.ctx.vertexAttribPointer(i, cb.size, cb.type, cb.normalized, cb.stride, 0); } @@ -301,6 +315,8 @@ var LibraryGL = { for (var i = 0; i < GL.maxVertexAttribs; i++) { GL.clientBuffers[i] = { enabled: false, size: 0, type: 0, normalized: 0, stride: 0, ptr: 0 }; } + + GL.generateTempBuffers(); #endif GL.compressionExt = Module.ctx.getExtension('WEBGL_compressed_texture_s3tc') || From 85b35ffa059457284f5da9f773a9f5e8b6213d99 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 15:32:16 -0800 Subject: [PATCH 18/81] use temp buffers for indices in glDrawElements in FULL_ES2 --- src/library_gl.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 84bb10d9509e0..bbcd33a2ffc67 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -2935,10 +2935,11 @@ var LibraryGL = { #if FULL_ES2 var buf; if (!GL.currElementArrayBuffer) { - buf = Module.ctx.createBuffer(); + var size = GL.calcBufLength(1, type, 0, count); + buf = GL.tempIndexBuffers[GL.tempBufferIndexLookup[size]]; Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, buf); Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, - HEAPU8.subarray(indices, indices + GL.calcBufLength(1, type, 0, count)), + HEAPU8.subarray(indices, indices + size), Module.ctx.DYNAMIC_DRAW); // the index is now 0 indices = 0; @@ -2955,7 +2956,6 @@ var LibraryGL = { if (!GL.currElementArrayBuffer) { Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null); - Module.ctx.deleteBuffer(buf); } #endif }, From 8ea95234f8827eea1b846c427040f94e932e7f46 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 16:33:08 -0800 Subject: [PATCH 19/81] FULL_ES2 todo --- src/library_gl.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/library_gl.js b/src/library_gl.js index bbcd33a2ffc67..c600780909900 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -273,6 +273,7 @@ var LibraryGL = { var used = GL.usedTempBuffers; used.length = 0; + // TODO: initial pass to detect ranges we need to upload, might not need an upload per attrib for (var i = 0; i < GL.maxVertexAttribs; ++i) { var cb = GL.clientBuffers[i]; if (!cb.enabled) continue; From f7e59e31bf9652293c9c96e90866e73236a2ae51 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 18:16:04 -0800 Subject: [PATCH 20/81] support llvm_ctpop_*; fixes #918 --- src/library.js | 14 ++++++++++++++ tests/runner.py | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/src/library.js b/src/library.js index 6ba6dab39fd05..d787e30c01944 100644 --- a/src/library.js +++ b/src/library.js @@ -4896,6 +4896,20 @@ LibraryManager.library = { #endif }, + llvm_ctpop_i32: function(x) { + var ret = 0; + while (x) { + if (x&1) ret++; + x >>= 1; + } + return ret; + }, + + llvm_ctpop_i64__deps: ['llvm_ctpop_i32'], + llvm_ctpop_i64: function(l, h) { + return _llvm_ctpop_i32(l) + _llvm_ctpop_i32(h); + }, + llvm_trap: function() { throw 'trap! ' + new Error().stack; }, diff --git a/tests/runner.py b/tests/runner.py index b631dfc27e537..1f40d69cff1af 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -1253,6 +1253,8 @@ def test_llvm_intrinsics(self): extern int64_t llvm_ctlz_i64(int64_t x); extern int32_t llvm_cttz_i32(int32_t x); extern int64_t llvm_cttz_i64(int64_t x); + extern int32_t llvm_ctpop_i32(int32_t x); + extern int64_t llvm_ctpop_i64(int64_t x); extern int llvm_expect_i32(int x, int y); } @@ -1269,6 +1271,7 @@ def test_llvm_intrinsics(self): printf("%d,%d\n", (int)llvm_ctlz_i64(((int64_t)1) << 40), llvm_ctlz_i32(1<<10)); printf("%d,%d\n", (int)llvm_cttz_i64(((int64_t)1) << 40), llvm_cttz_i32(1<<10)); + printf("%d,%d\n", (int)llvm_ctpop_i64((0x3101ULL << 32) | 1), llvm_ctpop_i32(0x3101)); printf("%d\n", llvm_expect_i32(x % 27, 3)); @@ -1285,6 +1288,7 @@ def test_llvm_intrinsics(self): c5,de,15,8a 23,21 40,10 +5,4 13 72057594037927936 ''') From a084e1795b24d2b076b07158b3fc101f6e9c7298 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Mar 2013 21:22:22 -0800 Subject: [PATCH 21/81] experimental patch to simplify generated function detection --- .../simplifyGeneratedFunctionsDetection.diff | 336 ++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 src/experimental/simplifyGeneratedFunctionsDetection.diff diff --git a/src/experimental/simplifyGeneratedFunctionsDetection.diff b/src/experimental/simplifyGeneratedFunctionsDetection.diff new file mode 100644 index 0000000000000..09e0ebcd911bb --- /dev/null +++ b/src/experimental/simplifyGeneratedFunctionsDetection.diff @@ -0,0 +1,336 @@ +diff --git a/emscripten.py b/emscripten.py +index b698654..a7843c7 100755 +--- a/emscripten.py ++++ b/emscripten.py +@@ -294,8 +294,6 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, + outfile.write(blockaddrsize(indexize(pre))) + pre = None + +- #if DEBUG: outfile.write('// funcs\n') +- + # forward + forwarded_data = json.dumps(forwarded_json) + forwarded_file = temp_files.get('.2.json').name +@@ -483,9 +481,14 @@ Runtime.stackRestore = function(top) { asm.stackRestore(top) }; + else: + function_tables_defs = '\n'.join([table for table in last_forwarded_json['Functions']['tables'].itervalues()]) + outfile.write(function_tables_defs) ++ ++ outfile.write('// EMSCRIPTEN_START_FUNCS\n') ++ + outfile.write(blockaddrsize(indexize(funcs_js))) + funcs_js = None + ++ outfile.write('// EMSCRIPTEN_END_FUNCS\n') ++ + outfile.write(indexize(post)) + if DEBUG: print >> sys.stderr, ' emscript: phase 3 took %s seconds' % (time.time() - t) + +diff --git a/src/jsifier.js b/src/jsifier.js +index ff58ece..d6aa110 100644 +--- a/src/jsifier.js ++++ b/src/jsifier.js +@@ -1587,12 +1587,6 @@ function JSify(data, functionsOnly, givenFunctions) { + + var shellParts = read(shellFile).split('{{BODY}}'); + print(shellParts[1]); +- // Print out some useful metadata (for additional optimizations later, like the eliminator) +- if (EMIT_GENERATED_FUNCTIONS) { +- print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + JSON.stringify(keys(Functions.implementedFunctions).filter(function(func) { +- return IGNORED_FUNCTIONS.indexOf(func.ident) < 0; +- })) + '\n'); +- } + + PassManager.serialize(); + +diff --git a/src/settings.js b/src/settings.js +index 1bfcf92..99c83f4 100644 +--- a/src/settings.js ++++ b/src/settings.js +@@ -336,8 +336,6 @@ var EXPLICIT_ZEXT = 0; // If 1, generate an explicit conversion of zext i1 to i3 + + var NECESSARY_BLOCKADDRS = []; // List of (function, block) for all block addresses that are taken. + +-var EMIT_GENERATED_FUNCTIONS = 0; // whether to emit the list of generated functions, needed for external JS optimization passes +- + // Compiler debugging options + var DEBUG_TAGS_SHOWING = []; + // Some useful items: +diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js +index f2dc516..9fa038c 100644 +--- a/tools/js-optimizer.js ++++ b/tools/js-optimizer.js +@@ -140,16 +140,6 @@ var UNDEFINED_NODE = ['unary-prefix', 'void', ['num', 0]]; + var TRUE_NODE = ['unary-prefix', '!', ['num', 0]]; + var FALSE_NODE = ['unary-prefix', '!', ['num', 1]]; + +-var GENERATED_FUNCTIONS_MARKER = '// EMSCRIPTEN_GENERATED_FUNCTIONS:'; +-var generatedFunctions = null; +-function setGeneratedFunctions(metadata) { +- var start = metadata.indexOf(GENERATED_FUNCTIONS_MARKER); +- generatedFunctions = set(eval(metadata.substr(start + GENERATED_FUNCTIONS_MARKER.length))); +-} +-function isGenerated(ident) { +- return ident in generatedFunctions; +-} +- + function srcToAst(src) { + return uglify.parser.parse(src); + } +@@ -212,21 +202,9 @@ function traverse(node, pre, post, stack) { + return result; + } + +-// Only walk through the generated functions +-function traverseGenerated(ast, pre, post, stack) { +- assert(generatedFunctions); +- traverse(ast, function(node) { +- if (node[0] == 'defun' && isGenerated(node[1])) { +- traverse(node, pre, post, stack); +- return null; +- } +- }); +-} +- +-function traverseGeneratedFunctions(ast, callback) { +- assert(generatedFunctions); ++function traverseFunctions(ast, callback) { + traverse(ast, function(node) { +- if (node[0] == 'defun' && isGenerated(node[1])) { ++ if (node[0] == 'defun') { + callback(node); + return null; + } +@@ -418,7 +396,7 @@ function simplifyExpressionsPre(ast) { + var rerun = true; + while (rerun) { + rerun = false; +- traverseGenerated(ast, function process(node, type, stack) { ++ traverse(ast, function process(node, type, stack) { + if (type == 'binary' && node[1] == '|') { + if (node[2][0] == 'num' && node[3][0] == 'num') { + return ['num', node[2][1] | node[3][1]]; +@@ -455,7 +433,7 @@ function simplifyExpressionsPre(ast) { + } + + // &-related optimizations +- traverseGenerated(ast, function(node, type) { ++ traverse(ast, function(node, type) { + if (type == 'binary' && node[1] == '&' && node[3][0] == 'num') { + if (node[2][0] == 'num') return ['num', node[2][1] & node[3][1]]; + var input = node[2]; +@@ -489,7 +467,7 @@ function simplifyExpressionsPre(ast) { + + if (asm) { + // optimize num >> num, in asm we need this here since we do not run optimizeShifts +- traverseGenerated(ast, function(node, type) { ++ traverse(ast, function(node, type) { + if (type == 'binary' && node[1] == '>>' && node[2][0] == 'num' && node[3][0] == 'num') { + node[0] = 'num'; + node[1] = node[2][1] >> node[3][1]; +@@ -505,7 +483,7 @@ function simplifyExpressionsPre(ast) { + var rerun = true; + while (rerun) { + rerun = false; +- traverseGenerated(ast, function(node, type) { ++ traverse(ast, function(node, type) { + if (type == 'binary' && node[1] == '+') { + if (node[2][0] == 'num' && node[3][0] == 'num') { + rerun = true; +@@ -528,7 +506,7 @@ function simplifyExpressionsPre(ast) { + + // if (x == 0) can be if (!x), etc. + function simplifyZeroComp(ast) { +- traverseGenerated(ast, function(node, type) { ++ traverse(ast, function(node, type) { + var binary; + if (type == 'if' && (binary = node[1])[0] == 'binary') { + if ((binary[1] == '!=' || binary[1] == '!==') && binary[3][0] == 'num' && binary[3][1] == 0) { +@@ -554,7 +532,7 @@ function simplifyExpressionsPre(ast) { + // TODO: when shifting a variable, if there are other uses, keep an unshifted version too, to prevent slowdowns? + function optimizeShiftsInternal(ast, conservative) { + var MAX_SHIFTS = 3; +- traverseGeneratedFunctions(ast, function(fun) { ++ traverseFunctions(ast, function(fun) { + var funMore = true; + var funFinished = {}; + while (funMore) { +@@ -999,7 +977,7 @@ function vacuum(ast) { + } break; + } + } +- traverseGeneratedFunctions(ast, function(node) { ++ traverseFunctions(ast, function(node) { + vacuumInternal(node); + simplifyNotComps(node); + }); +@@ -1021,7 +999,7 @@ function getStatements(node) { + // if (condition) { label == x } else .. + // We can hoist the multiple block into the condition, thus removing code and one 'if' check + function hoistMultiples(ast) { +- traverseGeneratedFunctions(ast, function(node) { ++ traverseFunctions(ast, function(node) { + traverse(node, function(node, type) { + var statements = getStatements(node); + if (!statements) return; +@@ -1135,7 +1113,7 @@ function hoistMultiples(ast) { + // if (..) { .. break|continue } else { .. } + // to + // if (..) { .. break|continue } .. +- traverseGenerated(ast, function(container, type) { ++ traverse(ast, function(container, type) { + var statements = getStatements(container); + if (!statements) return; + for (var i = 0; i < statements.length; i++) { +@@ -1168,7 +1146,7 @@ function loopOptimizer(ast) { + function passTwo(ast) { + var neededDos = []; + // Find unneeded labels +- traverseGenerated(ast, function(node, type, stack) { ++ traverse(ast, function(node, type, stack) { + if (type == 'label' && node[2][0] in LOOP) { + // this is a labelled loop. we don't know if it's needed yet. Mark its label for removal for now now. + stack.push(node); +@@ -1212,7 +1190,7 @@ function loopOptimizer(ast) { + // We return whether another pass is necessary + var more = false; + // Remove unneeded labels +- traverseGenerated(ast, function(node, type) { ++ traverse(ast, function(node, type) { + if (type == 'label' && node[1][0] == '+') { + more = true; + var ident = node[1].substr(1); +@@ -1227,13 +1205,13 @@ function loopOptimizer(ast) { + }); + // Remove unneeded one-time loops. We need such loops if (1) they have a label, or (2) they have a direct break so they are in neededDos. + // First, add all labeled loops of this nature to neededDos +- traverseGenerated(ast, function(node, type) { ++ traverse(ast, function(node, type) { + if (type == 'label' && node[2][0] == 'do') { + neededDos.push(node[2]); + } + }); + // Remove unneeded dos, we know who they are now +- traverseGenerated(ast, function(node, type) { ++ traverse(ast, function(node, type) { + if (type == 'do' && neededDos.indexOf(node) < 0) { + assert(jsonCompare(node[1], ['num', 0]), 'Trying to remove a one-time do loop that is not one of our generated ones.;'); + more = true; +@@ -1407,7 +1385,7 @@ function denormalizeAsm(func, data) { + // we still need the eliminator? Closure? And in what order? Perhaps just + // closure simple? + function registerize(ast) { +- traverseGeneratedFunctions(ast, function(fun) { ++ traverseFunctions(ast, function(fun) { + if (asm) var asmData = normalizeAsm(fun); + // Add parameters as a first (fake) var (with assignment), so they get taken into consideration + var params = {}; // note: params are special, they can never share a register between them (see later) +@@ -1671,7 +1649,7 @@ var ABORTING_ELIMINATOR_SCAN_NODES = set('new', 'object', 'function', 'defun', ' + + function eliminate(ast, memSafe) { + // Find variables that have a single use, and if they can be eliminated, do so +- traverseGeneratedFunctions(ast, function(func, type) { ++ traverseFunctions(ast, function(func, type) { + if (asm) var asmData = normalizeAsm(func); + //printErr('eliminate in ' + func[1]); + +@@ -2218,9 +2196,6 @@ var passes = { + var src = read(arguments_[0]); + var ast = srcToAst(src); + //printErr(JSON.stringify(ast)); throw 1; +-var metadata = src.split('\n').filter(function(line) { return line.indexOf(GENERATED_FUNCTIONS_MARKER) >= 0 })[0]; +-//assert(metadata, 'Must have EMSCRIPTEN_GENERATED_FUNCTIONS metadata'); +-if (metadata) setGeneratedFunctions(metadata); + + arguments_.slice(1).forEach(function(arg) { + passes[arg](ast); +diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py +index 2fd2211..a253afb 100644 +--- a/tools/js_optimizer.py ++++ b/tools/js_optimizer.py +@@ -41,17 +41,17 @@ def run_on_js(filename, passes, js_engine, jcache): + if os.linesep != '\n': + js = js.replace(os.linesep, '\n') # we assume \n in the splitting code + +- # Find suffix +- suffix_marker = '// EMSCRIPTEN_GENERATED_FUNCTIONS' +- suffix_start = js.find(suffix_marker) +- suffix = '' +- if suffix_start >= 0: +- suffix = js[suffix_start:js.find('\n', suffix_start)] + '\n' +- # if there is metadata, we will run only on the generated functions. If there isn't, we will run on everything. +- generated = set(eval(suffix[len(suffix_marker)+1:])) +- +- if not suffix and jcache: +- # JCache cannot be used without metadata, since it might reorder stuff, and that's dangerous since only generated can be reordered ++ # Find markers ++ start_marker = '// EMSCRIPTEN_START_FUNCS\n' ++ end_marker = '// EMSCRIPTEN_END_FUNCS\n' ++ start = js.find(start_marker) ++ end = js.find(end_marker) ++ assert (start >= 0) == (end >= 0), 'must have both markers or neither' ++ have_markers = start >= 0 ++ # if there are markers, we will run only on the generated functions. If there isn't, we will run on everything. ++ ++ if not have_markers and jcache: ++ # JCache cannot be used without markers, since it might reorder stuff, and that's dangerous since only generated can be reordered + # This means jcache does not work after closure compiler runs, for example. But you won't get much benefit from jcache with closure + # anyhow (since closure is likely the longest part of the build). + if DEBUG: print >>sys.stderr, 'js optimizer: no metadata, so disabling jcache' +@@ -59,27 +59,10 @@ def run_on_js(filename, passes, js_engine, jcache): + + # If we process only generated code, find that and save the rest on the side + func_sig = re.compile('( *)function (_[\w$]+)\(') +- if suffix: +- pos = 0 +- gen_start = 0 +- gen_end = 0 +- while 1: +- m = func_sig.search(js, pos) +- if not m: break +- pos = m.end() +- indent = m.group(1) +- ident = m.group(2) +- if ident in generated: +- if not gen_start: +- gen_start = m.start() +- assert gen_start +- gen_end = js.find('\n%s}\n' % indent, m.end()) + (3 + len(indent)) +- assert gen_end > gen_start +- pre = js[:gen_start] +- post = js[gen_end:] +- if 'last' in passes: +- post = post.replace(suffix, '') # no need to write out the metadata - nothing after us needs it +- js = js[gen_start:gen_end] ++ if have_markers: ++ pre = js[:start + len(start_marker)] # includes start marker ++ post = js[end:] # includes end marker ++ js = js[start + len(start_marker):end] + else: + pre = '' + post = '' +@@ -95,7 +78,7 @@ def run_on_js(filename, passes, js_engine, jcache): + if m: + ident = m.group(2) + else: +- if suffix: continue # ignore whitespace ++ if have_markers: continue # ignore whitespace + ident = 'anon_%d' % i + assert ident + funcs.append((ident, func)) +@@ -131,7 +114,6 @@ def run_on_js(filename, passes, js_engine, jcache): + temp_file = temp_files.get('.jsfunc_%d.js' % i).name + f = open(temp_file, 'w') + f.write(chunk) +- f.write(suffix) + f.close() + return temp_file + filenames = [write_chunk(chunks[i], i) for i in range(len(chunks))] +@@ -169,7 +151,6 @@ def run_on_js(filename, passes, js_engine, jcache): + f.write(cached); # TODO: preserve order + f.write('\n') + f.write(post); +- # No need to write suffix: if there was one, it is inside post which exists when suffix is there + f.write('\n') + f.close() + From 1836357e38f7a13c3ac3810ed0e82a8d393c5a3c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 10:09:34 -0800 Subject: [PATCH 22/81] disable test_openjpeg in s_x_x --- tests/runner.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/runner.py b/tests/runner.py index cc66068e4d1ef..719cf5f48a8cf 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7240,6 +7240,8 @@ def process(filename): #, build_ll_hook=self.do_autodebug) def test_openjpeg(self): + if self.emcc_args is None: return self.skip('needs libc for getopt') + if Settings.USE_TYPED_ARRAYS == 2: Settings.CORRECT_SIGNS = 1 else: From 82ddb0715d1aa655841223cff314a5377fe10aa5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 10:17:44 -0800 Subject: [PATCH 23/81] send only a marker of generated functions to js-optimizer.js; we either know the generated functions and send only them, or we don't know them and send all the code, in either case js-optimizer.js does not need a list of generated functions --- tools/eliminator/eliminator-test-output.js | 7 ------- tools/eliminator/eliminator-test.js | 7 ------- tools/js-optimizer.js | 19 +++++-------------- tools/js_optimizer.py | 2 +- tools/test-js-optimizer-output.js | 6 ------ tools/test-js-optimizer.js | 6 ------ 6 files changed, 6 insertions(+), 41 deletions(-) diff --git a/tools/eliminator/eliminator-test-output.js b/tools/eliminator/eliminator-test-output.js index 32b7ddcfe639a..69539e91c7eb7 100644 --- a/tools/eliminator/eliminator-test-output.js +++ b/tools/eliminator/eliminator-test-output.js @@ -192,13 +192,6 @@ function strtok_part(b, j, f) { function py() { HEAP[HEAP[HEAP[__PyThreadState_Current] + 12] + 1 + 12] = 99; } -function otherPy() { - var $4 = HEAP[__PyThreadState_Current]; - var $5 = $4 + 12; - var $7 = HEAP[$5] + 1; - var $8 = $4 + 12; - HEAP[$8] = $7; -} var anon = (function(x) { var $4 = HEAP[__PyThreadState_Current]; var $5 = $4 + 12; diff --git a/tools/eliminator/eliminator-test.js b/tools/eliminator/eliminator-test.js index 13ecab591774b..3edd61ac90ae1 100644 --- a/tools/eliminator/eliminator-test.js +++ b/tools/eliminator/eliminator-test.js @@ -230,13 +230,6 @@ function py() { var $8 = $7 + 12; HEAP[$8] = 99; } -function otherPy() { - var $4 = HEAP[__PyThreadState_Current]; - var $5 = $4 + 12; - var $7 = HEAP[$5] + 1; - var $8 = $4 + 12; - HEAP[$8] = $7; -} var anon = function(x) { var $4 = HEAP[__PyThreadState_Current]; var $5 = $4 + 12; diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index f2dc516a2441d..9c744fa33407c 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -140,15 +140,8 @@ var UNDEFINED_NODE = ['unary-prefix', 'void', ['num', 0]]; var TRUE_NODE = ['unary-prefix', '!', ['num', 0]]; var FALSE_NODE = ['unary-prefix', '!', ['num', 1]]; -var GENERATED_FUNCTIONS_MARKER = '// EMSCRIPTEN_GENERATED_FUNCTIONS:'; -var generatedFunctions = null; -function setGeneratedFunctions(metadata) { - var start = metadata.indexOf(GENERATED_FUNCTIONS_MARKER); - generatedFunctions = set(eval(metadata.substr(start + GENERATED_FUNCTIONS_MARKER.length))); -} -function isGenerated(ident) { - return ident in generatedFunctions; -} +var GENERATED_FUNCTIONS_MARKER = '// EMSCRIPTEN_GENERATED_FUNCTIONS'; +var generatedFunctions = false; // whether we have received only generated functions function srcToAst(src) { return uglify.parser.parse(src); @@ -216,7 +209,7 @@ function traverse(node, pre, post, stack) { function traverseGenerated(ast, pre, post, stack) { assert(generatedFunctions); traverse(ast, function(node) { - if (node[0] == 'defun' && isGenerated(node[1])) { + if (node[0] == 'defun') { traverse(node, pre, post, stack); return null; } @@ -226,7 +219,7 @@ function traverseGenerated(ast, pre, post, stack) { function traverseGeneratedFunctions(ast, callback) { assert(generatedFunctions); traverse(ast, function(node) { - if (node[0] == 'defun' && isGenerated(node[1])) { + if (node[0] == 'defun') { callback(node); return null; } @@ -2218,9 +2211,7 @@ var passes = { var src = read(arguments_[0]); var ast = srcToAst(src); //printErr(JSON.stringify(ast)); throw 1; -var metadata = src.split('\n').filter(function(line) { return line.indexOf(GENERATED_FUNCTIONS_MARKER) >= 0 })[0]; -//assert(metadata, 'Must have EMSCRIPTEN_GENERATED_FUNCTIONS metadata'); -if (metadata) setGeneratedFunctions(metadata); +generatedFunctions = src.indexOf(GENERATED_FUNCTIONS_MARKER) >= 0; arguments_.slice(1).forEach(function(arg) { passes[arg](ast); diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 2fd2211b759e2..13e6e4f6d91da 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -131,7 +131,7 @@ def write_chunk(chunk, i): temp_file = temp_files.get('.jsfunc_%d.js' % i).name f = open(temp_file, 'w') f.write(chunk) - f.write(suffix) + f.write(suffix_marker) f.close() return temp_file filenames = [write_chunk(chunks[i], i) for i in range(len(chunks))] diff --git a/tools/test-js-optimizer-output.js b/tools/test-js-optimizer-output.js index 5c06475e87608..13f927dee33fa 100644 --- a/tools/test-js-optimizer-output.js +++ b/tools/test-js-optimizer-output.js @@ -35,12 +35,6 @@ function loopy() { next(); something(); } -function ignoreLoopy() { - b$for_cond$4 : while (1) { - if ($ok) break b$for_cond$4; - var $inc = $ok + 1; - } -} function bits() { print(($s & 65535) + ((($f & 65535) << 16 >> 16) * (($f & 65535) << 16 >> 16) | 0) % 256 & 65535); z(HEAP32[$id + 40 >> 2]); diff --git a/tools/test-js-optimizer.js b/tools/test-js-optimizer.js index 982e3230e5b01..bd3be2810410b 100644 --- a/tools/test-js-optimizer.js +++ b/tools/test-js-optimizer.js @@ -37,12 +37,6 @@ function loopy() { something(); } while(0); } -function ignoreLoopy() { - b$for_cond$4: while(1) { - if ($ok) break b$for_cond$4; - var $inc=$ok+1; - } -} function bits() { print((($s & 65535) + ((($f & 65535) << 16 >> 16) * (($f & 65535) << 16 >> 16) | 0 | 0) % 256 | 0) & 65535); z(HEAP32[($id + 40 | 0) >> 2]); From a3fa0380155176e4d60159ccc5f2a264268863ac Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 10:22:16 -0800 Subject: [PATCH 24/81] deprecate USE_TYPED_ARRAYS=1 and QUANTUM_SIZE=1 --- src/settings.js | 4 ++-- tests/runner.py | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/settings.js b/src/settings.js index 1bfcf92ac552a..440d5094d05e0 100644 --- a/src/settings.js +++ b/src/settings.js @@ -15,7 +15,7 @@ var QUANTUM_SIZE = 4; // This is the size of an individual field in a structure. // the normal value of 4 means all fields take 4 memory addresses, // as per the norm on a 32-bit machine. // - // 1 is somewhat faster than 4, but dangerous. + // Changing this from the default of 4 is deprecated. var CORRECT_SIGNS = 1; // Whether we make sure to convert unsigned values to signed values. // Decreases performance with additional runtime checks. Might not be @@ -63,7 +63,7 @@ var RELOOPER = 'relooper.js'; // Loads the relooper from this path relative to c var USE_TYPED_ARRAYS = 2; // Use typed arrays for the heap. See https://github.com/kripken/emscripten/wiki/Code-Generation-Modes/ // 0 means no typed arrays are used. // 1 has two heaps, IHEAP (int32) and FHEAP (double), - // and addresses there are a match for normal addresses. + // and addresses there are a match for normal addresses. This is deprecated. // 2 is a single heap, accessible through views as int8, int32, etc. This is // the recommended mode both for performance and for compatibility. var USE_FHEAP = 1; // Relevant in USE_TYPED_ARRAYS == 1. If this is disabled, only IHEAP will be used, and FHEAP diff --git a/tests/runner.py b/tests/runner.py index 719cf5f48a8cf..cdc8684b98088 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -445,7 +445,7 @@ def setup_runtimelink_test(self): if len(sys.argv) == 2 and 'ALL.' in sys.argv[1]: ignore, test = sys.argv[1].split('.') print 'Running all test modes on test "%s"' % test - sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_0_1_q1.'+test, 's_1_0.'+test, 's_1_1.'+test, 's_1_1_q1.'+test] + sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test] class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline ## Does a complete test - builds, runs, checks output, etc. @@ -8529,8 +8529,6 @@ def setUp(self): # Make custom runs with various options for compiler, quantum, embetter, typed_arrays, llvm_opts in [ - (CLANG, 1, 1, 0, 0), - (CLANG, 1, 1, 1, 1), (CLANG, 4, 0, 0, 0), (CLANG, 4, 0, 0, 1), (CLANG, 4, 1, 1, 0), From 49970438a39d7f61d8591aca3f5f2d2d2ada748b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 10:26:18 -0800 Subject: [PATCH 25/81] run registerize pass last --- emcc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/emcc b/emcc index fa62acb10e999..58d49972066b9 100755 --- a/emcc +++ b/emcc @@ -1347,14 +1347,15 @@ try: if DEBUG: print >> sys.stderr, 'emcc: running closure' final = shared.Building.closure_compiler(final) if DEBUG: save_intermediate('closure') - elif shared.Settings.RELOOP and not closure and not keep_js_debug: - # do this if closure is not enabled (it gives similar speedups), and we do not need to keep debug info around - js_optimizer_queue += ['registerize'] if opt_level >= 1: if DEBUG: print >> sys.stderr, 'emcc: running post-closure post-opts' js_optimizer_queue += ['simplifyExpressionsPost'] + if not closure and shared.Settings.RELOOP and not keep_js_debug: + # do this if closure is not enabled (it gives similar speedups), and we do not need to keep debug info around + js_optimizer_queue += ['registerize'] + if minify_whitespace: js_optimizer_queue += ['compress'] From ca11fd78eb643ab5b28dac2328fb9012dccd1f25 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 12:04:34 -0800 Subject: [PATCH 26/81] initial work on asm.js minifier infrastructure --- tools/js-optimizer.js | 5 ++++ tools/js_optimizer.py | 70 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 9c744fa33407c..0387f9fd374e2 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -143,6 +143,8 @@ var FALSE_NODE = ['unary-prefix', '!', ['num', 1]]; var GENERATED_FUNCTIONS_MARKER = '// EMSCRIPTEN_GENERATED_FUNCTIONS'; var generatedFunctions = false; // whether we have received only generated functions +var minifierInfo = null; + function srcToAst(src) { return uglify.parser.parse(src); } @@ -2212,6 +2214,9 @@ var src = read(arguments_[0]); var ast = srcToAst(src); //printErr(JSON.stringify(ast)); throw 1; generatedFunctions = src.indexOf(GENERATED_FUNCTIONS_MARKER) >= 0; +var minifierInfoStart = src.indexOf('// MINIFY_INFO:') +if (minifierInfoStart > 0) minifierInfo = JSON.parse(src.substr(minifierInfoStart + 15)); +//printErr(JSON.stringify(minifierInfo)); arguments_.slice(1).forEach(function(arg) { passes[arg](ast); diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 13e6e4f6d91da..a82dcb9bfecdd 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -1,5 +1,5 @@ -import os, sys, subprocess, multiprocessing, re +import os, sys, subprocess, multiprocessing, re, string, json import shared configuration = shared.configuration @@ -19,6 +19,54 @@ def path_from_root(*pathelems): DEBUG = os.environ.get('EMCC_DEBUG') +class Minifier: + ''' + asm.js minification support. We calculate possible names and minification of + globals here, then pass that into the parallel js-optimizer.js runners which + during registerize perform minification of locals. + ''' + + def __init__(self, globs): + # Create list of valid short names + + MAX_NAMES = 200#60000 + INVALID_2 = set(['do', 'if', 'in']) + INVALID_3 = set(['for', 'new', 'try', 'var']) + + self.names = [] + init_possibles = string.ascii_letters + '_$' + later_possibles = init_possibles + string.digits + for a in init_possibles: + if len(self.names) >= MAX_NAMES: break + self.names.append(a) + for a in init_possibles: + for b in later_possibles: + if len(self.names) >= MAX_NAMES: break + curr = a + b + if curr not in INVALID_2: self.names.append(curr) + for a in init_possibles: + for b in later_possibles: + for c in later_possibles: + if len(self.names) >= MAX_NAMES: break + curr = a + b + c + if curr not in INVALID_3: self.names.append(curr) + #print >> sys.stderr, self.names + + # Minify the globals (initials - asm imports, etc. - and functions) + # TODO: find how many times they are used and do this more optimally + + self.globs = {} + i = 0 + for g in globs: + self.globs[g] = self.names[i] + i += 1 + + def serialize(self): + return json.dumps({ + 'names': self.names, + 'globals': self.globs + }) + def run_on_chunk(command): filename = command[2] # XXX hackish #print >> sys.stderr, 'running js optimizer command', ' '.join(command), '""""', open(filename).read() @@ -126,12 +174,32 @@ def load_from_cache(chunk): else: cached_outputs = [] + if 'registerize' in passes: + assert suffix, 'need generated info for registerize' + # Find basic globals (initial asm.js imports, etc.) + asm_marker = pre.find("'use asm'") + if asm_marker < 0: asm_marker = pre.find('"use asm"') + assert asm_marker > 0 + asm_funcs = pre.find('function ', asm_marker) + assert asm_funcs > asm_marker + globs = [] + for vardef in re.findall(r'var [^;]+;', pre[asm_marker:asm_funcs]): + vs = vardef[4:-1].split(',') + for v in vs: + v = v.split('=')[0].strip() + globs.append(v) + minify_info = Minifier(globs + list(generated)).serialize() + #print >> sys.stderr, 'm', minify_info + if len(chunks) > 0: def write_chunk(chunk, i): temp_file = temp_files.get('.jsfunc_%d.js' % i).name f = open(temp_file, 'w') f.write(chunk) f.write(suffix_marker) + if 'registerize' in passes: + f.write('\n') + f.write('// MINIFY_INFO:' + minify_info) f.close() return temp_file filenames = [write_chunk(chunks[i], i) for i in range(len(chunks))] From 52b9d04de89f922d9499415f2fe04f8ff6375e9f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 12:23:18 -0800 Subject: [PATCH 27/81] fix global minifying --- tools/js_optimizer.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index a82dcb9bfecdd..b7d342d256816 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -26,12 +26,12 @@ class Minifier: during registerize perform minification of locals. ''' - def __init__(self, globs): + def __init__(self): # Create list of valid short names MAX_NAMES = 200#60000 INVALID_2 = set(['do', 'if', 'in']) - INVALID_3 = set(['for', 'new', 'try', 'var']) + INVALID_3 = set(['for', 'new', 'try', 'var', 'env']) self.names = [] init_possibles = string.ascii_letters + '_$' @@ -52,14 +52,14 @@ def __init__(self, globs): if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names + self.globs = {} + + def add_glob(self, glob): # Minify the globals (initials - asm imports, etc. - and functions) # TODO: find how many times they are used and do this more optimally - - self.globs = {} - i = 0 - for g in globs: - self.globs[g] = self.names[i] - i += 1 + ret = self.names[len(self.globs)] + self.globs[glob] = ret + return ret def serialize(self): return json.dumps({ @@ -182,14 +182,19 @@ def load_from_cache(chunk): assert asm_marker > 0 asm_funcs = pre.find('function ', asm_marker) assert asm_funcs > asm_marker - globs = [] + minifier = Minifier() + new_vars = '' for vardef in re.findall(r'var [^;]+;', pre[asm_marker:asm_funcs]): vs = vardef[4:-1].split(',') for v in vs: - v = v.split('=')[0].strip() - globs.append(v) - minify_info = Minifier(globs + list(generated)).serialize() - #print >> sys.stderr, 'm', minify_info + name, value = map(lambda x: x.strip(), v.split('=')) + new_vars += 'var ' + minifier.add_glob(name) + '=' + value + ';' + for g in generated: + minifier.add_glob(g) + minify_info = minifier.serialize() + minifier = None + pre = pre[:asm_marker+11] + new_vars + pre[asm_funcs:] + print >> sys.stderr, 'm', minify_info if len(chunks) > 0: def write_chunk(chunk, i): From 51bbcd608450d161d1c26fc83aab545837929a86 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 13:51:56 -0800 Subject: [PATCH 28/81] handle assigns into globals at the top of asm functions in normalizeAsm --- tools/js-optimizer.js | 4 +++- tools/test-js-optimizer-asm-regs-output.js | 4 ++++ tools/test-js-optimizer-asm-regs.js | 6 +++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 0387f9fd374e2..77ad0ba3f4718 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1302,7 +1302,9 @@ function normalizeAsm(func) { var node = stats[i]; if (node[0] != 'stat' || node[1][0] != 'assign' || node[1][2][0] != 'name') break; node = node[1]; - data.params[node[2][1]] = detectAsmCoercion(node[3]); + var name = node[2][1]; + if (func[2] && func[2].indexOf(name) < 0) break; // not an assign into a parameter, but a global + data.params[name] = detectAsmCoercion(node[3]); stats[i] = emptyNode(); i++; } diff --git a/tools/test-js-optimizer-asm-regs-output.js b/tools/test-js-optimizer-asm-regs-output.js index 99bccd2e4e579..8c0bd97058309 100644 --- a/tools/test-js-optimizer-asm-regs-output.js +++ b/tools/test-js-optimizer-asm-regs-output.js @@ -38,4 +38,8 @@ function retf() { } return +0; } +function stackRestore(i1) { + i1 = i1 | 0; + STACKTOP = i1; +} diff --git a/tools/test-js-optimizer-asm-regs.js b/tools/test-js-optimizer-asm-regs.js index 0afced2959e62..a8b637ced4f06 100644 --- a/tools/test-js-optimizer-asm-regs.js +++ b/tools/test-js-optimizer-asm-regs.js @@ -41,5 +41,9 @@ function retf() { } // missing final return, need it as a float } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "rett", "ret2t", "retf"] +function stackRestore(top) { + top = top|0; + STACKTOP = top; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "rett", "ret2t", "retf", "stackRestore"] From 42f0bbd43da0bd99a3659441355e0b6257fa9e4e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 14:12:53 -0800 Subject: [PATCH 29/81] do not emit function names on runtime functions --- src/runtime.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime.js b/src/runtime.js index dc604a8d23375..8352ade1d018f 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -87,7 +87,7 @@ var RuntimeGenerator = { }; function unInline(name_, params) { - var src = '(function ' + name_ + '(' + params + ') { var ret = ' + RuntimeGenerator[name_].apply(null, params) + '; return ret; })'; + var src = '(function(' + params + ') { var ret = ' + RuntimeGenerator[name_].apply(null, params) + '; return ret; })'; var ret = eval(src); return ret; } From bdaddc1e00ff169ee7491d84e318e4a159c71013 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 14:24:04 -0800 Subject: [PATCH 30/81] disable minification --- tools/js_optimizer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index b7d342d256816..9e12ef2d277aa 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -174,7 +174,7 @@ def load_from_cache(chunk): else: cached_outputs = [] - if 'registerize' in passes: + if 'zzzregisterize' in passes: assert suffix, 'need generated info for registerize' # Find basic globals (initial asm.js imports, etc.) asm_marker = pre.find("'use asm'") @@ -202,7 +202,7 @@ def write_chunk(chunk, i): f = open(temp_file, 'w') f.write(chunk) f.write(suffix_marker) - if 'registerize' in passes: + if 'zzzregisterize' in passes: f.write('\n') f.write('// MINIFY_INFO:' + minify_info) f.close() From 21804c07c76ac3e0be86b2db6ba1c456ab0bae28 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 15:29:39 -0800 Subject: [PATCH 31/81] add explicit markers in generated code of where functions and asm are --- emscripten.py | 20 +++++++++++++++----- tools/js_optimizer.py | 44 +++++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/emscripten.py b/emscripten.py index b698654bba2f5..2291a65a3e09a 100755 --- a/emscripten.py +++ b/emscripten.py @@ -332,9 +332,9 @@ def make_table(sig, raw): params = ','.join(['p%d' % p for p in range(len(sig)-1)]) coercions = ';'.join(['p%d = %sp%d%s' % (p, '+' if sig[p+1] != 'i' else '', p, '' if sig[p+1] != 'i' else '|0') for p in range(len(sig)-1)]) + ';' ret = '' if sig[0] == 'v' else ('return %s0' % ('+' if sig[0] != 'i' else '')) - return ('function %s(%s) { %s abort(%d); %s };' % (bad, params, coercions, i, ret), raw.replace('[0,', '[' + bad + ',').replace(',0,', ',' + bad + ',').replace(',0,', ',' + bad + ',').replace(',0]', ',' + bad + ']').replace(',0]', ',' + bad + ']').replace(',0\n', ',' + bad + '\n')) + return ('function %s(%s) { %s abort(%d); %s }' % (bad, params, coercions, i, ret), raw.replace('[0,', '[' + bad + ',').replace(',0,', ',' + bad + ',').replace(',0,', ',' + bad + ',').replace(',0]', ',' + bad + ']').replace(',0]', ',' + bad + ']').replace(',0\n', ',' + bad + '\n')) infos = [make_table(sig, raw) for sig, raw in last_forwarded_json['Functions']['tables'].iteritems()] - function_tables_defs = '\n'.join([info[0] for info in infos] + [info[1] for info in infos]) + function_tables_defs = '\n'.join([info[0] for info in infos]) + '\n// EMSCRIPTEN_END_FUNCS\n' + '\n'.join([info[1] for info in infos]) asm_setup = '' maths = ['Math.' + func for func in ['floor', 'abs', 'sqrt', 'pow', 'cos', 'sin', 'tan', 'acos', 'asin', 'atan', 'atan2', 'exp', 'log', 'ceil', 'imul']] @@ -416,6 +416,7 @@ def math_fix(g): function asmPrintFloat(x, y) { Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); } +// EMSCRIPTEN_START_ASM var asm = (function(global, env, buffer) { 'use asm'; var HEAP8 = new global.Int8Array(buffer); @@ -456,12 +457,15 @@ def math_fix(g): value = value|0; tempRet%d = value; } -''' % (i, i) for i in range(10)]) + funcs_js + ''' - +''' % (i, i) for i in range(10)]) + ''' +// EMSCRIPTEN_START_FUNCS +''' + funcs_js + ''' %s return %s; -})(%s, %s, buffer); +}) +// EMSCRIPTEN_END_ASM +(%s, %s, buffer); %s; Runtime.stackAlloc = function(size) { return asm.stackAlloc(size) }; Runtime.stackSave = function() { return asm.stackSave() }; @@ -483,6 +487,12 @@ def fix(m): else: function_tables_defs = '\n'.join([table for table in last_forwarded_json['Functions']['tables'].itervalues()]) outfile.write(function_tables_defs) + funcs_js = ''' +// EMSCRIPTEN_START_FUNCS +''' + funcs_js + ''' +// EMSCRIPTEN_END_FUNCS +''' + outfile.write(blockaddrsize(indexize(funcs_js))) funcs_js = None diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 9e12ef2d277aa..5c155ff5a6ae5 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -98,6 +98,19 @@ def run_on_js(filename, passes, js_engine, jcache): # if there is metadata, we will run only on the generated functions. If there isn't, we will run on everything. generated = set(eval(suffix[len(suffix_marker)+1:])) + # Find markers + start_funcs_marker = '// EMSCRIPTEN_START_FUNCS\n' + end_funcs_marker = '// EMSCRIPTEN_END_FUNCS\n' + start_funcs = js.find(start_funcs_marker) + end_funcs = js.find(end_funcs_marker) + assert (start_funcs >= 0) == (end_funcs >= 0) == (not not suffix) + if 'asm' in passes: + start_asm_marker = '// EMSCRIPTEN_START_ASM\n' + end_asm_marker = '// EMSCRIPTEN_END_ASM\n' + start_asm = js.find(start_asm_marker) + end_asm = js.find(end_asm_marker) + assert (start_asm >= 0) == (end_asm >= 0) + if not suffix and jcache: # JCache cannot be used without metadata, since it might reorder stuff, and that's dangerous since only generated can be reordered # This means jcache does not work after closure compiler runs, for example. But you won't get much benefit from jcache with closure @@ -105,37 +118,24 @@ def run_on_js(filename, passes, js_engine, jcache): if DEBUG: print >>sys.stderr, 'js optimizer: no metadata, so disabling jcache' jcache = False - # If we process only generated code, find that and save the rest on the side - func_sig = re.compile('( *)function (_[\w$]+)\(') if suffix: - pos = 0 - gen_start = 0 - gen_end = 0 - while 1: - m = func_sig.search(js, pos) - if not m: break - pos = m.end() - indent = m.group(1) - ident = m.group(2) - if ident in generated: - if not gen_start: - gen_start = m.start() - assert gen_start - gen_end = js.find('\n%s}\n' % indent, m.end()) + (3 + len(indent)) - assert gen_end > gen_start - pre = js[:gen_start] - post = js[gen_end:] - if 'last' in passes: - post = post.replace(suffix, '') # no need to write out the metadata - nothing after us needs it - js = js[gen_start:gen_end] + pre = js[:start_funcs + len(start_funcs_marker)] + post = js[end_funcs:] + js = js[start_funcs + len(start_funcs_marker):end_funcs] + if 'asm' not in passes: # can have Module[..] and inlining prevention code, push those to post + for line in js.split('\n'): + if len(line) > 0 and not line.startswith((' ', 'function', '}')): + post = line + '\n' + post else: pre = '' post = '' + generated # Pick where to split into chunks, so that (1) they do not oom in node/uglify, and (2) we can run them in parallel # If we have metadata, we split only the generated code, and save the pre and post on the side (and do not optimize them) parts = map(lambda part: part, js.split('\n}\n')) funcs = [] + func_sig = re.compile('( *)function ([_\w$]+)\(') for i in range(len(parts)): func = parts[i] if i < len(parts)-1: func += '\n}\n' # last part needs no } From 50c7f9f00e4666860bf1f39181cc6f9133ef46bb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 15:58:28 -0800 Subject: [PATCH 32/81] remove unneeded line --- tools/js_optimizer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 5c155ff5a6ae5..a7d9c1e127ecf 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -129,7 +129,6 @@ def run_on_js(filename, passes, js_engine, jcache): else: pre = '' post = '' - generated # Pick where to split into chunks, so that (1) they do not oom in node/uglify, and (2) we can run them in parallel # If we have metadata, we split only the generated code, and save the pre and post on the side (and do not optimize them) From b31addd3ab55af8dddb703580ebf5d2a90660c61 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 16:17:52 -0800 Subject: [PATCH 33/81] split out asm shell in js optimizer, in preparation for minification of globals --- emscripten.py | 5 ++--- tools/js_optimizer.py | 34 ++++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/emscripten.py b/emscripten.py index 2291a65a3e09a..09a57e37e772e 100755 --- a/emscripten.py +++ b/emscripten.py @@ -433,6 +433,7 @@ def math_fix(g): var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0; ''' + ''.join([''' var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs + ''' +// EMSCRIPTEN_START_FUNCS function stackAlloc(size) { size = size|0; var ret = 0; @@ -457,9 +458,7 @@ def math_fix(g): value = value|0; tempRet%d = value; } -''' % (i, i) for i in range(10)]) + ''' -// EMSCRIPTEN_START_FUNCS -''' + funcs_js + ''' +''' % (i, i) for i in range(10)]) + funcs_js + ''' %s return %s; diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index a7d9c1e127ecf..4661580badbdc 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -102,13 +102,14 @@ def run_on_js(filename, passes, js_engine, jcache): start_funcs_marker = '// EMSCRIPTEN_START_FUNCS\n' end_funcs_marker = '// EMSCRIPTEN_END_FUNCS\n' start_funcs = js.find(start_funcs_marker) - end_funcs = js.find(end_funcs_marker) + end_funcs = js.rfind(end_funcs_marker) assert (start_funcs >= 0) == (end_funcs >= 0) == (not not suffix) - if 'asm' in passes: + asm_registerize = 'asm' in passes and 'registerize' in passes + if asm_registerize: start_asm_marker = '// EMSCRIPTEN_START_ASM\n' end_asm_marker = '// EMSCRIPTEN_END_ASM\n' start_asm = js.find(start_asm_marker) - end_asm = js.find(end_asm_marker) + end_asm = js.rfind(end_asm_marker) assert (start_asm >= 0) == (end_asm >= 0) if not suffix and jcache: @@ -119,13 +120,26 @@ def run_on_js(filename, passes, js_engine, jcache): jcache = False if suffix: - pre = js[:start_funcs + len(start_funcs_marker)] - post = js[end_funcs:] - js = js[start_funcs + len(start_funcs_marker):end_funcs] - if 'asm' not in passes: # can have Module[..] and inlining prevention code, push those to post - for line in js.split('\n'): - if len(line) > 0 and not line.startswith((' ', 'function', '}')): - post = line + '\n' + post + if not asm_registerize: + pre = js[:start_funcs + len(start_funcs_marker)] + post = js[end_funcs:] + js = js[start_funcs + len(start_funcs_marker):end_funcs] + if 'asm' not in passes: # can have Module[..] and inlining prevention code, push those to post + for line in js.split('\n'): + if len(line) > 0 and not line.startswith((' ', 'function', '}')): + post = line + '\n' + post + else: + # We need to split out the asm shell as well, for minification + pre = js[:start_asm + len(start_asm_marker)] + post = js[end_asm:] + asm_shell = js[start_asm + len(start_asm_marker):start_funcs + len(start_funcs_marker)] + ''' +EMSCRIPTEN_FUNCS(); +''' + js[end_funcs + len(end_funcs_marker):end_asm + len(end_asm_marker)] + minified_asm_shell = asm_shell # TODO: minification of globals + asm_shell_pre, asm_shell_post = minified_asm_shell.split('EMSCRIPTEN_FUNCS();'); + pre += asm_shell_pre + post = asm_shell_post + post + js = js[start_funcs + len(start_funcs_marker):end_funcs] else: pre = '' post = '' From dac020142d05493a1c47632e561f4069a85ee13a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 17:12:22 -0800 Subject: [PATCH 34/81] minify globals in a pass before the functions --- tools/js-optimizer.js | 35 +++++++++++++++++++++++++++++++++ tools/js_optimizer.py | 45 ++++++++++++++++++++++++++++++++----------- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 77ad0ba3f4718..092c9f3523138 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -2159,6 +2159,37 @@ function eliminateMemSafe(ast) { eliminate(ast, true); } +function minifyGlobals(ast) { + var minified = {}; + var next = 0; + var first = true; // do not minify initial 'var asm =' + traverse(ast, function(node, type) { + if (type == 'var') { + if (first) { + first = false; + return; + } + var vars = node[1]; + for (var i = 0; i < vars.length; i++) { + var name = vars[i][0]; + vars[i][0] = minified[name] = minifierInfo.names[next++]; + } + } else if (type == 'name') { + var name = node[1]; + if (name in minified) { + node[1] = minified[name]; + } else if (name == 'EMSCRIPTEN_FUNCS') { + // minify all the globals + for (var i = 0; i < minifierInfo.globals.length; i++) { + name = minifierInfo.globals[i]; + minified[name] = minifierInfo.names[next++]; + } + } + } + }); + suffix = '// MINIFY_INFO:' + JSON.stringify(minified); +} + // Change +5 to DOT$ZERO(5). We then textually change 5 to 5.0 (uglify's ast cannot differentiate between 5 and 5.0 directly) function prepDotZero(ast) { traverse(ast, function(node, type) { @@ -2204,6 +2235,7 @@ var passes = { registerize: registerize, eliminate: eliminate, eliminateMemSafe: eliminateMemSafe, + minifyGlobals: minifyGlobals, compress: function() { compress = true }, noPrintMetadata: function() { printMetadata = false }, asm: function() { asm = true }, @@ -2212,6 +2244,8 @@ var passes = { // Main +var suffix = ''; + var src = read(arguments_[0]); var ast = srcToAst(src); //printErr(JSON.stringify(ast)); throw 1; @@ -2238,4 +2272,5 @@ do { } while (js != old); print(js); print('\n'); +print(suffix); diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 4661580badbdc..cc7e81042d088 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -19,6 +19,8 @@ def path_from_root(*pathelems): DEBUG = os.environ.get('EMCC_DEBUG') +func_sig = re.compile('( *)function ([_\w$]+)\(') + class Minifier: ''' asm.js minification support. We calculate possible names and minification of @@ -26,7 +28,10 @@ class Minifier: during registerize perform minification of locals. ''' - def __init__(self): + def __init__(self, js, js_engine): + self.js = js + self.js_engine = js_engine + # Create list of valid short names MAX_NAMES = 200#60000 @@ -52,14 +57,30 @@ def __init__(self): if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names - self.globs = {} + def minify_shell(self, shell): + #print >> sys.stderr, "MINIFY SHELL 1111111111", shell, "\n222222222222222" + # Run through js-optimizer.js to find and minify the global symbols + # We send it the globals, which it parses at the proper time. JS decides how + # to minify all global names, we receive a dictionary back, which is then + # used by the function processors + + # Find all globals in the JS functions code + self.globs = [m.group(2) for m in func_sig.finditer(self.js)] + + temp_file = temp_files.get('.minifyglobals.js').name + f = open(temp_file, 'w') + f.write(shell) + f.write('\n') + self + f.write('// MINIFY_INFO:' + self.serialize()) + f.close() - def add_glob(self, glob): - # Minify the globals (initials - asm imports, etc. - and functions) - # TODO: find how many times they are used and do this more optimally - ret = self.names[len(self.globs)] - self.globs[glob] = ret - return ret + output = subprocess.Popen(self.js_engine + [JS_OPTIMIZER, temp_file, 'minifyGlobals', 'noPrintMetadata'], stdout=subprocess.PIPE).communicate()[0] + assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + output + #print >> sys.stderr, "minified SHELL 3333333333333333", output, "\n44444444444444444444" + code, metadata = output.split('// MINIFY_INFO:') + self.globs = json.loads(metadata) + return output def serialize(self): return json.dumps({ @@ -135,11 +156,14 @@ def run_on_js(filename, passes, js_engine, jcache): asm_shell = js[start_asm + len(start_asm_marker):start_funcs + len(start_funcs_marker)] + ''' EMSCRIPTEN_FUNCS(); ''' + js[end_funcs + len(end_funcs_marker):end_asm + len(end_asm_marker)] - minified_asm_shell = asm_shell # TODO: minification of globals + js = js[start_funcs + len(start_funcs_marker):end_funcs] + + minifier = Minifier(js, js_engine) + minified_asm_shell = minifier.minify_shell(asm_shell) + asm_shell_pre, asm_shell_post = minified_asm_shell.split('EMSCRIPTEN_FUNCS();'); pre += asm_shell_pre post = asm_shell_post + post - js = js[start_funcs + len(start_funcs_marker):end_funcs] else: pre = '' post = '' @@ -148,7 +172,6 @@ def run_on_js(filename, passes, js_engine, jcache): # If we have metadata, we split only the generated code, and save the pre and post on the side (and do not optimize them) parts = map(lambda part: part, js.split('\n}\n')) funcs = [] - func_sig = re.compile('( *)function ([_\w$]+)\(') for i in range(len(parts)): func = parts[i] if i < len(parts)-1: func += '\n}\n' # last part needs no } From 8a7a96a56bcb63d19c03c0c93c662c9493c3c77f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 17:30:58 -0800 Subject: [PATCH 35/81] start to minify inside functions, using global data from previous pass --- tools/js-optimizer.js | 14 +++++++++++++- tools/js_optimizer.py | 30 ++++-------------------------- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 092c9f3523138..7b774deebffaa 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1397,14 +1397,26 @@ function denormalizeAsm(func, data) { //printErr('denormalized \n\n' + astToSrc(func) + '\n\n'); } -// Very simple 'registerization', coalescing of variables into a smaller number. +// Very simple 'registerization', coalescing of variables into a smaller number, +// as part of minification. Globals-level minification began in a previous pass, +// we receive minifierInfo which tells us how to rename globals. +// // We do not optimize when there are switches, so this pass only makes sense with // relooping. // TODO: Consider how this fits in with the rest of the optimization toolchain. Do // we still need the eliminator? Closure? And in what order? Perhaps just // closure simple? function registerize(ast) { + assert(minifierInfo); + traverseGeneratedFunctions(ast, function(fun) { + // First, fix globals. Note that we know/assume that locals cannot shadow globals. + traverse(fun, function(node, type) { + if (type == 'name') { + var minified = minifierInfo.globals[node[1]]; + if (minified) node[1] = minified; + } + }); if (asm) var asmData = normalizeAsm(fun); // Add parameters as a first (fake) var (with assignment), so they get taken into consideration var params = {}; // note: params are special, they can never share a register between them (see later) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index cc7e81042d088..b5213ac3f3a73 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -159,11 +159,11 @@ def run_on_js(filename, passes, js_engine, jcache): js = js[start_funcs + len(start_funcs_marker):end_funcs] minifier = Minifier(js, js_engine) - minified_asm_shell = minifier.minify_shell(asm_shell) - - asm_shell_pre, asm_shell_post = minified_asm_shell.split('EMSCRIPTEN_FUNCS();'); + asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell).split('EMSCRIPTEN_FUNCS();'); pre += asm_shell_pre post = asm_shell_post + post + + minify_info = minifier.serialize() else: pre = '' post = '' @@ -210,35 +210,13 @@ def load_from_cache(chunk): else: cached_outputs = [] - if 'zzzregisterize' in passes: - assert suffix, 'need generated info for registerize' - # Find basic globals (initial asm.js imports, etc.) - asm_marker = pre.find("'use asm'") - if asm_marker < 0: asm_marker = pre.find('"use asm"') - assert asm_marker > 0 - asm_funcs = pre.find('function ', asm_marker) - assert asm_funcs > asm_marker - minifier = Minifier() - new_vars = '' - for vardef in re.findall(r'var [^;]+;', pre[asm_marker:asm_funcs]): - vs = vardef[4:-1].split(',') - for v in vs: - name, value = map(lambda x: x.strip(), v.split('=')) - new_vars += 'var ' + minifier.add_glob(name) + '=' + value + ';' - for g in generated: - minifier.add_glob(g) - minify_info = minifier.serialize() - minifier = None - pre = pre[:asm_marker+11] + new_vars + pre[asm_funcs:] - print >> sys.stderr, 'm', minify_info - if len(chunks) > 0: def write_chunk(chunk, i): temp_file = temp_files.get('.jsfunc_%d.js' % i).name f = open(temp_file, 'w') f.write(chunk) f.write(suffix_marker) - if 'zzzregisterize' in passes: + if asm_registerize: f.write('\n') f.write('// MINIFY_INFO:' + minify_info) f.close() From 96f22dfe5820deb27a7428f22a5703a6a676b7f9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 17:32:50 -0800 Subject: [PATCH 36/81] allow -O2 to also call registerize, but without minification of globals that we do in asm.js --- tools/js-optimizer.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 7b774deebffaa..60414228efc17 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1399,7 +1399,7 @@ function denormalizeAsm(func, data) { // Very simple 'registerization', coalescing of variables into a smaller number, // as part of minification. Globals-level minification began in a previous pass, -// we receive minifierInfo which tells us how to rename globals. +// we receive minifierInfo which tells us how to rename globals. (Only in asm.js.) // // We do not optimize when there are switches, so this pass only makes sense with // relooping. @@ -1407,16 +1407,16 @@ function denormalizeAsm(func, data) { // we still need the eliminator? Closure? And in what order? Perhaps just // closure simple? function registerize(ast) { - assert(minifierInfo); - traverseGeneratedFunctions(ast, function(fun) { - // First, fix globals. Note that we know/assume that locals cannot shadow globals. - traverse(fun, function(node, type) { - if (type == 'name') { - var minified = minifierInfo.globals[node[1]]; - if (minified) node[1] = minified; - } - }); + if (minifierInfo) { + // First, fix globals. Note that we know/assume that locals cannot shadow globals. + traverse(fun, function(node, type) { + if (type == 'name') { + var minified = minifierInfo.globals[node[1]]; + if (minified) node[1] = minified; + } + }); + } if (asm) var asmData = normalizeAsm(fun); // Add parameters as a first (fake) var (with assignment), so they get taken into consideration var params = {}; // note: params are special, they can never share a register between them (see later) From f086eaa9beabfe409a0706315f4f738dc2bbcdab Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 17:45:39 -0800 Subject: [PATCH 37/81] minify function names in function definitions --- tools/js-optimizer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 60414228efc17..c3cb7f395b762 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1416,6 +1416,8 @@ function registerize(ast) { if (minified) node[1] = minified; } }); + assert(fun[1] in minifierInfo.globals, fun[1]); + fun[1] = minifierInfo.globals[fun[1]]; } if (asm) var asmData = normalizeAsm(fun); // Add parameters as a first (fake) var (with assignment), so they get taken into consideration From c65bba4e0d06db216c1176c4b02f98d816a9cfd7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 17:45:58 -0800 Subject: [PATCH 38/81] remove unnecessary semicolon; hello world minifies --- tools/js_optimizer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index b5213ac3f3a73..afbf1cc73987a 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -80,7 +80,7 @@ def minify_shell(self, shell): #print >> sys.stderr, "minified SHELL 3333333333333333", output, "\n44444444444444444444" code, metadata = output.split('// MINIFY_INFO:') self.globs = json.loads(metadata) - return output + return code def serialize(self): return json.dumps({ @@ -160,6 +160,7 @@ def run_on_js(filename, passes, js_engine, jcache): minifier = Minifier(js, js_engine) asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell).split('EMSCRIPTEN_FUNCS();'); + asm_shell_post = asm_shell_post.replace('});', '})'); pre += asm_shell_pre post = asm_shell_post + post From 99a6455bffe5598b0b33ff95d30b9b0fb61976b4 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:02:57 -0800 Subject: [PATCH 39/81] properly scan all globals, including function names, before applying them --- tools/js-optimizer.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index c3cb7f395b762..59ec1c3b1aa84 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -2177,6 +2177,7 @@ function minifyGlobals(ast) { var minified = {}; var next = 0; var first = true; // do not minify initial 'var asm =' + // find the globals traverse(ast, function(node, type) { if (type == 'var') { if (first) { @@ -2188,16 +2189,19 @@ function minifyGlobals(ast) { var name = vars[i][0]; vars[i][0] = minified[name] = minifierInfo.names[next++]; } - } else if (type == 'name') { + } + }); + // add all globals in function chunks, i.e. not here but passed to us + for (var i = 0; i < minifierInfo.globals.length; i++) { + name = minifierInfo.globals[i]; + minified[name] = minifierInfo.names[next++]; + } + // apply minification + traverse(ast, function(node, type) { + if (type == 'name') { var name = node[1]; if (name in minified) { node[1] = minified[name]; - } else if (name == 'EMSCRIPTEN_FUNCS') { - // minify all the globals - for (var i = 0; i < minifierInfo.globals.length; i++) { - name = minifierInfo.globals[i]; - minified[name] = minifierInfo.names[next++]; - } } } }); From 6742048b4a761d8064d495fc22248ca87ff5ea1d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:14:47 -0800 Subject: [PATCH 40/81] assertions on number of minified names --- tools/js-optimizer.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 59ec1c3b1aa84..fdc456f8c8bf9 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1418,6 +1418,7 @@ function registerize(ast) { }); assert(fun[1] in minifierInfo.globals, fun[1]); fun[1] = minifierInfo.globals[fun[1]]; + assert(fun[1]); } if (asm) var asmData = normalizeAsm(fun); // Add parameters as a first (fake) var (with assignment), so they get taken into consideration @@ -2187,6 +2188,7 @@ function minifyGlobals(ast) { var vars = node[1]; for (var i = 0; i < vars.length; i++) { var name = vars[i][0]; + assert(next < minifierInfo.names.length); vars[i][0] = minified[name] = minifierInfo.names[next++]; } } @@ -2194,6 +2196,7 @@ function minifyGlobals(ast) { // add all globals in function chunks, i.e. not here but passed to us for (var i = 0; i < minifierInfo.globals.length; i++) { name = minifierInfo.globals[i]; + assert(next < minifierInfo.names.length); minified[name] = minifierInfo.names[next++]; } // apply minification From 0764a9d32f80ae30ad824dcdc20b174653d2b185 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:15:07 -0800 Subject: [PATCH 41/81] increase number of minified names, and add func markers --- tools/js_optimizer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index afbf1cc73987a..bac693bfeac76 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -34,7 +34,7 @@ def __init__(self, js, js_engine): # Create list of valid short names - MAX_NAMES = 200#60000 + MAX_NAMES = 6000#0 INVALID_2 = set(['do', 'if', 'in']) INVALID_3 = set(['for', 'new', 'try', 'var', 'env']) @@ -161,8 +161,8 @@ def run_on_js(filename, passes, js_engine, jcache): minifier = Minifier(js, js_engine) asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell).split('EMSCRIPTEN_FUNCS();'); asm_shell_post = asm_shell_post.replace('});', '})'); - pre += asm_shell_pre - post = asm_shell_post + post + pre += asm_shell_pre + '\n' + start_funcs_marker + post = end_funcs_marker + asm_shell_post + post minify_info = minifier.serialize() else: From de3c3ca816dd92103802b9d222d00f561666208e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:17:14 -0800 Subject: [PATCH 42/81] for now, do not use rX as minified names, reserve that for registerize locals --- tools/js-optimizer.js | 2 +- tools/js_optimizer.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index fdc456f8c8bf9..102ced8bd5206 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1540,7 +1540,7 @@ function registerize(ast) { saved++; } else { reg = nextReg++; - fullNames[reg] = (asm ? (asmData.vars[name] ? 'd' : 'i') : 'r') + reg; // TODO: even smaller names + fullNames[reg] = (asm ? (asmData.vars[name] ? 'd' : 'i') : 'r') + reg; // XXX need to ensure we do not override used globals if (params[name]) paramRegs[reg] = 1; } varRegs[name] = reg; diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index bac693bfeac76..6a2f409117557 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -47,12 +47,14 @@ def __init__(self, js, js_engine): for a in init_possibles: for b in later_possibles: if len(self.names) >= MAX_NAMES: break + if a == 'r' and b in string.digits: continue # TODO: minify registerize names curr = a + b if curr not in INVALID_2: self.names.append(curr) for a in init_possibles: for b in later_possibles: for c in later_possibles: if len(self.names) >= MAX_NAMES: break + if a == 'r' and b in string.digits and c in string.digits: continue # TODO: minify registerize names curr = a + b + c if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names From e0fe8d85edff16483f0fa1e82653f0415c703cf2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:31:56 -0800 Subject: [PATCH 43/81] fix temporary workaround for register names --- tools/js_optimizer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 6a2f409117557..8c5edefb62066 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -47,14 +47,14 @@ def __init__(self, js, js_engine): for a in init_possibles: for b in later_possibles: if len(self.names) >= MAX_NAMES: break - if a == 'r' and b in string.digits: continue # TODO: minify registerize names + if a in 'id' and b in string.digits: continue # TODO: minify registerize names curr = a + b if curr not in INVALID_2: self.names.append(curr) for a in init_possibles: for b in later_possibles: for c in later_possibles: if len(self.names) >= MAX_NAMES: break - if a == 'r' and b in string.digits and c in string.digits: continue # TODO: minify registerize names + if a in 'id' and b in string.digits and c in string.digits: continue # TODO: minify registerize names curr = a + b + c if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names From 0d0ce4f677f293697123d4e237ca446dbc3fcc27 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:53:17 -0800 Subject: [PATCH 44/81] fix another name collision --- tools/js_optimizer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 8c5edefb62066..fda5e77ddb2d6 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -47,14 +47,14 @@ def __init__(self, js, js_engine): for a in init_possibles: for b in later_possibles: if len(self.names) >= MAX_NAMES: break - if a in 'id' and b in string.digits: continue # TODO: minify registerize names + if a in 'ida' and b in string.digits: continue # TODO: minify registerize names curr = a + b if curr not in INVALID_2: self.names.append(curr) for a in init_possibles: for b in later_possibles: for c in later_possibles: if len(self.names) >= MAX_NAMES: break - if a in 'id' and b in string.digits and c in string.digits: continue # TODO: minify registerize names + if a in 'ida' and b in string.digits and c in string.digits: continue # TODO: minify registerize names curr = a + b + c if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names @@ -167,6 +167,7 @@ def run_on_js(filename, passes, js_engine, jcache): post = end_funcs_marker + asm_shell_post + post minify_info = minifier.serialize() + #if DEBUG: print >> sys.stderr, 'minify info:', minify_info else: pre = '' post = '' From f1bbf0244b08dce2c2bfb9fc507d6088dcb6a596 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:59:39 -0800 Subject: [PATCH 45/81] save 0.0 in asm shell minification --- tools/js_optimizer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index fda5e77ddb2d6..f8dfddf20c2ba 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -66,6 +66,8 @@ def minify_shell(self, shell): # to minify all global names, we receive a dictionary back, which is then # used by the function processors + shell = shell.replace('0.0', '13371337') # avoid uglify doing 0.0 => 0 + # Find all globals in the JS functions code self.globs = [m.group(2) for m in func_sig.finditer(self.js)] @@ -82,7 +84,8 @@ def minify_shell(self, shell): #print >> sys.stderr, "minified SHELL 3333333333333333", output, "\n44444444444444444444" code, metadata = output.split('// MINIFY_INFO:') self.globs = json.loads(metadata) - return code + return code.replace('13371337', '0.0') + def serialize(self): return json.dumps({ From 5c5a9dd4bf35d95ffe83e655fe2a237241f0a96a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 20:42:36 -0800 Subject: [PATCH 46/81] make sure we use a C compiler to build libc. fixes #937, #938 --- emcc | 4 ++ tests/runner.py | 117 +++++++++++++++++++++++++----------------------- 2 files changed, 64 insertions(+), 57 deletions(-) diff --git a/emcc b/emcc index 58d49972066b9..ca23adf0bc3f2 100755 --- a/emcc +++ b/emcc @@ -1084,10 +1084,14 @@ try: os.path.join('libc', 'stdlib', 'strtod.c'), ]; + prev_cxx = os.environ.get('EMMAKEN_CXX') + if prev_cxx: os.environ['EMMAKEN_CXX'] = '' for src in libc_files: o = in_temp(os.path.basename(src) + '.o') execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', src), '-o', o], stdout=stdout, stderr=stderr) o_s.append(o) + if prev_cxx: os.environ['EMMAKEN_CXX'] = prev_cxx + shared.Building.link(o_s, in_temp('libc.bc')) return in_temp('libc.bc') diff --git a/tests/runner.py b/tests/runner.py index cdc8684b98088..2a41d9531b0a9 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -12024,66 +12024,69 @@ def test_emcc_caching(self): EMCC_CACHE = Cache.dirname - restore() - - Cache.erase() - assert not os.path.exists(EMCC_CACHE) + for compiler in [EMCC, EMXX]: + print compiler - try: - os.environ['EMCC_DEBUG'] ='1' - self.working_dir = os.path.join(TEMP_DIR, 'emscripten_temp') + restore() - # Building a file that doesn't need cached stuff should not trigger cache generation - output = self.do([EMCC, path_from_root('tests', 'hello_world.cpp')]) - assert INCLUDING_MESSAGE.replace('X', 'libc') not in output - assert BUILDING_MESSAGE.replace('X', 'libc') not in output - self.assertContained('hello, world!', run_js('a.out.js')) + Cache.erase() assert not os.path.exists(EMCC_CACHE) - try_delete('a.out.js') - - basebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-0-basebc.bc') - dcebc_name1 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-1-linktime.bc') - dcebc_name2 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-2-linktime.bc') - ll_names = [os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-X-ll.ll').replace('X', str(x)) for x in range(2,5)] - - # Building a file that *does* need dlmalloc *should* trigger cache generation, but only the first time - for filename, libname in [('hello_malloc.cpp', 'libc'), ('hello_libcxx.cpp', 'libcxx')]: - for i in range(3): - print filename, libname, i - self.clear() - dcebc_name = dcebc_name1 if i == 0 else dcebc_name2 - try_delete(basebc_name) # we might need to check this file later - try_delete(dcebc_name) # we might need to check this file later - for ll_name in ll_names: try_delete(ll_name) - output = self.do([EMCC, '-O' + str(i), '-s', 'RELOOP=0', '--llvm-lto', '0', path_from_root('tests', filename)]) - #print output - assert INCLUDING_MESSAGE.replace('X', libname) in output - if libname == 'libc': - assert INCLUDING_MESSAGE.replace('X', 'libcxx') not in output # we don't need libcxx in this code - else: - assert INCLUDING_MESSAGE.replace('X', 'libc') in output # libcxx always forces inclusion of libc - assert (BUILDING_MESSAGE.replace('X', libname) in output) == (i == 0), 'Must only build the first time' - self.assertContained('hello, world!', run_js('a.out.js')) - assert os.path.exists(EMCC_CACHE) - assert os.path.exists(os.path.join(EMCC_CACHE, libname + '.bc')) - if libname == 'libcxx': - print os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size, os.stat(basebc_name).st_size, os.stat(dcebc_name).st_size - assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 1800000, 'libc++ is big' - assert os.stat(basebc_name).st_size > 1800000, 'libc++ is indeed big' - assert os.stat(dcebc_name).st_size < 750000, 'Dead code elimination must remove most of libc++' - # should only have metadata in -O0, not 1 and 2 - if i > 0: - for ll_name in ll_names: - ll = None - try: - ll = open(ll_name).read() - break - except: - pass - assert ll - assert ll.count('\n!') < 10 # a few lines are left even in -O1 and -O2 - finally: - del os.environ['EMCC_DEBUG'] + + try: + os.environ['EMCC_DEBUG'] ='1' + self.working_dir = os.path.join(TEMP_DIR, 'emscripten_temp') + + # Building a file that doesn't need cached stuff should not trigger cache generation + output = self.do([compiler, path_from_root('tests', 'hello_world.cpp')]) + assert INCLUDING_MESSAGE.replace('X', 'libc') not in output + assert BUILDING_MESSAGE.replace('X', 'libc') not in output + self.assertContained('hello, world!', run_js('a.out.js')) + assert not os.path.exists(EMCC_CACHE) + try_delete('a.out.js') + + basebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-0-basebc.bc') + dcebc_name1 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-1-linktime.bc') + dcebc_name2 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-2-linktime.bc') + ll_names = [os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-X-ll.ll').replace('X', str(x)) for x in range(2,5)] + + # Building a file that *does* need dlmalloc *should* trigger cache generation, but only the first time + for filename, libname in [('hello_malloc.cpp', 'libc'), ('hello_libcxx.cpp', 'libcxx')]: + for i in range(3): + print filename, libname, i + self.clear() + dcebc_name = dcebc_name1 if i == 0 else dcebc_name2 + try_delete(basebc_name) # we might need to check this file later + try_delete(dcebc_name) # we might need to check this file later + for ll_name in ll_names: try_delete(ll_name) + output = self.do([compiler, '-O' + str(i), '-s', 'RELOOP=0', '--llvm-lto', '0', path_from_root('tests', filename)]) + #print output + assert INCLUDING_MESSAGE.replace('X', libname) in output + if libname == 'libc': + assert INCLUDING_MESSAGE.replace('X', 'libcxx') not in output # we don't need libcxx in this code + else: + assert INCLUDING_MESSAGE.replace('X', 'libc') in output # libcxx always forces inclusion of libc + assert (BUILDING_MESSAGE.replace('X', libname) in output) == (i == 0), 'Must only build the first time' + self.assertContained('hello, world!', run_js('a.out.js')) + assert os.path.exists(EMCC_CACHE) + assert os.path.exists(os.path.join(EMCC_CACHE, libname + '.bc')) + if libname == 'libcxx': + print os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size, os.stat(basebc_name).st_size, os.stat(dcebc_name).st_size + assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 1800000, 'libc++ is big' + assert os.stat(basebc_name).st_size > 1800000, 'libc++ is indeed big' + assert os.stat(dcebc_name).st_size < 750000, 'Dead code elimination must remove most of libc++' + # should only have metadata in -O0, not 1 and 2 + if i > 0: + for ll_name in ll_names: + ll = None + try: + ll = open(ll_name).read() + break + except: + pass + assert ll + assert ll.count('\n!') < 10 # a few lines are left even in -O1 and -O2 + finally: + del os.environ['EMCC_DEBUG'] # Manual cache clearing assert os.path.exists(EMCC_CACHE) From 92a6658da855b0e6bb9bd157992912e242985e76 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 09:12:35 -0800 Subject: [PATCH 47/81] minify by default in -O2+, unless -g --- emcc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/emcc b/emcc index 58d49972066b9..035180ac21aa6 100755 --- a/emcc +++ b/emcc @@ -332,13 +332,11 @@ Options that are modified or new in %s include: output HTML but with suffix .data.compress --minify 0: Do not minify the generated JavaScript's - whitespace (default if closure compiler - will not be run) + whitespace (default in -O0, -O1, or if + -g is used) 1: Minify the generated JavaScript's - whitespace (default if closure compiler - will be run). Note that this by itself - will not minify the code (closure does - that) + whitespace (default in -O2+, assuming + -g is not used) --split Splits the resulting javascript file into pieces to ease debugging. This option only works if @@ -983,7 +981,7 @@ try: closure = False if minify_whitespace is None: - minify_whitespace = closure # if closure is run, minify whitespace + minify_whitespace = opt_level >= 2 and not keep_js_debug ## Compile source code to bitcode From a69c712141706578a6dcd4f092bf0222273c8e0a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 09:21:15 -0800 Subject: [PATCH 48/81] test for asm minifier sizes --- tests/runner.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/runner.py b/tests/runner.py index cdc8684b98088..eb7c468f3b88a 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -8927,6 +8927,32 @@ def test_unaligned_memory_2(self): Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate() self.assertContained('testString = Hello, World!', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + def test_asm_minify(self): + def test(args): + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop_malloc.cpp')] + args).communicate() + self.assertContained('hello, world!', run_js(self.in_dir('a.out.js'))) + return open(self.in_dir('a.out.js')).read() + + src = test([]) + assert 'function _malloc' in src + + src = test(['-O2', '-s', 'ASM_JS=1']) + normal_size = len(src) + print 'normal', normal_size + assert 'function _malloc' not in src + + src = test(['-O2', '-s', 'ASM_JS=1', '--minify', '0']) + unminified_size = len(src) + print 'unminified', unminified_size + assert unminified_size > normal_size + assert 'function _malloc' not in src + + src = test(['-O2', '-s', 'ASM_JS=1', '-g']) + debug_size = len(src) + print 'debug', debug_size + assert debug_size > unminified_size + assert 'function _malloc' in src + def test_l_link(self): # Linking with -lLIBNAME and -L/DIRNAME should work From 2829db174b7a5f9189d3a58bf1f39f59365d2c60 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 09:23:40 -0800 Subject: [PATCH 49/81] add asm2g test pass for asm -O2 -g --- tests/runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index eb7c468f3b88a..4d0fa885d9135 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -445,7 +445,7 @@ def setup_runtimelink_test(self): if len(sys.argv) == 2 and 'ALL.' in sys.argv[1]: ignore, test = sys.argv[1].split('.') print 'Running all test modes on test "%s"' % test - sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test] + sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 'asm2g'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test] class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline ## Does a complete test - builds, runs, checks output, etc. @@ -8524,8 +8524,8 @@ def setUp(self): exec('o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2"])') # asm.js - #exec('asm = make_run("asm", compiler=CLANG, emcc_args=["-O0", "-s", "ASM_JS=1"])') exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1"])') + exec('asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1", "-g"])') # Make custom runs with various options for compiler, quantum, embetter, typed_arrays, llvm_opts in [ From d4d5bdf5e12d0a0b1d1094edd4c048d8dfa1f0c1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 09:26:23 -0800 Subject: [PATCH 50/81] asm2g fix --- tests/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index 4d0fa885d9135..9126017740077 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -445,7 +445,7 @@ def setup_runtimelink_test(self): if len(sys.argv) == 2 and 'ALL.' in sys.argv[1]: ignore, test = sys.argv[1].split('.') print 'Running all test modes on test "%s"' % test - sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 'asm2g'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test] + sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 'asm2g.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test] class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline ## Does a complete test - builds, runs, checks output, etc. From a43d5b5a146a4cfc654c2c1dbd05001e58977273 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 09:28:54 -0800 Subject: [PATCH 51/81] do not emit generated functions suffix when no longer needed --- tools/js_optimizer.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index f8dfddf20c2ba..d089a98957de9 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -171,6 +171,9 @@ def run_on_js(filename, passes, js_engine, jcache): minify_info = minifier.serialize() #if DEBUG: print >> sys.stderr, 'minify info:', minify_info + # remove suffix if no longer needed + if 'last' in passes: + post = post.split(suffix_marker)[0] else: pre = '' post = '' From 74a855a0d5a8d1708f47e6531a22ca6ae3f8f76e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 10:04:07 -0800 Subject: [PATCH 52/81] improve non-asm parsing of generated functions area to be identical in EMCC_DEBUG=1 and 2 --- tests/runner.py | 2 ++ tools/js_optimizer.py | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index 9126017740077..025586503cb64 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7311,6 +7311,8 @@ def image_compare(output, err): return output + self.emcc_args += ['--minify', '0'] # to compare the versions + def do_test(): self.do_run(open(path_from_root('tests', 'openjpeg', 'codec', 'j2k_to_image.c'), 'r').read(), 'Successfully generated', # The real test for valid output is in image_compare diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index d089a98957de9..b52f23240d35a 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -148,12 +148,19 @@ def run_on_js(filename, passes, js_engine, jcache): if suffix: if not asm_registerize: pre = js[:start_funcs + len(start_funcs_marker)] - post = js[end_funcs:] + post = js[end_funcs + len(end_funcs_marker):] js = js[start_funcs + len(start_funcs_marker):end_funcs] if 'asm' not in passes: # can have Module[..] and inlining prevention code, push those to post - for line in js.split('\n'): + class Finals: + buf = [] + def process(line): if len(line) > 0 and not line.startswith((' ', 'function', '}')): - post = line + '\n' + post + Finals.buf.append(line) + return False + return True + js = '\n'.join(filter(process, js.split('\n'))) + post = '\n'.join(Finals.buf) + '\n' + post + post = end_funcs_marker + post else: # We need to split out the asm shell as well, for minification pre = js[:start_asm + len(start_asm_marker)] From 99ac7e40feb2739edfecd0c3f962ec9f666607f4 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 10:10:29 -0800 Subject: [PATCH 53/81] make sure to remove trivial whitespace --- emcc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/emcc b/emcc index 035180ac21aa6..e8999ceb29e49 100755 --- a/emcc +++ b/emcc @@ -1361,11 +1361,10 @@ try: flush_js_optimizer_queue() - if not minify_whitespace: - # Remove some trivial whitespace - src = open(final).read() - src = re.sub(r'\n+[ \n]*\n+', '\n', src) - open(final, 'w').write(src) + # Remove some trivial whitespace # TODO: do not run when compress has already been done on all parts of the code + src = open(final).read() + src = re.sub(r'\n+[ \n]*\n+', '\n', src) + open(final, 'w').write(src) # If we were asked to also generate HTML, do that if final_suffix == 'html': From d937b1804545832eea96713850e04ee3f484ffb8 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 11:15:39 -0800 Subject: [PATCH 54/81] update test_chunking --- tests/runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index 025586503cb64..d268672afaa0e 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -9688,8 +9688,8 @@ def test_chunking(self): try: os.environ['EMCC_DEBUG'] = '1' for asm, linkable, chunks, js_chunks in [ - (0, 0, 3, 2), (0, 1, 4, 4), - (1, 0, 3, 2), (1, 1, 4, 5) + (0, 0, 3, 2), (0, 1, 3, 4), + (1, 0, 3, 2), (1, 1, 3, 4) ]: print asm, linkable, chunks, js_chunks output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm], stdout=PIPE, stderr=PIPE).communicate() From e2c783622d9d6e8b2b73fd26d3847d704d69a02e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 11:32:02 -0800 Subject: [PATCH 55/81] update test_emcc --- tests/runner.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index d268672afaa0e..e4cc2d27cec48 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -8698,7 +8698,8 @@ def test_emcc(self): assert 'SAFE_HEAP' not in generated, 'safe heap should not be used by default' assert ': while(' not in generated, 'when relooping we also js-optimize, so there should be no labelled whiles' if closure: - assert 'Module._main=' in generated, 'closure compiler should have been run (and output should be minified)' + if opt_level <= 1: assert 'Module._main =' in generated, 'closure compiler should have been run' + elif opt_level >= 2: assert 'Module._main=' in generated, 'closure compiler should have been run (and output should be minified)' else: # closure has not been run, we can do some additional checks. TODO: figure out how to do these even with closure assert 'Module._main = ' not in generated, 'closure compiler should not have been run' @@ -8707,14 +8708,15 @@ def test_emcc(self): assert ('assert(STACKTOP < STACK_MAX' in generated) == (opt_level == 0), 'assertions should be in opt == 0' assert 'var $i;' in generated or 'var $i_0' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or 'var $i_04;' in generated, 'micro opts should always be on' if opt_level >= 2: - assert re.search('HEAP8\[\$?\w+ \+ \(+\$?\w+ ', generated) or re.search('HEAP8\[HEAP32\[', generated), 'eliminator should create compound expressions, and fewer one-time vars' # also in -O1, but easier to test in -O2 + assert re.search('HEAP8\[\$?\w+ ?\+ ?\(+\$?\w+ ?', generated) or re.search('HEAP8\[HEAP32\[', generated), 'eliminator should create compound expressions, and fewer one-time vars' # also in -O1, but easier to test in -O2 assert ('_puts(' in generated) == (opt_level >= 1), 'with opt >= 1, llvm opts are run and they should optimize printf to puts' - assert 'function _main() {' in generated, 'Should be unminified, including whitespace' + if opt_level <= 1 or '-g' in params: assert 'function _main() {' in generated, 'Should be unminified, including whitespace' + elif opt_level >= 2: assert 'function _main(){' in generated, 'Should be whitespace-minified' # emcc -s RELOOP=1 src.cpp ==> should pass -s to emscripten.py. --typed-arrays is a convenient alias for -s USE_TYPED_ARRAYS for params, test, text in [ - (['-s', 'ASM_JS=1', '-O2'], lambda generated: 'var i1 = 0' in generated, 'registerize is run by default in -O2'), - (['-s', 'ASM_JS=1', '-O2', '-g'], lambda generated: 'var i1 = 0' not in generated, 'registerize is cancelled by -g'), + (['-s', 'ASM_JS=1', '-O2'], lambda generated: 'var i1=0' in generated, 'registerize is run by default in -O2'), + (['-s', 'ASM_JS=1', '-O2', '-g'], lambda generated: 'var i1=0' not in generated, 'registerize is cancelled by -g'), (['-s', 'INLINING_LIMIT=0'], lambda generated: 'function _dump' in generated, 'no inlining without opts'), (['-O3', '-s', 'INLINING_LIMIT=0', '--closure', '0'], lambda generated: 'function _dump' not in generated, 'lto/inlining'), (['-Os', '--llvm-lto', '1'], lambda generated: 'function _dump' in generated, '-Os disables inlining'), From 48d96fcb6433149a992ba811894c7e690de413eb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 11:40:44 -0800 Subject: [PATCH 56/81] add testing for asm_js minification/registerization --- tests/runner.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index e4cc2d27cec48..91de2f74dd924 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -8715,8 +8715,9 @@ def test_emcc(self): # emcc -s RELOOP=1 src.cpp ==> should pass -s to emscripten.py. --typed-arrays is a convenient alias for -s USE_TYPED_ARRAYS for params, test, text in [ - (['-s', 'ASM_JS=1', '-O2'], lambda generated: 'var i1=0' in generated, 'registerize is run by default in -O2'), - (['-s', 'ASM_JS=1', '-O2', '-g'], lambda generated: 'var i1=0' not in generated, 'registerize is cancelled by -g'), + (['-s', 'ASM_JS=1', '-O2'], lambda generated: 'var i1=0' in generated and not 'function _main' in generated, 'registerize/minify is run by default in -O2'), + (['-s', 'ASM_JS=1', '-O2', '--minify', '0'], lambda generated: 'var i1 = 0' in generated and not 'function _main' in generated, 'minify is cancelled, but not registerize'), + (['-s', 'ASM_JS=1', '-O2', '-g'], lambda generated: 'var i1=0' not in generated and 'var i1 = 0' not in generated and 'function _main' in generated, 'registerize/minify is cancelled by -g'), (['-s', 'INLINING_LIMIT=0'], lambda generated: 'function _dump' in generated, 'no inlining without opts'), (['-O3', '-s', 'INLINING_LIMIT=0', '--closure', '0'], lambda generated: 'function _dump' not in generated, 'lto/inlining'), (['-Os', '--llvm-lto', '1'], lambda generated: 'function _dump' in generated, '-Os disables inlining'), From 9f9be7e02e6f8173cf883f01ccef71892b4e33e0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 13:30:46 -0800 Subject: [PATCH 57/81] compress asm shell --- tools/js_optimizer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index b52f23240d35a..94883a90c5a0a 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -59,7 +59,7 @@ def __init__(self, js, js_engine): if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names - def minify_shell(self, shell): + def minify_shell(self, shell, compress): #print >> sys.stderr, "MINIFY SHELL 1111111111", shell, "\n222222222222222" # Run through js-optimizer.js to find and minify the global symbols # We send it the globals, which it parses at the proper time. JS decides how @@ -79,7 +79,7 @@ def minify_shell(self, shell): f.write('// MINIFY_INFO:' + self.serialize()) f.close() - output = subprocess.Popen(self.js_engine + [JS_OPTIMIZER, temp_file, 'minifyGlobals', 'noPrintMetadata'], stdout=subprocess.PIPE).communicate()[0] + output = subprocess.Popen(self.js_engine + [JS_OPTIMIZER, temp_file, 'minifyGlobals', 'noPrintMetadata'] + (['compress'] if compress else []), stdout=subprocess.PIPE).communicate()[0] assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + output #print >> sys.stderr, "minified SHELL 3333333333333333", output, "\n44444444444444444444" code, metadata = output.split('// MINIFY_INFO:') @@ -171,7 +171,7 @@ def process(line): js = js[start_funcs + len(start_funcs_marker):end_funcs] minifier = Minifier(js, js_engine) - asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell).split('EMSCRIPTEN_FUNCS();'); + asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell, 'compress' in passes).split('EMSCRIPTEN_FUNCS();'); asm_shell_post = asm_shell_post.replace('});', '})'); pre += asm_shell_pre + '\n' + start_funcs_marker post = end_funcs_marker + asm_shell_post + post From d3d23885170ad1151277e8980d3b41313ed7b9a3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 14:07:05 -0800 Subject: [PATCH 58/81] refactor registerize global substitution --- tools/js-optimizer.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 102ced8bd5206..f944eb9bc3fe9 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1408,18 +1408,6 @@ function denormalizeAsm(func, data) { // closure simple? function registerize(ast) { traverseGeneratedFunctions(ast, function(fun) { - if (minifierInfo) { - // First, fix globals. Note that we know/assume that locals cannot shadow globals. - traverse(fun, function(node, type) { - if (type == 'name') { - var minified = minifierInfo.globals[node[1]]; - if (minified) node[1] = minified; - } - }); - assert(fun[1] in minifierInfo.globals, fun[1]); - fun[1] = minifierInfo.globals[fun[1]]; - assert(fun[1]); - } if (asm) var asmData = normalizeAsm(fun); // Add parameters as a first (fake) var (with assignment), so they get taken into consideration var params = {}; // note: params are special, they can never share a register between them (see later) @@ -1456,6 +1444,18 @@ function registerize(ast) { } }); vacuum(fun); + if (minifierInfo) { + // Fix globals. Note that we know/assume that locals cannot shadow globals. + traverse(fun, function(node, type) { + if (type == 'name') { + var minified = minifierInfo.globals[node[1]]; + if (minified) node[1] = minified; + } + }); + assert(fun[1] in minifierInfo.globals, fun[1]); + fun[1] = minifierInfo.globals[fun[1]]; + assert(fun[1]); + } // Find the # of uses of each variable. // While doing so, check if all a variable's uses are dominated in a simple // way by a simple assign, if so, then we can assign its register to it From 4c95c34ca8166f49f995ea8fe082cd0aaa70d839 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 15:37:49 -0800 Subject: [PATCH 59/81] use minified names in registerize for locals --- tests/runner.py | 2 + tools/js-optimizer.js | 65 +++++++++++++++++-- .../test-js-optimizer-asm-regs-min-output.js | 36 ++++++++++ tools/test-js-optimizer-asm-regs-min.js | 37 +++++++++++ 4 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 tools/test-js-optimizer-asm-regs-min-output.js create mode 100644 tools/test-js-optimizer-asm-regs-min.js diff --git a/tests/runner.py b/tests/runner.py index 91de2f74dd924..af12ed80e7e8b 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -9670,6 +9670,8 @@ def test_js_optimizer(self): ['asm', 'eliminate']), (path_from_root('tools', 'test-js-optimizer-asm-regs.js'), open(path_from_root('tools', 'test-js-optimizer-asm-regs-output.js')).read(), ['asm', 'registerize']), + (path_from_root('tools', 'test-js-optimizer-asm-regs-min.js'), open(path_from_root('tools', 'test-js-optimizer-asm-regs-min-output.js')).read(), + ['asm', 'registerize']), (path_from_root('tools', 'test-js-optimizer-asm-pre.js'), open(path_from_root('tools', 'test-js-optimizer-asm-pre-output.js')).read(), ['asm', 'simplifyExpressionsPre']), (path_from_root('tools', 'test-js-optimizer-asm-last.js'), open(path_from_root('tools', 'test-js-optimizer-asm-last-output.js')).read(), diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index f944eb9bc3fe9..5b2e618823d0b 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1445,16 +1445,69 @@ function registerize(ast) { }); vacuum(fun); if (minifierInfo) { - // Fix globals. Note that we know/assume that locals cannot shadow globals. + assert(asm); + var usedGlobals = {}; + var nextLocal = 0; + // Minify globals using the mapping we were given traverse(fun, function(node, type) { if (type == 'name') { - var minified = minifierInfo.globals[node[1]]; - if (minified) node[1] = minified; + var name = node[1]; + var minified = minifierInfo.globals[name]; + if (minified) { + assert(!localVars[name]); // locals must not shadow globals, or else we don't know which is which + if (localVars[minified]) { + // trying to minify a global into a name used locally. rename all the locals + var newName = '$_newLocal_' + (nextLocal++); + assert(!localVars[newName]); + if (params[minified]) { + params[newName] = 1; + delete params[minified]; + } + localVars[newName] = 1; + delete localVars[minified]; + asmData.vars[newName] = asmData.vars[minified]; + delete asmData.vars[minified]; + asmData.params[newName] = asmData.params[minified]; + delete asmData.params[minified]; + traverse(fun, function(node, type) { + if (type == 'name' && node[1] == minified) { + node[1] = newName; + } + }); + if (fun[2]) { + for (var i = 0; i < fun[2].length; i++) { + if (fun[2][i] == minified) fun[2][i] = newName; + } + } + } + node[1] = minified; + usedGlobals[minified] = 1; + } } }); assert(fun[1] in minifierInfo.globals, fun[1]); fun[1] = minifierInfo.globals[fun[1]]; assert(fun[1]); + var nextRegName = 0; + } + var regTypes = {}; + function getNewRegName(num, name) { + if (!asm) return 'r' + num; + var type = asmData.vars[name]; + if (!minifierInfo) { + var ret = (type ? 'd' : 'i') + num; + regTypes[ret] = type; + return ret; + } + // find the next free minified name that is not used by a global that shows up in this function + while (nextRegName < minifierInfo.names.length) { + var ret = minifierInfo.names[nextRegName++]; + if (!usedGlobals[ret]) { + regTypes[ret] = type; + return ret; + } + } + assert('ran out of names'); } // Find the # of uses of each variable. // While doing so, check if all a variable's uses are dominated in a simple @@ -1540,7 +1593,7 @@ function registerize(ast) { saved++; } else { reg = nextReg++; - fullNames[reg] = (asm ? (asmData.vars[name] ? 'd' : 'i') : 'r') + reg; // XXX need to ensure we do not override used globals + fullNames[reg] = getNewRegName(reg, name); if (params[name]) paramRegs[reg] = 1; } varRegs[name] = reg; @@ -1584,7 +1637,7 @@ function registerize(ast) { if (loopRegs[loops]) { if (asm) { loopRegs[loops].forEach(function(loopReg) { - freeRegsClasses[fullNames[loopReg][0] == 'i' ? ASM_INT : ASM_DOUBLE].push(loopReg); + freeRegsClasses[regTypes[fullNames[loopReg]]].push(loopReg); }); } else { freeRegsClasses = freeRegsClasses.concat(loopRegs[loops]); @@ -1620,7 +1673,7 @@ function registerize(ast) { }; for (var i = 1; i < nextReg; i++) { var reg = fullNames[i]; - var type = reg[0] == 'i' ? ASM_INT : ASM_DOUBLE + var type = regTypes[reg]; if (!paramRegs[i]) { finalAsmData.vars[reg] = type; } else { diff --git a/tools/test-js-optimizer-asm-regs-min-output.js b/tools/test-js-optimizer-asm-regs-min-output.js new file mode 100644 index 0000000000000..b8088022b956a --- /dev/null +++ b/tools/test-js-optimizer-asm-regs-min-output.js @@ -0,0 +1,36 @@ +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} + diff --git a/tools/test-js-optimizer-asm-regs-min.js b/tools/test-js-optimizer-asm-regs-min.js new file mode 100644 index 0000000000000..c126946de4db5 --- /dev/null +++ b/tools/test-js-optimizer-asm-regs-min.js @@ -0,0 +1,37 @@ +function collideLocal(x) { + x = x | 0; + var a = 0; + a = x*x; + aGlobal(a); // aGlobal needs to be minified into a, but a is used! + bGlobal(x); +} +function collideLocal(x) { + x = x | 0; + var i1 = 0; + i1 = x*x; + aGlobal(i1); + bGlobal(x); // bGlobal needs to be minified into i1, but i1 is used! +} +function collideLocal(a) { + a = a | 0; + var x = 0; + x = a*a; + aGlobal(x); // aGlobal needs to be minified into a, but a is used by a param! + bGlobal(a); +} +function collideLocal(i1) { + i1 = i1 | 0; + var x = 0; + x = i1*i1; + aGlobal(x); + bGlobal(i1); // bGlobal needs to be minified into i1, but i1 is used by a param! +} +function collideLocal(i1) { + i1 = i1 | 0; + var a = 0; + a = i1*i1; + aGlobal(a); // multiple collisions, a and i1 + bGlobal(i1); +} +// EMSCRIPTEN_GENERATED_FUNCTIONS +// MINIFY_INFO: { "names": ["a", "b", "c", "d", "e", "f", "g", "h", "i", "i1", "cl"], "globals": { "aGlobal": "a", "bGlobal": "i1", "collideLocal": "cl" } } From 0ecad78d552f20c7dfc454489df3eba61361fa06 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 15:47:41 -0800 Subject: [PATCH 60/81] remove limitations on minified names --- tools/js-optimizer.js | 2 +- tools/js_optimizer.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 5b2e618823d0b..2b9064b267df3 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1454,7 +1454,7 @@ function registerize(ast) { var name = node[1]; var minified = minifierInfo.globals[name]; if (minified) { - assert(!localVars[name]); // locals must not shadow globals, or else we don't know which is which + assert(!localVars[name], name); // locals must not shadow globals, or else we don't know which is which if (localVars[minified]) { // trying to minify a global into a name used locally. rename all the locals var newName = '$_newLocal_' + (nextLocal++); diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 94883a90c5a0a..98b346845ee42 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -47,14 +47,12 @@ def __init__(self, js, js_engine): for a in init_possibles: for b in later_possibles: if len(self.names) >= MAX_NAMES: break - if a in 'ida' and b in string.digits: continue # TODO: minify registerize names curr = a + b if curr not in INVALID_2: self.names.append(curr) for a in init_possibles: for b in later_possibles: for c in later_possibles: if len(self.names) >= MAX_NAMES: break - if a in 'ida' and b in string.digits and c in string.digits: continue # TODO: minify registerize names curr = a + b + c if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names From b7093afaf4bb9fa593d687d6c9646289e8d75cff Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 16:50:41 -0800 Subject: [PATCH 61/81] do not wipe out everything after the generated functions suffix; fixes test_embind --- tools/js_optimizer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 98b346845ee42..60093bca24449 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -118,7 +118,8 @@ def run_on_js(filename, passes, js_engine, jcache): suffix_start = js.find(suffix_marker) suffix = '' if suffix_start >= 0: - suffix = js[suffix_start:js.find('\n', suffix_start)] + '\n' + suffix_end = js.find('\n', suffix_start) + suffix = js[suffix_start:suffix_end] + '\n' # if there is metadata, we will run only on the generated functions. If there isn't, we will run on everything. generated = set(eval(suffix[len(suffix_marker)+1:])) @@ -178,7 +179,10 @@ def process(line): #if DEBUG: print >> sys.stderr, 'minify info:', minify_info # remove suffix if no longer needed if 'last' in passes: - post = post.split(suffix_marker)[0] + suffix_start = post.find(suffix_marker) + suffix_end = post.find('\n', suffix_start) + post = post[:suffix_start] + post[suffix_end:] + else: pre = '' post = '' From 4d1e778aa727abcc6d9b2ab0e39a8348bcb971df Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 19:20:36 -0800 Subject: [PATCH 62/81] optimize traverseGeneratedFunctions --- tools/js-optimizer.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 2b9064b267df3..8df467f89931c 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -220,12 +220,15 @@ function traverseGenerated(ast, pre, post, stack) { function traverseGeneratedFunctions(ast, callback) { assert(generatedFunctions); - traverse(ast, function(node) { - if (node[0] == 'defun') { - callback(node); - return null; + if (ast[0] == 'toplevel') { + var stats = ast[1]; + for (var i = 0; i < stats.length; i++) { + var curr = stats[i]; + if (curr[0] == 'defun') callback(curr); } - }); + } else if (ast[0] == 'defun') { + callback(ast); + } } // Walk the ast in a simple way, with an understanding of which JS variables are defined) From ca6e55cbf2fa746697527327aa6f9f5c3b3cab8b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 19:26:17 -0800 Subject: [PATCH 63/81] update test_emcc --- tests/runner.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index af12ed80e7e8b..f67b826db16e8 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -8715,9 +8715,9 @@ def test_emcc(self): # emcc -s RELOOP=1 src.cpp ==> should pass -s to emscripten.py. --typed-arrays is a convenient alias for -s USE_TYPED_ARRAYS for params, test, text in [ - (['-s', 'ASM_JS=1', '-O2'], lambda generated: 'var i1=0' in generated and not 'function _main' in generated, 'registerize/minify is run by default in -O2'), - (['-s', 'ASM_JS=1', '-O2', '--minify', '0'], lambda generated: 'var i1 = 0' in generated and not 'function _main' in generated, 'minify is cancelled, but not registerize'), - (['-s', 'ASM_JS=1', '-O2', '-g'], lambda generated: 'var i1=0' not in generated and 'var i1 = 0' not in generated and 'function _main' in generated, 'registerize/minify is cancelled by -g'), + (['-s', 'ASM_JS=1', '-O2'], lambda generated: 'var b=0' in generated and not 'function _main' in generated, 'registerize/minify is run by default in -O2'), + (['-s', 'ASM_JS=1', '-O2', '--minify', '0'], lambda generated: 'var b = 0' in generated and not 'function _main' in generated, 'minify is cancelled, but not registerize'), + (['-s', 'ASM_JS=1', '-O2', '-g'], lambda generated: 'var b=0' not in generated and 'var b = 0' not in generated and 'function _main' in generated, 'registerize/minify is cancelled by -g'), (['-s', 'INLINING_LIMIT=0'], lambda generated: 'function _dump' in generated, 'no inlining without opts'), (['-O3', '-s', 'INLINING_LIMIT=0', '--closure', '0'], lambda generated: 'function _dump' not in generated, 'lto/inlining'), (['-Os', '--llvm-lto', '1'], lambda generated: 'function _dump' in generated, '-Os disables inlining'), From 4794e95b9ba2ab9104d6da7b0a6c7bf31c2f812a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 19:36:05 -0800 Subject: [PATCH 64/81] move addFinalReturns to simplyExpressionsPre so it runs even in -g --- tools/js-optimizer.js | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 8df467f89931c..834c99e338799 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -540,9 +540,31 @@ function simplifyExpressionsPre(ast) { }); } + function addFinalReturns(ast) { + traverseGeneratedFunctions(ast, function(fun) { + var returnType = null; + traverse(fun, function(node, type) { + if (type == 'return' && node[1]) { + returnType = detectAsmCoercion(node[1]); + } + }); + // Add a final return if one is missing. + if (returnType !== null) { + var stats = getStatements(fun); + var last = stats[stats.length-1]; + if (last[0] != 'return') { + var returnValue = ['num', 0]; + if (returnType == ASM_DOUBLE) returnValue = ['unary-prefix', '+', returnValue]; + stats.push(['return', returnValue]); + } + } + }); + } + simplifyBitops(ast); joinAdditions(ast); // simplifyZeroComp(ast); TODO: investigate performance + if (asm) addFinalReturns(ast); } // In typed arrays mode 2, we can have @@ -1430,7 +1452,6 @@ function registerize(ast) { // We also mark local variables - i.e., having a var definition var localVars = {}; var hasSwitch = false; // we cannot optimize variables if there is a switch - var returnType = null; // for asm traverse(fun, function(node, type) { if (type == 'var') { node[1].forEach(function(defined) { localVars[defined[0]] = 1 }); @@ -1442,8 +1463,6 @@ function registerize(ast) { } } else if (type == 'switch') { hasSwitch = true; - } else if (asm && type == 'return' && node[1]) { - returnType = detectAsmCoercion(node[1]); } }); vacuum(fun); @@ -1685,17 +1704,6 @@ function registerize(ast) { } } denormalizeAsm(fun, finalAsmData); - // Add a final return if one is missing. This is not strictly a register operation, but - // this pass traverses the entire AST anyhow so adding it here is efficient. - if (returnType !== null) { - var stats = getStatements(fun); - var last = stats[stats.length-1]; - if (last[0] != 'return') { - var returnValue = ['num', 0]; - if (returnType == ASM_DOUBLE) returnValue = ['unary-prefix', '+', returnValue]; - stats.push(['return', returnValue]); - } - } } }); } From b5c3e1bda0ef9080228f452ce7ca8c60d3dcf452 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 20:22:33 -0800 Subject: [PATCH 65/81] remove coercions on asm function calls that have no capturing variables --- tools/js-optimizer.js | 12 ++++++++++-- tools/test-js-optimizer-asm-pre-output.js | 2 ++ tools/test-js-optimizer-asm-pre.js | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 834c99e338799..48ab5a1f5e38f 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -540,12 +540,20 @@ function simplifyExpressionsPre(ast) { }); } - function addFinalReturns(ast) { + function asmOpts(ast) { + // 1. Add final returns when necessary + // 2. Remove unneeded coercions on function calls that have no targets (eliminator removed it) traverseGeneratedFunctions(ast, function(fun) { var returnType = null; traverse(fun, function(node, type) { if (type == 'return' && node[1]) { returnType = detectAsmCoercion(node[1]); + } else if (type == 'stat') { + var inner = node[1]; + if ((inner[0] == 'binary' && inner[1] in ASSOCIATIVE_BINARIES && inner[2][0] == 'call' && inner[3][0] == 'num') || + (inner[0] == 'unary-prefix' && inner[1] == '+' && inner[2][0] == 'call')) { + node[1] = inner[2]; + } } }); // Add a final return if one is missing. @@ -564,7 +572,7 @@ function simplifyExpressionsPre(ast) { simplifyBitops(ast); joinAdditions(ast); // simplifyZeroComp(ast); TODO: investigate performance - if (asm) addFinalReturns(ast); + if (asm) asmOpts(ast); } // In typed arrays mode 2, we can have diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 3437163e7f7e3..745873f885236 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -6,6 +6,8 @@ function a() { f(8); HEAP[1024] = 5; HEAP[1024] = 5; + whee(12, 13); + whee(12, 13); } function b($this, $__n) { $this = $this | 0; diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index 42eb435ae2682..36fe245ae790d 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -6,6 +6,8 @@ function a() { f(347 & 12); HEAP[4096 >> 2] = 5; HEAP[(4096 & 8191) >> 2] = 5; + whee(12, 13) | 0; + +whee(12, 13); } function b($this, $__n) { $this = $this | 0; From 683c5b45085fd947d66e7ade49e1bc1df000c06a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 20:45:59 -0800 Subject: [PATCH 66/81] move asm return adding test to right place --- tools/test-js-optimizer-asm-pre-output.js | 20 +++++++++++++++++++ tools/test-js-optimizer-asm-pre.js | 23 +++++++++++++++++++++- tools/test-js-optimizer-asm-regs-output.js | 20 ------------------- tools/test-js-optimizer-asm-regs.js | 23 +--------------------- 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 745873f885236..53619c84ba6e4 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -53,4 +53,24 @@ function b($this, $__n) { HEAP8[$38 + $40 & 16777215] = 0; return; } +function rett() { + if (f()) { + g(); + return 5; + } + return 0; +} +function ret2t() { + if (f()) { + g(); + return; + } +} +function retf() { + if (f()) { + g(); + return +h(); + } + return +0; +} diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index 36fe245ae790d..0fb7050f96589 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -53,4 +53,25 @@ function b($this, $__n) { HEAP8[($38 + $40 | 0) & 16777215] = 0; return; } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b"] +function rett() { + if (f()) { + g(); + return 5; + } + // missing final return, need to add it +} +function ret2t() { + if (f()) { + g(); + return; + } + // missing final return, but no need +} +function retf() { + if (f()) { + g(); + return +h(); + } + // missing final return, need it as a float +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "rett", "ret2t", "retf"] diff --git a/tools/test-js-optimizer-asm-regs-output.js b/tools/test-js-optimizer-asm-regs-output.js index 8c0bd97058309..bb6a502b45538 100644 --- a/tools/test-js-optimizer-asm-regs-output.js +++ b/tools/test-js-optimizer-asm-regs-output.js @@ -18,26 +18,6 @@ function _doit(i1, i2, i3) { STACKTOP = i1; return 0 | 0; } -function rett() { - if (f()) { - g(); - return 5; - } - return 0; -} -function ret2t() { - if (f()) { - g(); - return; - } -} -function retf() { - if (f()) { - g(); - return +h(); - } - return +0; -} function stackRestore(i1) { i1 = i1 | 0; STACKTOP = i1; diff --git a/tools/test-js-optimizer-asm-regs.js b/tools/test-js-optimizer-asm-regs.js index a8b637ced4f06..4f7e04d42fde4 100644 --- a/tools/test-js-optimizer-asm-regs.js +++ b/tools/test-js-optimizer-asm-regs.js @@ -20,30 +20,9 @@ function _doit($x, $y$0, $y$1) { STACKTOP = __stackBase__; return 0 | 0; } -function rett() { - if (f()) { - g(); - return 5; - } - // missing final return, need to add it -} -function ret2t() { - if (f()) { - g(); - return; - } - // missing final return, but no need -} -function retf() { - if (f()) { - g(); - return +h(); - } - // missing final return, need it as a float -} function stackRestore(top) { top = top|0; STACKTOP = top; } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "rett", "ret2t", "retf", "stackRestore"] +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "stackRestore"] From b900ac09a2da00442e70be78136b180e820480bf Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 08:41:12 -0700 Subject: [PATCH 67/81] save asm validation errors and continue, in fuzzer --- tests/fuzz/csmith_driver.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/fuzz/csmith_driver.py b/tests/fuzz/csmith_driver.py index 5bdef0094cf0f..ac033377cb0ca 100755 --- a/tests/fuzz/csmith_driver.py +++ b/tests/fuzz/csmith_driver.py @@ -114,7 +114,13 @@ def try_js(args): break # asm.js testing - assert 'warning: Successfully compiled asm.js code' in js2, 'must validate' + if 'warning: Successfully compiled asm.js code' not in js2: + print "ODIN VALIDATION BUG" + notes['embug'] += 1 + fails += 1 + shutil.copyfile('fuzzcode.c', 'newfail%d.c' % fails) + continue + js2 = js2.replace('\nwarning: Successfully compiled asm.js code\n', '') assert js2 == correct1 or js2 == correct2, ''.join([a.rstrip()+'\n' for a in difflib.unified_diff(correct1.split('\n'), js2.split('\n'), fromfile='expected', tofile='actual')]) + 'ODIN FAIL' From e5afcd2290c4914ec0ba16d8b54168c535773a0c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 10:02:40 -0700 Subject: [PATCH 68/81] disable getopt tests in s_x_x --- tests/runner.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/runner.py b/tests/runner.py index bb787def15dee..cbbbf345c45d6 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -4271,6 +4271,8 @@ def test_memcpy2(self): self.do_run(src, 'ok.'); def test_getopt(self): + if self.emcc_args is None: return self.skip('needs emcc for libc') + src = ''' #pragma clang diagnostic ignored "-Winvalid-pp-token" #include @@ -4319,6 +4321,8 @@ def test_getopt(self): self.do_run(src, 'flags=1; tfnd=1; optind=4\nname argument = foobar', args=['-t', '12', '-n', 'foobar']) def test_getopt_long(self): + if self.emcc_args is None: return self.skip('needs emcc for libc') + src = ''' #pragma clang diagnostic ignored "-Winvalid-pp-token" #pragma clang diagnostic ignored "-Wdeprecated-writable-strings" From 1c25bb627bb43d2595dc59545d65d5a2ec83a9bf Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 10:03:06 -0700 Subject: [PATCH 69/81] use whitelist of lines to forward out of generated functions area --- tools/js_optimizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 60093bca24449..ae7fe817f11ef 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -153,7 +153,7 @@ def run_on_js(filename, passes, js_engine, jcache): class Finals: buf = [] def process(line): - if len(line) > 0 and not line.startswith((' ', 'function', '}')): + if len(line) > 0 and (line.startswith('Module[') or line.endswith('["X"]=1;')): Finals.buf.append(line) return False return True From 97b2c07543c3cac24c2ab21907976342a9ea1abe Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 10:05:21 -0700 Subject: [PATCH 70/81] disable test_sscanf and test_strtod in s_x_x --- tests/runner.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/runner.py b/tests/runner.py index cbbbf345c45d6..ce37778a25b0e 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -5029,6 +5029,8 @@ def test_rand(self): self.do_run(src, re.sub(r'(^|\n)\s+', r'\1', expected)) def test_strtod(self): + if self.emcc_args is None: return self.skip('needs emcc for libc') + src = r''' #include #include @@ -5372,6 +5374,8 @@ def test_strstr(self): ''') def test_sscanf(self): + if self.emcc_args is None: return self.skip('needs emcc for libc') + src = r''' #include #include From a373820140dc019bb01561883380595ae8a1f739 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 10:18:45 -0700 Subject: [PATCH 71/81] add 'progress' updates from multicore operations in emcc --- emscripten.py | 5 +++-- tools/js_optimizer.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/emscripten.py b/emscripten.py index 09a57e37e772e..34a5b20f247f1 100755 --- a/emscripten.py +++ b/emscripten.py @@ -33,7 +33,7 @@ def scan(ll, settings): MIN_CHUNK_SIZE = 1024*1024 MAX_CHUNK_SIZE = float(os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or 'inf') # configuring this is just for debugging purposes -def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files)): +def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files, DEBUG)): ll = ''.join(funcs) + '\n' + meta funcs_file = temp_files.get('.func_%d.ll' % i).name open(funcs_file, 'w').write(ll) @@ -44,6 +44,7 @@ def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libr stdout=subprocess.PIPE, cwd=path_from_root('src')) tempfiles.try_delete(funcs_file) + if DEBUG: print >> sys.stderr, '.' return out def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, @@ -213,7 +214,7 @@ def load_from_cache(chunk): if DEBUG: print >> sys.stderr, ' emscript: phase 2 working on %d chunks %s (intended chunk size: %.2f MB, meta: %.2f MB, forwarded: %.2f MB, total: %.2f MB)' % (len(chunks), ('using %d cores' % cores) if len(chunks) > 1 else '', chunk_size/(1024*1024.), len(meta)/(1024*1024.), len(forwarded_data)/(1024*1024.), total_ll_size/(1024*1024.)) commands = [ - (i, chunk, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files) + (i, chunk, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files, DEBUG) for i, chunk in enumerate(chunks) ] diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index ae7fe817f11ef..053f0dcdba7e3 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -100,6 +100,7 @@ def run_on_chunk(command): f = open(filename, 'w') f.write(output) f.close() + if DEBUG: print >> sys.stderr, '.' return filename def run_on_js(filename, passes, js_engine, jcache): From 14010845731c216f8ce7620ccd83b965702bcdaa Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 10:33:42 -0700 Subject: [PATCH 72/81] disable inlining in sqlite with asm in debug mode --- tests/runner.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/runner.py b/tests/runner.py index ce37778a25b0e..b8855c622e4f3 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7147,6 +7147,9 @@ def test_sqlite(self): Settings.DISABLE_EXCEPTION_CATCHING = 1 Settings.FAST_MEMORY = 4*1024*1024 Settings.EXPORTED_FUNCTIONS += ['_sqlite3_open', '_sqlite3_close', '_sqlite3_exec', '_sqlite3_free', '_callback']; + if Settings.ASM_JS == 1 and '-g' in self.emcc_args: + print "disabling inlining" # without registerize (which -g disables), we generate huge amounts of code + Settings.INLINING_LIMIT = 50 self.do_run(r''' #define SQLITE_DISABLE_LFS From b1240603040c53bbedb3f2ac08063532a96bcd0e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 11:55:06 -0700 Subject: [PATCH 73/81] adjust csmith driver timeout --- tests/fuzz/csmith_driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzz/csmith_driver.py b/tests/fuzz/csmith_driver.py index ac033377cb0ca..b60e67f7c2693 100755 --- a/tests/fuzz/csmith_driver.py +++ b/tests/fuzz/csmith_driver.py @@ -20,7 +20,7 @@ filename = os.path.join(shared.CANONICAL_TEMP_DIR, 'fuzzcode') -shared.DEFAULT_TIMEOUT = 1 +shared.DEFAULT_TIMEOUT = 5 tried = 0 From 8be82c04408cab6519d3ed58305465ae97ca9da3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 13:59:40 -0700 Subject: [PATCH 74/81] pgo for unused function detection --- src/compiler.js | 1 + src/intertyper.js | 23 +++++++++++++---------- src/jsifier.js | 18 ++++++++++++++---- src/preamble.js | 17 +++++++++++++++++ src/settings.js | 8 ++++++++ tests/runner.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 14 deletions(-) diff --git a/src/compiler.js b/src/compiler.js index 3047daf1ae8b9..447d34b7e3e70 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -163,6 +163,7 @@ if (SAFE_HEAP >= 2) { EXPORTED_FUNCTIONS = set(EXPORTED_FUNCTIONS); EXPORTED_GLOBALS = set(EXPORTED_GLOBALS); EXCEPTION_CATCHING_WHITELIST = set(EXCEPTION_CATCHING_WHITELIST); +DEAD_FUNCTIONS = set(DEAD_FUNCTIONS); RUNTIME_DEBUG = LIBRARY_DEBUG || GL_DEBUG; diff --git a/src/intertyper.js b/src/intertyper.js index 2103ecfab35e2..57e3011d04149 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -122,16 +122,19 @@ function intertyper(data, sidePass, baseLineNums) { SKIP_STACK_IN_SMALL = 0; } - unparsedBundles.push({ - intertype: 'unparsedFunction', - // We need this early, to know basic function info - ident, params, varargs - ident: toNiceIdent(func.ident), - params: func.params, - returnType: func.returnType, - hasVarArgs: func.hasVarArgs, - lineNum: currFunctionLineNum, - lines: currFunctionLines - }); + var ident = toNiceIdent(func.ident); + if (!(ident in DEAD_FUNCTIONS)) { + unparsedBundles.push({ + intertype: 'unparsedFunction', + // We need this early, to know basic function info - ident, params, varargs + ident: ident, + params: func.params, + returnType: func.returnType, + hasVarArgs: func.hasVarArgs, + lineNum: currFunctionLineNum, + lines: currFunctionLines + }); + } currFunctionLines = []; } } diff --git a/src/jsifier.js b/src/jsifier.js index ff58ece2e7a04..1662d249a2832 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -600,6 +600,10 @@ function JSify(data, functionsOnly, givenFunctions) { func.JS += 'function ' + func.ident + '(' + paramIdents.join(', ') + ') {\n'; + if (PGO) { + func.JS += ' PGOMonitor.called["' + func.ident + '"] = 1;\n'; + } + if (ASM_JS) { // spell out argument types func.params.forEach(function(param) { @@ -1587,11 +1591,17 @@ function JSify(data, functionsOnly, givenFunctions) { var shellParts = read(shellFile).split('{{BODY}}'); print(shellParts[1]); - // Print out some useful metadata (for additional optimizations later, like the eliminator) - if (EMIT_GENERATED_FUNCTIONS) { - print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + JSON.stringify(keys(Functions.implementedFunctions).filter(function(func) { + // Print out some useful metadata + if (EMIT_GENERATED_FUNCTIONS || PGO) { + var generatedFunctions = JSON.stringify(keys(Functions.implementedFunctions).filter(function(func) { return IGNORED_FUNCTIONS.indexOf(func.ident) < 0; - })) + '\n'); + })); + if (PGO) { + print('PGOMonitor.allGenerated = ' + generatedFunctions + ';\nremoveRunDependency("pgo");\n'); + } + if (EMIT_GENERATED_FUNCTIONS) { + print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + generatedFunctions + '\n'); + } } PassManager.serialize(); diff --git a/src/preamble.js b/src/preamble.js index 9bc68d8fe5185..7538b19c35a0a 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -848,5 +848,22 @@ Module['removeRunDependency'] = removeRunDependency; Module["preloadedImages"] = {}; // maps url to image data Module["preloadedAudios"] = {}; // maps url to audio data +#if PGO +var PGOMonitor = { + called: {}, + dump: function() { + var dead = []; + for (var i = 0; i < this.allGenerated.length; i++) { + var func = this.allGenerated[i]; + if (!this.called[func]) dead.push(func); + } + Module.print('-s DEAD_FUNCTIONS=\'' + JSON.stringify(dead) + '\'\n'); + } +}; +__ATEXIT__.push({ func: function() { PGOMonitor.dump() } }); +if (!Module.preRun) Module.preRun = []; +Module.preRun.push(function() { addRunDependency('pgo') }); +#endif + // === Body === diff --git a/src/settings.js b/src/settings.js index 440d5094d05e0..101c403c9e05c 100644 --- a/src/settings.js +++ b/src/settings.js @@ -332,6 +332,14 @@ var ASM_JS = 0; // If 1, generate code in asm.js format. XXX This is highly expe // and will not work on most codebases yet. It is NOT recommended that you // try this yet. +var PGO = 0; // Enables profile-guided optimization in the form of runtime checks for + // which functions are actually called. Emits a list during shutdown that you + // can pass to DEAD_FUNCTIONS (you can also emit the list manually by + // calling PGOMonitor.dump()); +var DEAD_FUNCTIONS = []; // A list of functions that no code will be emitted for, and + // a runtime abort will happen if they are called + // TODO: options to lazily load such functions + var EXPLICIT_ZEXT = 0; // If 1, generate an explicit conversion of zext i1 to i32, using ?: var NECESSARY_BLOCKADDRS = []; // List of (function, block) for all block addresses that are taken. diff --git a/tests/runner.py b/tests/runner.py index b8855c622e4f3..61fb582a3636b 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7672,6 +7672,50 @@ def process(filename): self.do_run(src, '*\nnumber,5\nnumber,3.14\nstring,hello world\n12\nundefined\n14.56\nundefined\ncheez\nundefined\narr-ay\nundefined\nmore\nnumber,10\n650\nnumber,21\n*\natr\n10\nbret\n53\n*\nstack is ok.\n', post_build=post) + def test_pgo(self): + if Settings.ASM_JS: return self.skip('PGO does not work in asm mode') + + src = r''' + #include + extern "C" { + int used(int x) { + if (x == 0) return -1; + return used(x/3) + used(x/17) + x%5; + } + int unused(int x) { + if (x == 0) return -1; + return unused(x/4) + unused(x/23) + x%7; + } + } + int main(int argc, char **argv) { + printf("*%d*\n", argc == 3 ? unused(argv[0][0] + 1024) : used(argc + 1555)); + return 0; + } + ''' + + def test(expected, args=[], no_build=False): + self.do_run(src, expected, args=args, no_build=no_build) + return open(self.in_dir('src.cpp.o.js')).read() + + # Sanity check that it works and the dead function is emitted + js = test('*9*') + assert 'function _unused(' in js + + # Run with PGO, see that unused is true to its name + Settings.PGO = 1 + test("*9*\n-s DEAD_FUNCTIONS='[\"_unused\"]'") + Settings.PGO = 0 + + # Kill off the dead function, still works and it is not emitted + Settings.DEAD_FUNCTIONS = ['_unused'] + js = test('*9*') + assert 'function _unused(' not in js + + # Run the same code with argc that uses the dead function, see abort + test('ReferenceError: _unused is not defined', args=['a', 'b'], no_build=True) + + # TODO: function pointers + def test_scriptaclass(self): if self.emcc_args is None: return self.skip('requires emcc') if Settings.ASM_JS: return self.skip('asm does not bindings generator yet') From f8066edde43495c5ca6b869ff37f99a8290f30b5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 14:21:42 -0700 Subject: [PATCH 75/81] function pointer support in PGO --- src/modules.js | 2 +- tests/runner.py | 74 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/modules.js b/src/modules.js index 797d4d83e0404..e78b294fd5bfa 100644 --- a/src/modules.js +++ b/src/modules.js @@ -291,7 +291,7 @@ var Functions = { var sig = ASM_JS ? Functions.implementedFunctions[ident] || Functions.unimplementedFunctions[ident] || LibraryManager.library[ident.substr(1) + '__sig'] : 'x'; assert(sig, ident); if (!tables[sig]) tables[sig] = emptyTable(sig); // TODO: make them compact - tables[sig][this.indexedFunctions[ident]] = ident; + tables[sig][this.indexedFunctions[ident]] = ident in DEAD_FUNCTIONS ? '0' : ident; } var generated = false; var wrapped = {}; diff --git a/tests/runner.py b/tests/runner.py index 61fb582a3636b..b2bacb1b28f85 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7675,7 +7675,32 @@ def process(filename): def test_pgo(self): if Settings.ASM_JS: return self.skip('PGO does not work in asm mode') - src = r''' + def run_all(name, src): + print name + def test(expected, args=[], no_build=False): + self.do_run(src, expected, args=args, no_build=no_build) + return open(self.in_dir('src.cpp.o.js')).read() + + # Sanity check that it works and the dead function is emitted + js = test('*9*') + assert 'function _unused(' in js + + # Run with PGO, see that unused is true to its name + Settings.PGO = 1 + test("*9*\n-s DEAD_FUNCTIONS='[\"_unused\"]'") + Settings.PGO = 0 + + # Kill off the dead function, still works and it is not emitted + Settings.DEAD_FUNCTIONS = ['_unused'] + js = test('*9*') + assert 'function _unused(' not in js + Settings.DEAD_FUNCTIONS = [] + + # Run the same code with argc that uses the dead function, see abort + test(('ReferenceError: _unused is not defined', 'is not a function'), args=['a', 'b'], no_build=True) + + # Normal stuff + run_all('normal', r''' #include extern "C" { int used(int x) { @@ -7691,30 +7716,31 @@ def test_pgo(self): printf("*%d*\n", argc == 3 ? unused(argv[0][0] + 1024) : used(argc + 1555)); return 0; } - ''' - - def test(expected, args=[], no_build=False): - self.do_run(src, expected, args=args, no_build=no_build) - return open(self.in_dir('src.cpp.o.js')).read() - - # Sanity check that it works and the dead function is emitted - js = test('*9*') - assert 'function _unused(' in js - - # Run with PGO, see that unused is true to its name - Settings.PGO = 1 - test("*9*\n-s DEAD_FUNCTIONS='[\"_unused\"]'") - Settings.PGO = 0 - - # Kill off the dead function, still works and it is not emitted - Settings.DEAD_FUNCTIONS = ['_unused'] - js = test('*9*') - assert 'function _unused(' not in js - - # Run the same code with argc that uses the dead function, see abort - test('ReferenceError: _unused is not defined', args=['a', 'b'], no_build=True) + ''') - # TODO: function pointers + # Call by function pointer + run_all('function pointers', r''' + #include + extern "C" { + int used(int x) { + if (x == 0) return -1; + return used(x/3) + used(x/17) + x%5; + } + int unused(int x) { + if (x == 0) return -1; + return unused(x/4) + unused(x/23) + x%7; + } + } + typedef int (*ii)(int); + int main(int argc, char **argv) { + ii pointers[256]; + for (int i = 0; i < 256; i++) { + pointers[i] = (i == 3) ? unused : used; + } + printf("*%d*\n", pointers[argc](argc + 1555)); + return 0; + } + ''') def test_scriptaclass(self): if self.emcc_args is None: return self.skip('requires emcc') From 7c39b40357a764fcf0a52d0c647d28c10af4d59f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 15:02:11 -0700 Subject: [PATCH 76/81] larger pgo test, with asm measurements --- emcc | 2 +- src/modules.js | 2 +- tests/runner.py | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/emcc b/emcc index 1acd3aff4d114..4ae69673c43d4 100755 --- a/emcc +++ b/emcc @@ -129,8 +129,8 @@ while response_file: for index in range(1, len(sys.argv)): if sys.argv[index][0] == '@': # found one, loop again next time - print >>sys.stderr, 'emcc: using response file: %s' % response_file response_file = sys.argv[index][1:] + print >>sys.stderr, 'emcc: using response file: %s' % response_file if not os.path.exists(response_file): print >>sys.stderr, 'emcc: error: Response file not found: %s' % response_file exit(1) diff --git a/src/modules.js b/src/modules.js index e78b294fd5bfa..65b8d43786d53 100644 --- a/src/modules.js +++ b/src/modules.js @@ -315,7 +315,7 @@ var Functions = { } if (ASM_JS) { var curr = table[i]; - if (curr && !Functions.implementedFunctions[curr]) { + if (curr && curr != '0' && !Functions.implementedFunctions[curr]) { // This is a library function, we can't just put it in the function table, need a wrapper if (!wrapped[curr]) { var args = '', arg_coercions = '', call = curr + '(', retPre = '', retPost = ''; diff --git a/tests/runner.py b/tests/runner.py index b2bacb1b28f85..33e6095aa1416 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -9039,6 +9039,22 @@ def test(args): assert debug_size > unminified_size assert 'function _malloc' in src + def test_asm_pgo(self): + Popen([PYTHON, EMXX, '-O2', '-s', 'ASM_JS=1', path_from_root('tests', 'hello_libcxx.cpp'), '-o', 'normal.js']).communicate() + self.assertContained('hello, world!', run_js(self.in_dir('normal.js'))) + + Popen([PYTHON, EMXX, '-O2', '-s', 'PGO=1', path_from_root('tests', 'hello_libcxx.cpp'), '-o', 'pgo.js']).communicate() + pgo_output = run_js(self.in_dir('pgo.js')) + self.assertContained('hello, world!', pgo_output) + + open('pgo_data', 'w').write(pgo_output.split('\n')[1]) + Popen([PYTHON, EMXX, '-O2', '-s', 'ASM_JS=1', path_from_root('tests', 'hello_libcxx.cpp'), '-o', 'pgoed.js', '@pgo_data']).communicate() + self.assertContained('hello, world!', run_js(self.in_dir('pgoed.js'))) + + before = len(open('normal.js').read()) + after = len(open('pgoed.js').read()) + assert after < 0.66 * before, [before, after] # expect a big size reduction + def test_l_link(self): # Linking with -lLIBNAME and -L/DIRNAME should work From b028fb574e06232d3df6e6a25c38af427006666a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 16:22:29 -0700 Subject: [PATCH 77/81] error on pgo with asm --- emcc | 1 + 1 file changed, 1 insertion(+) diff --git a/emcc b/emcc index 4ae69673c43d4..057e17ec9d38e 100755 --- a/emcc +++ b/emcc @@ -972,6 +972,7 @@ try: if shared.Settings.CORRECT_OVERFLOWS != 1: print >> sys.stderr, 'emcc: warning: setting CORRECT_OVERFLOWS to 1 for asm.js code generation' shared.Settings.CORRECT_OVERFLOWS = 1 + assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode' if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2: keep_llvm_debug = True # must keep debug info to do line-by-line operations From 6a91523540888fe343495090f9ee1acb659905f1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 18:47:38 -0700 Subject: [PATCH 78/81] --save-bc option --- emcc | 17 +++++++++++++++++ tests/runner.py | 16 ++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/emcc b/emcc index 057e17ec9d38e..d06bb21cc7296 100755 --- a/emcc +++ b/emcc @@ -449,6 +449,13 @@ Options that are modified or new in %s include: the bootstrapped relooper. After the cache is cleared, this process will exit. + --save-bc PATH When compiling to JavaScript or HTML, this + option will save a copy of the bitcode to + the specified path. The bitcode will include + all files being linked, including standard + libraries, and after any link-time optimizations + (if any). + The target file, if specified (-o ), defines what will be generated: @@ -694,6 +701,8 @@ try: keep_js_debug = False bind = False jcache = False + save_bc = False + if use_cxx: default_cxx_std = '-std=c++03' # Enforce a consistent C++ standard when compiling .cpp files, if user does not specify one on the cmdline. else: @@ -821,6 +830,11 @@ try: print >> sys.stderr, 'emcc: clearing cache' shared.Cache.erase() sys.exit(0) + elif newargs[i] == '--save-bc': + check_bad_eq(newargs[i]) + save_bc = newargs[i+1] + newargs[i] = '' + newargs[i+1] = '' elif newargs[i].startswith(('-I/', '-L/')): if not absolute_warning_shown: print >> sys.stderr, 'emcc: warning: -I or -L of an absolute path encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript)' # Of course an absolute path to a non-system-specific library or header is fine, and you can ignore this warning. The danger are system headers that are e.g. x86 specific and nonportable. The emscripten bundled headers are modified to be portable, local system ones are generally not @@ -1238,6 +1252,9 @@ try: shared.Building.llvm_opt(in_temp(target_basename + '.bc'), link_opts) if DEBUG: save_intermediate('linktime', 'bc') + if save_bc: + shutil.copyfile(final, save_bc) + # Prepare .ll for Emscripten if not LEAVE_INPUTS_RAW: final = shared.Building.llvm_dis(final, final + '.ll') diff --git a/tests/runner.py b/tests/runner.py index 33e6095aa1416..eb0f8e7b88f45 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -9737,6 +9737,22 @@ def test_prepre(self): Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'pre.js', '--pre-js', 'pre2.js']).communicate() self.assertContained('prepre\npre-run\nhello from main\n', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + def test_save_bc(self): + for save in [0, 1]: + self.clear() + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop_malloc.cpp')] + ([] if not save else ['--save-bc', self.in_dir('my_bitcode.bc')])).communicate() + assert 'hello, world!' in run_js(self.in_dir('a.out.js')) + assert os.path.exists(self.in_dir('my_bitcode.bc')) == save + if save: + try_delete('a.out.js') + Building.llvm_dis(self.in_dir('my_bitcode.bc'), self.in_dir('my_ll.ll')) + try: + os.environ['EMCC_LEAVE_INPUTS_RAW'] = '1' + Popen([PYTHON, EMCC, 'my_ll.ll', '-o', 'two.js']).communicate() + assert 'hello, world!' in run_js(self.in_dir('two.js')) + finally: + del os.environ['EMCC_LEAVE_INPUTS_RAW'] + def test_fix_closure(self): input = path_from_root('tests', 'test-fix-closure.js') expected = path_from_root('tests', 'test-fix-closure.out.js') From 4c774c6d058e0648501c5a9f61ed7a254d9a2acf Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 21:27:25 -0700 Subject: [PATCH 79/81] legalize truncs from legal values into illegal values --- src/analyzer.js | 5 +- tests/cases/phi24_ta2.ll | 1876 +++++++++++++++++++++++++++++++++++++ tests/cases/phi24_ta2.txt | 1 + 3 files changed, 1880 insertions(+), 2 deletions(-) create mode 100644 tests/cases/phi24_ta2.ll create mode 100644 tests/cases/phi24_ta2.txt diff --git a/src/analyzer.js b/src/analyzer.js index 209e31404e5d5..926ac9d38b291 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -231,9 +231,10 @@ function analyzer(data, sidePass) { } if (isIllegalType(item.valueType) || isIllegalType(item.type)) { isIllegal = true; - } - if ((item.intertype == 'load' || item.intertype == 'store') && isStructType(item.valueType)) { + } else if ((item.intertype == 'load' || item.intertype == 'store') && isStructType(item.valueType)) { isIllegal = true; // storing an entire structure is illegal + } else if (item.intertype == 'mathop' && item.op == 'trunc' && isIllegalType(item.params[1].ident)) { // trunc stores target value in second ident + isIllegal = true; } }); if (!isIllegal) { diff --git a/tests/cases/phi24_ta2.ll b/tests/cases/phi24_ta2.ll new file mode 100644 index 0000000000000..b5b0664bb5e2f --- /dev/null +++ b/tests/cases/phi24_ta2.ll @@ -0,0 +1,1876 @@ + +;;; trunc i32 into i24, needs $0 on target variable name + +; ModuleID = '/tmp/tmpvqlBv2/a.out.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-pc-linux-gnu" + +%union.U4 = type { i32 } +%union.U3 = type { i8* } +%struct.S1 = type { i8, i32, [4 x i8], %struct.S0, %struct.S0, i8 } +%struct.S0 = type { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], [4 x i8], i16 } + +@.str = private unnamed_addr constant [2 x i8] c"1\00", align 1 +@.str1 = private unnamed_addr constant [4 x i8] c"g_8\00", align 1 +@g_10 = internal global i8 5, align 1 +@.str2 = private unnamed_addr constant [5 x i8] c"g_10\00", align 1 +@.str3 = private unnamed_addr constant [8 x i8] c"g_17.f0\00", align 1 +@.str4 = private unnamed_addr constant [8 x i8] c"g_17.f1\00", align 1 +@.str5 = private unnamed_addr constant [8 x i8] c"g_17.f2\00", align 1 +@.str6 = private unnamed_addr constant [8 x i8] c"g_17.f3\00", align 1 +@.str7 = private unnamed_addr constant [8 x i8] c"g_38.f0\00", align 1 +@.str8 = private unnamed_addr constant [8 x i8] c"g_38.f1\00", align 1 +@.str9 = private unnamed_addr constant [8 x i8] c"g_38.f2\00", align 1 +@.str10 = private unnamed_addr constant [11 x i8] c"g_38.f3.f0\00", align 1 +@.str11 = private unnamed_addr constant [11 x i8] c"g_38.f3.f1\00", align 1 +@.str12 = private unnamed_addr constant [11 x i8] c"g_38.f3.f2\00", align 1 +@.str13 = private unnamed_addr constant [11 x i8] c"g_38.f3.f3\00", align 1 +@.str14 = private unnamed_addr constant [11 x i8] c"g_38.f3.f4\00", align 1 +@.str15 = private unnamed_addr constant [11 x i8] c"g_38.f3.f5\00", align 1 +@.str16 = private unnamed_addr constant [11 x i8] c"g_38.f3.f6\00", align 1 +@.str17 = private unnamed_addr constant [11 x i8] c"g_38.f3.f7\00", align 1 +@.str18 = private unnamed_addr constant [11 x i8] c"g_38.f3.f8\00", align 1 +@.str19 = private unnamed_addr constant [11 x i8] c"g_38.f3.f9\00", align 1 +@.str20 = private unnamed_addr constant [11 x i8] c"g_38.f4.f0\00", align 1 +@.str21 = private unnamed_addr constant [11 x i8] c"g_38.f4.f1\00", align 1 +@.str22 = private unnamed_addr constant [11 x i8] c"g_38.f4.f2\00", align 1 +@.str23 = private unnamed_addr constant [11 x i8] c"g_38.f4.f3\00", align 1 +@.str24 = private unnamed_addr constant [11 x i8] c"g_38.f4.f4\00", align 1 +@.str25 = private unnamed_addr constant [11 x i8] c"g_38.f4.f5\00", align 1 +@.str26 = private unnamed_addr constant [11 x i8] c"g_38.f4.f6\00", align 1 +@.str27 = private unnamed_addr constant [11 x i8] c"g_38.f4.f7\00", align 1 +@.str28 = private unnamed_addr constant [11 x i8] c"g_38.f4.f8\00", align 1 +@.str29 = private unnamed_addr constant [11 x i8] c"g_38.f4.f9\00", align 1 +@.str30 = private unnamed_addr constant [8 x i8] c"g_38.f5\00", align 1 +@g_53 = internal global %union.U4 { i32 5 }, align 4 +@.str31 = private unnamed_addr constant [8 x i8] c"g_53.f0\00", align 1 +@.str32 = private unnamed_addr constant [8 x i8] c"g_53.f1\00", align 1 +@.str33 = private unnamed_addr constant [8 x i8] c"g_53.f2\00", align 1 +@.str34 = private unnamed_addr constant [8 x i8] c"g_53.f3\00", align 1 +@g_58 = internal unnamed_addr global [5 x [10 x i32]] [[10 x i32] [i32 -1394082054, i32 331836000, i32 -1394082054, i32 -3, i32 -1394082054, i32 -992756762, i32 1, i32 331836000, i32 331836000, i32 -2072662602], [10 x i32] [i32 -809167067, i32 -3, i32 -2072662602, i32 -2072662602, i32 -479446353, i32 0, i32 -479446353, i32 -2072662602, i32 -479446353, i32 -3], [10 x i32] [i32 1, i32 -809167067, i32 -992756762, i32 -992756762, i32 -2072662602, i32 0, i32 1, i32 1, i32 -3, i32 -809167067], [10 x i32] [i32 -992756762, i32 -1394082054, i32 -1394082054, i32 0, i32 -2072662602, i32 0, i32 -1394082054, i32 0, i32 -809167067, i32 -3], [10 x i32] [i32 -3, i32 1, i32 1, i32 0, i32 -479446353, i32 -809167067, i32 -809167067, i32 331836000, i32 -3, i32 331836000]], align 4 +@.str35 = private unnamed_addr constant [11 x i8] c"g_58[i][j]\00", align 1 +@.str36 = private unnamed_addr constant [18 x i8] c"index = [%d][%d]\0A\00", align 1 +@g_60 = internal global i32 -3, align 4 +@.str37 = private unnamed_addr constant [5 x i8] c"g_60\00", align 1 +@g_76 = internal global i32 -1, align 4 +@.str38 = private unnamed_addr constant [5 x i8] c"g_76\00", align 1 +@g_84 = internal unnamed_addr global i16 32296, align 2 +@.str39 = private unnamed_addr constant [5 x i8] c"g_84\00", align 1 +@g_116 = internal global i8 -44, align 1 +@.str40 = private unnamed_addr constant [6 x i8] c"g_116\00", align 1 +@g_117 = internal global i32 -6, align 4 +@.str41 = private unnamed_addr constant [6 x i8] c"g_117\00", align 1 +@g_123 = internal global %union.U4 { i32 -1 }, align 4 +@.str42 = private unnamed_addr constant [9 x i8] c"g_123.f0\00", align 1 +@.str43 = private unnamed_addr constant [9 x i8] c"g_123.f1\00", align 1 +@.str44 = private unnamed_addr constant [9 x i8] c"g_123.f2\00", align 1 +@.str45 = private unnamed_addr constant [9 x i8] c"g_123.f3\00", align 1 +@g_145 = internal unnamed_addr global i16 8, align 2 +@.str46 = private unnamed_addr constant [6 x i8] c"g_145\00", align 1 +@g_153 = internal global i8 23, align 1 +@.str47 = private unnamed_addr constant [6 x i8] c"g_153\00", align 1 +@g_161 = internal global i8 8, align 1 +@.str48 = private unnamed_addr constant [6 x i8] c"g_161\00", align 1 +@g_162 = internal unnamed_addr global i32 388565681, align 4 +@.str49 = private unnamed_addr constant [6 x i8] c"g_162\00", align 1 +@.str50 = private unnamed_addr constant [6 x i8] c"g_187\00", align 1 +@g_192 = internal unnamed_addr global [3 x i16] [i16 -3243, i16 -3243, i16 -3243], align 2 +@.str51 = private unnamed_addr constant [9 x i8] c"g_192[i]\00", align 1 +@.str52 = private unnamed_addr constant [14 x i8] c"index = [%d]\0A\00", align 1 +@.str53 = private unnamed_addr constant [9 x i8] c"g_261.f0\00", align 1 +@.str54 = private unnamed_addr constant [9 x i8] c"g_261.f1\00", align 1 +@.str55 = private unnamed_addr constant [9 x i8] c"g_261.f2\00", align 1 +@.str56 = private unnamed_addr constant [9 x i8] c"g_261.f3\00", align 1 +@.str57 = private unnamed_addr constant [9 x i8] c"g_261.f4\00", align 1 +@.str58 = private unnamed_addr constant [9 x i8] c"g_261.f5\00", align 1 +@.str59 = private unnamed_addr constant [9 x i8] c"g_261.f6\00", align 1 +@.str60 = private unnamed_addr constant [9 x i8] c"g_261.f7\00", align 1 +@.str61 = private unnamed_addr constant [9 x i8] c"g_261.f8\00", align 1 +@.str62 = private unnamed_addr constant [9 x i8] c"g_261.f9\00", align 1 +@.str63 = private unnamed_addr constant [6 x i8] c"g_287\00", align 1 +@g_325 = internal unnamed_addr global i32 1, align 4 +@.str64 = private unnamed_addr constant [6 x i8] c"g_325\00", align 1 +@g_331 = internal global i8 0, align 1 +@.str65 = private unnamed_addr constant [6 x i8] c"g_331\00", align 1 +@g_333 = internal unnamed_addr global i32 3, align 4 +@.str66 = private unnamed_addr constant [6 x i8] c"g_333\00", align 1 +@g_337 = internal global i32 1408789087, align 4 +@.str67 = private unnamed_addr constant [6 x i8] c"g_337\00", align 1 +@g_349 = internal global i32 49917741, align 4 +@.str68 = private unnamed_addr constant [6 x i8] c"g_349\00", align 1 +@g_382 = internal global i8 -1, align 1 +@.str69 = private unnamed_addr constant [6 x i8] c"g_382\00", align 1 +@.str70 = private unnamed_addr constant [12 x i8] c"g_409[i][j]\00", align 1 +@.str71 = private unnamed_addr constant [6 x i8] c"g_410\00", align 1 +@g_445 = internal unnamed_addr global [3 x [2 x [4 x i32]]] [[2 x [4 x i32]] [[4 x i32] [i32 -1169816097, i32 -1718720460, i32 -1718720460, i32 -9], [4 x i32] [i32 -1, i32 7, i32 -9, i32 -1718720460]], [2 x [4 x i32]] [[4 x i32] [i32 0, i32 -9, i32 -9, i32 -1], [4 x i32] [i32 -1, i32 7, i32 -1169816097, i32 7]], [2 x [4 x i32]] [[4 x i32] [i32 -9, i32 -487065431, i32 7, i32 7], [4 x i32] [i32 7, i32 7, i32 -1169816097, i32 0]]], align 4 +@.str72 = private unnamed_addr constant [15 x i8] c"g_445[i][j][k]\00", align 1 +@.str73 = private unnamed_addr constant [22 x i8] c"index = [%d][%d][%d]\0A\00", align 1 +@g_455 = internal unnamed_addr global i16 -24588, align 2 +@.str74 = private unnamed_addr constant [6 x i8] c"g_455\00", align 1 +@g_483 = internal unnamed_addr global [4 x [3 x i8]] [[3 x i8] c"\00uu", [3 x i8] c"W\FF\FF", [3 x i8] c"\FBu\00", [3 x i8] c"W\FFW"], align 1 +@.str75 = private unnamed_addr constant [12 x i8] c"g_483[i][j]\00", align 1 +@.str76 = private unnamed_addr constant [9 x i8] c"g_533.f0\00", align 1 +@.str77 = private unnamed_addr constant [9 x i8] c"g_533.f1\00", align 1 +@.str78 = private unnamed_addr constant [9 x i8] c"g_533.f2\00", align 1 +@.str79 = private unnamed_addr constant [12 x i8] c"g_533.f3.f0\00", align 1 +@.str80 = private unnamed_addr constant [12 x i8] c"g_533.f3.f1\00", align 1 +@.str81 = private unnamed_addr constant [12 x i8] c"g_533.f3.f2\00", align 1 +@.str82 = private unnamed_addr constant [12 x i8] c"g_533.f3.f3\00", align 1 +@.str83 = private unnamed_addr constant [12 x i8] c"g_533.f3.f4\00", align 1 +@.str84 = private unnamed_addr constant [12 x i8] c"g_533.f3.f5\00", align 1 +@.str85 = private unnamed_addr constant [12 x i8] c"g_533.f3.f6\00", align 1 +@.str86 = private unnamed_addr constant [12 x i8] c"g_533.f3.f7\00", align 1 +@.str87 = private unnamed_addr constant [12 x i8] c"g_533.f3.f8\00", align 1 +@.str88 = private unnamed_addr constant [12 x i8] c"g_533.f3.f9\00", align 1 +@.str89 = private unnamed_addr constant [12 x i8] c"g_533.f4.f0\00", align 1 +@.str90 = private unnamed_addr constant [12 x i8] c"g_533.f4.f1\00", align 1 +@.str91 = private unnamed_addr constant [12 x i8] c"g_533.f4.f2\00", align 1 +@.str92 = private unnamed_addr constant [12 x i8] c"g_533.f4.f3\00", align 1 +@.str93 = private unnamed_addr constant [12 x i8] c"g_533.f4.f4\00", align 1 +@.str94 = private unnamed_addr constant [12 x i8] c"g_533.f4.f5\00", align 1 +@.str95 = private unnamed_addr constant [12 x i8] c"g_533.f4.f6\00", align 1 +@.str96 = private unnamed_addr constant [12 x i8] c"g_533.f4.f7\00", align 1 +@.str97 = private unnamed_addr constant [12 x i8] c"g_533.f4.f8\00", align 1 +@.str98 = private unnamed_addr constant [12 x i8] c"g_533.f4.f9\00", align 1 +@.str99 = private unnamed_addr constant [9 x i8] c"g_533.f5\00", align 1 +@g_542 = internal global i32 -1851924269, align 4 +@.str100 = private unnamed_addr constant [6 x i8] c"g_542\00", align 1 +@g_543 = internal global i8 0, align 1 +@.str101 = private unnamed_addr constant [6 x i8] c"g_543\00", align 1 +@.str102 = private unnamed_addr constant [15 x i8] c"g_647[i][j].f0\00", align 1 +@.str103 = private unnamed_addr constant [15 x i8] c"g_647[i][j].f1\00", align 1 +@.str104 = private unnamed_addr constant [15 x i8] c"g_647[i][j].f2\00", align 1 +@.str105 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f0\00", align 1 +@.str106 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f1\00", align 1 +@.str107 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f2\00", align 1 +@.str108 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f3\00", align 1 +@.str109 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f4\00", align 1 +@.str110 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f5\00", align 1 +@.str111 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f6\00", align 1 +@.str112 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f7\00", align 1 +@.str113 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f8\00", align 1 +@.str114 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f3.f9\00", align 1 +@.str115 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f0\00", align 1 +@.str116 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f1\00", align 1 +@.str117 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f2\00", align 1 +@.str118 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f3\00", align 1 +@.str119 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f4\00", align 1 +@.str120 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f5\00", align 1 +@.str121 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f6\00", align 1 +@.str122 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f7\00", align 1 +@.str123 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f8\00", align 1 +@.str124 = private unnamed_addr constant [18 x i8] c"g_647[i][j].f4.f9\00", align 1 +@.str125 = private unnamed_addr constant [15 x i8] c"g_647[i][j].f5\00", align 1 +@.str126 = private unnamed_addr constant [9 x i8] c"g_649.f0\00", align 1 +@.str127 = private unnamed_addr constant [9 x i8] c"g_649.f1\00", align 1 +@.str128 = private unnamed_addr constant [9 x i8] c"g_649.f2\00", align 1 +@.str129 = private unnamed_addr constant [12 x i8] c"g_649.f3.f0\00", align 1 +@.str130 = private unnamed_addr constant [12 x i8] c"g_649.f3.f1\00", align 1 +@.str131 = private unnamed_addr constant [12 x i8] c"g_649.f3.f2\00", align 1 +@.str132 = private unnamed_addr constant [12 x i8] c"g_649.f3.f3\00", align 1 +@.str133 = private unnamed_addr constant [12 x i8] c"g_649.f3.f4\00", align 1 +@.str134 = private unnamed_addr constant [12 x i8] c"g_649.f3.f5\00", align 1 +@.str135 = private unnamed_addr constant [12 x i8] c"g_649.f3.f6\00", align 1 +@.str136 = private unnamed_addr constant [12 x i8] c"g_649.f3.f7\00", align 1 +@.str137 = private unnamed_addr constant [12 x i8] c"g_649.f3.f8\00", align 1 +@.str138 = private unnamed_addr constant [12 x i8] c"g_649.f3.f9\00", align 1 +@.str139 = private unnamed_addr constant [12 x i8] c"g_649.f4.f0\00", align 1 +@.str140 = private unnamed_addr constant [12 x i8] c"g_649.f4.f1\00", align 1 +@.str141 = private unnamed_addr constant [12 x i8] c"g_649.f4.f2\00", align 1 +@.str142 = private unnamed_addr constant [12 x i8] c"g_649.f4.f3\00", align 1 +@.str143 = private unnamed_addr constant [12 x i8] c"g_649.f4.f4\00", align 1 +@.str144 = private unnamed_addr constant [12 x i8] c"g_649.f4.f5\00", align 1 +@.str145 = private unnamed_addr constant [12 x i8] c"g_649.f4.f6\00", align 1 +@.str146 = private unnamed_addr constant [12 x i8] c"g_649.f4.f7\00", align 1 +@.str147 = private unnamed_addr constant [12 x i8] c"g_649.f4.f8\00", align 1 +@.str148 = private unnamed_addr constant [12 x i8] c"g_649.f4.f9\00", align 1 +@.str149 = private unnamed_addr constant [9 x i8] c"g_649.f5\00", align 1 +@g_839 = internal global [1 x [3 x [6 x i8]]] [[3 x [6 x i8]] [[6 x i8] c"FFFFFF", [6 x i8] c"FFFFFF", [6 x i8] c"FFFFFF"]], align 1 +@.str150 = private unnamed_addr constant [15 x i8] c"g_839[i][j][k]\00", align 1 +@.str151 = private unnamed_addr constant [6 x i8] c"g_902\00", align 1 +@.str152 = private unnamed_addr constant [9 x i8] c"g_916[i]\00", align 1 +@.str153 = private unnamed_addr constant [9 x i8] c"g_955.f0\00", align 1 +@.str154 = private unnamed_addr constant [9 x i8] c"g_955.f1\00", align 1 +@.str155 = private unnamed_addr constant [9 x i8] c"g_955.f2\00", align 1 +@.str156 = private unnamed_addr constant [9 x i8] c"g_955.f3\00", align 1 +@g_1003 = internal unnamed_addr global i16 14774, align 2 +@.str157 = private unnamed_addr constant [7 x i8] c"g_1003\00", align 1 +@.str158 = private unnamed_addr constant [7 x i8] c"g_1004\00", align 1 +@g_1048 = internal unnamed_addr global i16 11482, align 2 +@.str159 = private unnamed_addr constant [7 x i8] c"g_1048\00", align 1 +@.str160 = private unnamed_addr constant [10 x i8] c"g_1075.f0\00", align 1 +@.str161 = private unnamed_addr constant [10 x i8] c"g_1075.f1\00", align 1 +@.str162 = private unnamed_addr constant [10 x i8] c"g_1075.f2\00", align 1 +@.str163 = private unnamed_addr constant [10 x i8] c"g_1075.f3\00", align 1 +@g_1137 = internal unnamed_addr global i16 -30603, align 2 +@.str164 = private unnamed_addr constant [7 x i8] c"g_1137\00", align 1 +@g_1209 = internal unnamed_addr global i16 12544, align 2 +@.str165 = private unnamed_addr constant [7 x i8] c"g_1209\00", align 1 +@g_1211 = internal unnamed_addr global i32 80803188, align 4 +@.str166 = private unnamed_addr constant [7 x i8] c"g_1211\00", align 1 +@g_1326 = internal unnamed_addr global [8 x i32] [i32 8, i32 8, i32 -6, i32 -6, i32 -6, i32 8, i32 -7, i32 -7], align 4 +@.str167 = private unnamed_addr constant [10 x i8] c"g_1326[i]\00", align 1 +@.str168 = private unnamed_addr constant [7 x i8] c"g_1518\00", align 1 +@.str169 = private unnamed_addr constant [7 x i8] c"g_1530\00", align 1 +@g_1531 = internal unnamed_addr global i32 -2102599148, align 4 +@.str170 = private unnamed_addr constant [7 x i8] c"g_1531\00", align 1 +@.str171 = private unnamed_addr constant [7 x i8] c"g_1540\00", align 1 +@g_1541 = internal unnamed_addr global i16 -1, align 2 +@.str172 = private unnamed_addr constant [7 x i8] c"g_1541\00", align 1 +@.str173 = private unnamed_addr constant [7 x i8] c"g_1542\00", align 1 +@.str174 = private unnamed_addr constant [7 x i8] c"g_1543\00", align 1 +@g_1544 = internal unnamed_addr global i32 -1075110111, align 4 +@.str175 = private unnamed_addr constant [7 x i8] c"g_1544\00", align 1 +@g_1639 = internal global i8 -2, align 1 +@.str176 = private unnamed_addr constant [7 x i8] c"g_1639\00", align 1 +@g_1737 = internal unnamed_addr constant [1 x [6 x [9 x %union.U4]]] [[6 x [9 x %union.U4]] [[9 x %union.U4] [%union.U4 { i32 -513569997 }, %union.U4 { i32 1 }, %union.U4 { i32 1 }, %union.U4 { i32 -271352390 }, %union.U4 { i32 1492635285 }, %union.U4 { i32 1 }, %union.U4 { i32 -6 }, %union.U4 { i32 -1640860186 }, %union.U4 { i32 -6 }], [9 x %union.U4] [%union.U4 { i32 -1368613310 }, %union.U4 { i32 -5 }, %union.U4 { i32 -2126413891 }, %union.U4 { i32 -2126413891 }, %union.U4 { i32 1823702945 }, %union.U4 { i32 1272602072 }, %union.U4 { i32 -2126413891 }, %union.U4 { i32 -1368613310 }, %union.U4 { i32 2129204323 }], [9 x %union.U4] [%union.U4 zeroinitializer, %union.U4 { i32 1492635285 }, %union.U4 zeroinitializer, %union.U4 { i32 1487751473 }, %union.U4 { i32 1487751473 }, %union.U4 { i32 1 }, %union.U4 { i32 -513569997 }, %union.U4 { i32 1487751473 }, %union.U4 { i32 1492635285 }], [9 x %union.U4] [%union.U4 { i32 1823702945 }, %union.U4 { i32 -2002368716 }, %union.U4 { i32 -1832387217 }, %union.U4 { i32 1272602072 }, %union.U4 { i32 1823702945 }, %union.U4 { i32 1823702945 }, %union.U4 { i32 -5 }, %union.U4 { i32 -1368613310 }, %union.U4 { i32 1823702945 }], [9 x %union.U4] [%union.U4 { i32 -513569997 }, %union.U4 { i32 -1866190761 }, %union.U4 { i32 -1640860186 }, %union.U4 { i32 1 }, %union.U4 { i32 -6 }, %union.U4 { i32 -1866190761 }, %union.U4 { i32 -1866190761 }, %union.U4 { i32 1492635285 }, %union.U4 { i32 1487751473 }], [9 x %union.U4] [%union.U4 { i32 -188486937 }, %union.U4 { i32 -2126413891 }, %union.U4 { i32 -188486937 }, %union.U4 { i32 -5 }, %union.U4 { i32 8 }, %union.U4 { i32 -5 }, %union.U4 { i32 -188486937 }, %union.U4 { i32 -188486937 }, %union.U4 { i32 1823702945 }]]], align 4 +@.str177 = private unnamed_addr constant [19 x i8] c"g_1737[i][j][k].f0\00", align 1 +@.str178 = private unnamed_addr constant [19 x i8] c"g_1737[i][j][k].f1\00", align 1 +@.str179 = private unnamed_addr constant [19 x i8] c"g_1737[i][j][k].f2\00", align 1 +@.str180 = private unnamed_addr constant [19 x i8] c"g_1737[i][j][k].f3\00", align 1 +@crc32_context = internal unnamed_addr global i32 -1, align 4 +@.str181 = private unnamed_addr constant [15 x i8] c"checksum = %X\0A\00", align 1 +@g_649 = internal global { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -9, i32 4, i8 55, i8 18, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 3, i32 -533516120, i32 1392086955, i32 -9, i32 1854958672, i16 5, i32 -154239720, i8 -1, [3 x i8] undef, i8 27, i8 48, i8 0, i8 0, i16 14074, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 105, i32 5, i32 1631521711, i32 573890954, i32 -1866043804, i16 0, i32 1731355470, i8 -84, [3 x i8] undef, i8 46, i8 22, i8 0, i8 0, i16 31245, [2 x i8] undef }, i8 95, [3 x i8] undef }, align 4 +@g_647 = internal global <{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }> <{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 87, i32 2121274849, i8 -72, i8 9, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 60, i32 1, i32 1470943878, i32 1, i32 612042415, i16 0, i32 2144098676, i8 -1, [3 x i8] undef, i8 35, i8 78, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 6, i32 -1822390552, i32 5, i32 -1733470896, i32 1983147151, i16 -20410, i32 1776828983, i8 1, [3 x i8] undef, i8 126, i8 7, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -3, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 87, i32 2121274849, i8 -72, i8 9, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 60, i32 1, i32 1470943878, i32 1, i32 612042415, i16 0, i32 2144098676, i8 -1, [3 x i8] undef, i8 35, i8 78, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 6, i32 -1822390552, i32 5, i32 -1733470896, i32 1983147151, i16 -20410, i32 1776828983, i8 1, [3 x i8] undef, i8 126, i8 7, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -3, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 87, i32 2121274849, i8 -72, i8 9, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 60, i32 1, i32 1470943878, i32 1, i32 612042415, i16 0, i32 2144098676, i8 -1, [3 x i8] undef, i8 35, i8 78, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 6, i32 -1822390552, i32 5, i32 -1733470896, i32 1983147151, i16 -20410, i32 1776828983, i8 1, [3 x i8] undef, i8 126, i8 7, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -3, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 87, i32 2121274849, i8 -72, i8 9, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 60, i32 1, i32 1470943878, i32 1, i32 612042415, i16 0, i32 2144098676, i8 -1, [3 x i8] undef, i8 35, i8 78, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 6, i32 -1822390552, i32 5, i32 -1733470896, i32 1983147151, i16 -20410, i32 1776828983, i8 1, [3 x i8] undef, i8 126, i8 7, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -3, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 87, i32 2121274849, i8 -72, i8 9, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 60, i32 1, i32 1470943878, i32 1, i32 612042415, i16 0, i32 2144098676, i8 -1, [3 x i8] undef, i8 35, i8 78, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 6, i32 -1822390552, i32 5, i32 -1733470896, i32 1983147151, i16 -20410, i32 1776828983, i8 1, [3 x i8] undef, i8 126, i8 7, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -3, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 87, i32 2121274849, i8 -72, i8 9, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 60, i32 1, i32 1470943878, i32 1, i32 612042415, i16 0, i32 2144098676, i8 -1, [3 x i8] undef, i8 35, i8 78, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 6, i32 -1822390552, i32 5, i32 -1733470896, i32 1983147151, i16 -20410, i32 1776828983, i8 1, [3 x i8] undef, i8 126, i8 7, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -3, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 87, i32 2121274849, i8 -72, i8 9, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 60, i32 1, i32 1470943878, i32 1, i32 612042415, i16 0, i32 2144098676, i8 -1, [3 x i8] undef, i8 35, i8 78, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 6, i32 -1822390552, i32 5, i32 -1733470896, i32 1983147151, i16 -20410, i32 1776828983, i8 1, [3 x i8] undef, i8 126, i8 7, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -3, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 87, i32 2121274849, i8 -72, i8 9, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 60, i32 1, i32 1470943878, i32 1, i32 612042415, i16 0, i32 2144098676, i8 -1, [3 x i8] undef, i8 35, i8 78, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 6, i32 -1822390552, i32 5, i32 -1733470896, i32 1983147151, i16 -20410, i32 1776828983, i8 1, [3 x i8] undef, i8 126, i8 7, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -3, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 87, i32 2121274849, i8 -72, i8 9, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 60, i32 1, i32 1470943878, i32 1, i32 612042415, i16 0, i32 2144098676, i8 -1, [3 x i8] undef, i8 35, i8 78, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 6, i32 -1822390552, i32 5, i32 -1733470896, i32 1983147151, i16 -20410, i32 1776828983, i8 1, [3 x i8] undef, i8 126, i8 7, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -3, [3 x i8] undef } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -110, i32 -3, i8 118, i8 24, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -39, i32 626814409, i32 475710044, i32 1, i32 0, i16 -1, i32 6, i8 115, [3 x i8] undef, i8 -59, i8 33, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -14, i32 -456774250, i32 -1972472119, i32 -5, i32 1210377991, i16 -15869, i32 -543945797, i8 1, [3 x i8] undef, i8 116, i8 2, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -61, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -110, i32 -3, i8 118, i8 24, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -39, i32 626814409, i32 475710044, i32 1, i32 0, i16 -1, i32 6, i8 115, [3 x i8] undef, i8 -59, i8 33, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -14, i32 -456774250, i32 -1972472119, i32 -5, i32 1210377991, i16 -15869, i32 -543945797, i8 1, [3 x i8] undef, i8 116, i8 2, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -61, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -110, i32 -3, i8 118, i8 24, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -39, i32 626814409, i32 475710044, i32 1, i32 0, i16 -1, i32 6, i8 115, [3 x i8] undef, i8 -59, i8 33, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -14, i32 -456774250, i32 -1972472119, i32 -5, i32 1210377991, i16 -15869, i32 -543945797, i8 1, [3 x i8] undef, i8 116, i8 2, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -61, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -110, i32 -3, i8 118, i8 24, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -39, i32 626814409, i32 475710044, i32 1, i32 0, i16 -1, i32 6, i8 115, [3 x i8] undef, i8 -59, i8 33, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -14, i32 -456774250, i32 -1972472119, i32 -5, i32 1210377991, i16 -15869, i32 -543945797, i8 1, [3 x i8] undef, i8 116, i8 2, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -61, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -110, i32 -3, i8 118, i8 24, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -39, i32 626814409, i32 475710044, i32 1, i32 0, i16 -1, i32 6, i8 115, [3 x i8] undef, i8 -59, i8 33, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -14, i32 -456774250, i32 -1972472119, i32 -5, i32 1210377991, i16 -15869, i32 -543945797, i8 1, [3 x i8] undef, i8 116, i8 2, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -61, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -110, i32 -3, i8 118, i8 24, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -39, i32 626814409, i32 475710044, i32 1, i32 0, i16 -1, i32 6, i8 115, [3 x i8] undef, i8 -59, i8 33, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -14, i32 -456774250, i32 -1972472119, i32 -5, i32 1210377991, i16 -15869, i32 -543945797, i8 1, [3 x i8] undef, i8 116, i8 2, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -61, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -110, i32 -3, i8 118, i8 24, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -39, i32 626814409, i32 475710044, i32 1, i32 0, i16 -1, i32 6, i8 115, [3 x i8] undef, i8 -59, i8 33, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -14, i32 -456774250, i32 -1972472119, i32 -5, i32 1210377991, i16 -15869, i32 -543945797, i8 1, [3 x i8] undef, i8 116, i8 2, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -61, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -110, i32 -3, i8 118, i8 24, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -39, i32 626814409, i32 475710044, i32 1, i32 0, i16 -1, i32 6, i8 115, [3 x i8] undef, i8 -59, i8 33, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -14, i32 -456774250, i32 -1972472119, i32 -5, i32 1210377991, i16 -15869, i32 -543945797, i8 1, [3 x i8] undef, i8 116, i8 2, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -61, [3 x i8] undef }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -110, i32 -3, i8 118, i8 24, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -39, i32 626814409, i32 475710044, i32 1, i32 0, i16 -1, i32 6, i8 115, [3 x i8] undef, i8 -59, i8 33, i8 0, i8 0, i16 -1, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 -14, i32 -456774250, i32 -1972472119, i32 -5, i32 1210377991, i16 -15869, i32 -543945797, i8 1, [3 x i8] undef, i8 116, i8 2, i8 0, i8 0, i16 7, [2 x i8] undef }, i8 -61, [3 x i8] undef } }> }>, align 4 +@g_261 = internal global { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 34, i32 1, i32 -9, i32 -7, i32 0, i16 10822, i32 -1893550337, i8 -1, [3 x i8] undef, i8 41, i8 81, i8 0, i8 0, i16 -18532, [2 x i8] undef }, align 4 +@g_38 = internal global { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } { i8 -5, i32 1, i8 40, i8 25, i8 0, i8 0, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 8, i32 7, i32 1, i32 0, i32 -185147255, i16 -10, i32 -323821878, i8 101, [3 x i8] undef, i8 -21, i8 -92, i8 0, i8 0, i16 2, [2 x i8] undef }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] } { i8 45, i32 -1, i32 -218183498, i32 -473519531, i32 1765140400, i16 -25635, i32 -560658624, i8 40, [3 x i8] undef, i8 81, i8 -83, i8 0, i8 0, i16 0, [2 x i8] undef }, i8 0, [3 x i8] undef }, align 4 +@g_17 = internal global { i8, i8, [2 x i8], i8, i8, i8, i8, i8, i8, [2 x i8] } { i8 9, i8 0, [2 x i8] undef, i8 -79, i8 -9, i8 127, i8 undef, i8 15, i8 0, [2 x i8] undef }, align 4 +@.str182 = private unnamed_addr constant [36 x i8] c"...checksum after hashing %s : %lX\0A\00", align 1 +@crc32_tab = internal unnamed_addr global [256 x i32] zeroinitializer, align 4 +@g_1335 = internal global i32* getelementptr inbounds (%union.U4* @g_123, i32 0, i32 0), align 4 +@g_1357 = internal global i8**** null, align 4 +@g_1726 = internal unnamed_addr global [4 x i8*****] [i8***** @g_1727, i8***** @g_1727, i8***** @g_1727, i8***** @g_1727], align 4 +@g_1727 = internal constant i8**** @g_1728, align 4 +@g_1728 = internal global i8*** @g_1729, align 4 +@g_1729 = internal constant i8** getelementptr inbounds ([3 x [3 x [10 x i8*]]]* @g_1730, i32 0, i32 1, i32 1, i32 4), align 4 +@g_1730 = internal global [3 x [3 x [10 x i8*]]] [[3 x [10 x i8*]] [[10 x i8*] [i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5), i8* @g_1639, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5)], [10 x i8*] [i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_153, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232)], [10 x i8*] [i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5)]], [3 x [10 x i8*]] [[10 x i8*] [i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_153, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92)], [10 x i8*] [i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_153, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5), i8* @g_153, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_153, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5)], [10 x i8*] [i8* @g_1639, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_153, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92)]], [3 x [10 x i8*]] [[10 x i8*] [i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_153, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92)], [10 x i8*] [i8* @g_1639, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5), i8* @g_153, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_153, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_153, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5)], [10 x i8*] [i8* @g_1639, i8* getelementptr inbounds ([1 x [3 x [6 x i8]]]* @g_839, i32 0, i32 0, i64 2, i64 5), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_153, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds (<{ <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }>, <{ { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }, { i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] } }> }>* @g_647, i32 0, i32 0, i32 0, i32 0), i64 232), i8* @g_1639, i8* getelementptr (i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 0), i64 92)]]], align 4 +@g_1430 = internal unnamed_addr global %union.U3* @g_388, align 4 +@g_388 = internal global %union.U3 zeroinitializer, align 4 +@g_171 = internal global i8* getelementptr inbounds ({ i8, i32, i8, i8, i8, i8, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, { i8, i32, i32, i32, i32, i16, i32, i8, [3 x i8], i8, i8, i8, i8, i16, [2 x i8] }, i8, [3 x i8] }* @g_38, i32 0, i32 6, i32 7), align 4 +@g_170 = internal unnamed_addr global [10 x [6 x [4 x i8**]]] [[6 x [4 x i8**]] [[4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** null], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** null], [4 x i8**] [i8** @g_171, i8** null, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171]], [6 x [4 x i8**]] [[4 x i8**] [i8** @g_171, i8** null, i8** null, i8** null], [4 x i8**] [i8** @g_171, i8** null, i8** @g_171, i8** null], [4 x i8**] [i8** @g_171, i8** null, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** null, i8** null, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** null]], [6 x [4 x i8**]] [[4 x i8**] [i8** @g_171, i8** @g_171, i8** null, i8** @g_171], [4 x i8**] [i8** null, i8** null, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** null, i8** null], [4 x i8**] [i8** null, i8** @g_171, i8** @g_171, i8** null]], [6 x [4 x i8**]] [[4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** null, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** null, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** null, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** null, i8** @g_171]], [6 x [4 x i8**]] [[4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** null, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** null, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** null, i8** null, i8** null], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** null]], [6 x [4 x i8**]] [[4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** null, i8** @g_171], [4 x i8**] [i8** null, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** null, i8** @g_171, i8** @g_171, i8** @g_171]], [6 x [4 x i8**]] [[4 x i8**] [i8** null, i8** @g_171, i8** @g_171, i8** null], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** null, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** null]], [6 x [4 x i8**]] [[4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** null], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171]], [6 x [4 x i8**]] [[4 x i8**] [i8** @g_171, i8** null, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** null, i8** @g_171, i8** @g_171], [4 x i8**] [i8** null, i8** null, i8** @g_171, i8** null], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** null], [4 x i8**] [i8** null, i8** null, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171]], [6 x [4 x i8**]] [[4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** null, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** null, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** @g_171, i8** @g_171], [4 x i8**] [i8** @g_171, i8** @g_171, i8** null, i8** @g_171]]], align 4 +@g_286 = internal global [10 x i32*] [i32* @g_287, i32* @g_287, i32* @g_287, i32* @g_287, i32* @g_287, i32* @g_287, i32* @g_287, i32* @g_287, i32* @g_287, i32* @g_287], align 4 +@g_287 = internal constant i32 -1, align 4 + +define i32 @main(i32 %argc, i8** nocapture %argv) nounwind { + %p_6.i.i = alloca %union.U3, align 8 + %1 = icmp eq i32 %argc, 2 + br i1 %1, label %2, label %7 + +;