~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to src/analyzer.js

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-06-11 15:45:24 UTC
  • mfrom: (1.2.1) (2.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20130611154524-rppb3w6tixlegv4n
Tags: 1.4.7~20130611~a1eb425-1
* New snapshot release
* Upload to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
var LABEL_ENDERS = set('branch', 'return', 'switch');
21
21
var SIDE_EFFECT_CAUSERS = set('call', 'invoke', 'atomic');
22
22
var UNUNFOLDABLE = set('value', 'structvalue', 'type', 'phiparam');
 
23
var I64_DOUBLE_FLIP = { i64: 'double', double: 'i64' };
23
24
 
24
25
// Analyzer
25
26
 
99
100
        }
100
101
      }
101
102
      delete item.items;
 
103
      this.forwardItem(item, 'CastAway');
 
104
    }
 
105
  });
 
106
 
 
107
  // CastAway - try to remove bitcasts of double<-->i64, which LLVM sometimes generates unnecessarily
 
108
  // (load a double, convert to i64, use as i64).
 
109
  // We optimize this by checking if there are such bitcasts. If so we create a shadow
 
110
  // variable that is of the other type, and use that in the relevant places. (As SSA, this is valid, and
 
111
  // variable elimination later will remove the double load if it is no longer needed.)
 
112
  //
 
113
  // Note that aside from being an optimization, this is needed for correctness in some cases: If code
 
114
  // assumes it can bitcast a double to an i64 and back and forth without loss, that may be violated
 
115
  // due to NaN canonicalization.
 
116
  substrate.addActor('CastAway', {
 
117
    processItem: function(item) {
102
118
      this.forwardItem(item, 'Legalizer');
 
119
      if (USE_TYPED_ARRAYS != 2) return;
 
120
 
 
121
      item.functions.forEach(function(func) {
 
122
        var has = false;
 
123
        func.labels.forEach(function(label) {
 
124
          var lines = label.lines;
 
125
          for (var i = 0; i < lines.length; i++) {
 
126
            var line = lines[i];
 
127
            if (line.intertype == 'bitcast' && line.type in I64_DOUBLE_FLIP) {
 
128
              has = true;
 
129
            }
 
130
          }
 
131
        });
 
132
        if (!has) return;
 
133
        // there are i64<-->double bitcasts, create shadows for everything
 
134
        var shadowed = {};
 
135
        func.labels.forEach(function(label) {
 
136
          var lines = label.lines;
 
137
          var i = 0;
 
138
          while (i < lines.length) {
 
139
          var lines = label.lines;
 
140
            var line = lines[i];
 
141
            if (line.intertype == 'load' && line.type in I64_DOUBLE_FLIP) {
 
142
              if (line.pointer.intertype != 'value') { i++; continue } // TODO
 
143
              shadowed[line.assignTo] = 1;
 
144
              var shadow = line.assignTo + '$$SHADOW';
 
145
              var flip = I64_DOUBLE_FLIP[line.type];
 
146
              lines.splice(i + 1, 0, { // if necessary this element will be legalized in the next phase
 
147
                tokens: null,
 
148
                indent: 2,
 
149
                lineNum: line.lineNum + 0.5,
 
150
                assignTo: shadow,
 
151
                intertype: 'load',
 
152
                pointerType: flip + '*',
 
153
                type: flip,
 
154
                valueType: flip,
 
155
                pointer: {
 
156
                 intertype: 'value',
 
157
                 ident: line.pointer.ident,
 
158
                 type: flip + '*'
 
159
                },
 
160
                align: line.align,
 
161
                ident: line.ident
 
162
              });
 
163
              // note: no need to update func.lines, it is generated in a later pass
 
164
              i++;
 
165
            }
 
166
            i++;
 
167
          }
 
168
        });
 
169
        // use shadows where possible
 
170
        func.labels.forEach(function(label) {
 
171
          var lines = label.lines;
 
172
          for (var i = 0; i < lines.length; i++) {
 
173
            var line = lines[i];
 
174
            if (line.intertype == 'bitcast' && line.type in I64_DOUBLE_FLIP && line.ident in shadowed) {
 
175
              var shadow = line.ident + '$$SHADOW';
 
176
              line.params[0].ident = shadow;
 
177
              line.params[0].type = line.type;
 
178
              line.type2 = line.type;
 
179
            }
 
180
          }
 
181
        });
 
182
      });
103
183
    }
104
184
  });
105
185
 
174
254
          var factor = (next - prev)/(4*toAdd.length+3);
175
255
          for (var k = 0; k < toAdd.length; k++) {
176
256
            toAdd[k].lineNum = prev + ((k+1)*factor);
 
257
            assert(k == 0 || toAdd[k].lineNum > toAdd[k-1].lineNum);
177
258
          }
178
259
        }
179
260
        function removeAndAdd(lines, i, toAdd) {
180
261
          var item = lines[i];
181
262
          interpLines(lines, i, toAdd);
182
263
          Array.prototype.splice.apply(lines, [i, 1].concat(toAdd));
 
264
          if (i > 0) assert(lines[i].lineNum > lines[i-1].lineNum);
 
265
          if (i + toAdd.length < lines.length) assert(lines[i + toAdd.length - 1].lineNum < lines[i + toAdd.length].lineNum);
183
266
          return toAdd.length;
184
267
        }
185
268
        function legalizeFunctionParameters(params) {
328
411
                  // legalize parameters
329
412
                  legalizeFunctionParameters(value.params);
330
413
                  // legalize return value, if any
331
 
                  if (value.assignTo && isIllegalType(item.type)) {
332
 
                    bits = getBits(value.type);
 
414
                  var returnType = getReturnType(item.type);
 
415
                  if (value.assignTo && isIllegalType(returnType)) {
 
416
                    bits = getBits(returnType);
333
417
                    var elements = getLegalVars(item.assignTo, bits);
334
418
                    // legalize return value
335
419
                    value.assignTo = elements[0].ident;