Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Side by Side Diff: lib/Target/JSBackend/JSBackend.cpp

Issue 1692803002: Remove Emscripten support (Closed) Base URL: https://chromium.googlesource.com/a/native_client/pnacl-llvm.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/Target/JSBackend/JS.h ('k') | lib/Target/JSBackend/JSTargetMachine.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===-- JSBackend.cpp - Library for converting LLVM code to JS -----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements compiling of LLVM IR, which is assumed to have been
11 // simplified using the PNaCl passes, i64 legalization, and other necessary
12 // transformations, into JavaScript in asm.js format, suitable for passing
13 // to emscripten for final processing.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #include "JSTargetMachine.h"
18 #include "MCTargetDesc/JSBackendMCTargetDesc.h"
19 #include "AllocaManager.h"
20 #include "llvm/Analysis/ValueTracking.h"
21 #include "llvm/ADT/SmallPtrSet.h"
22 #include "llvm/ADT/SmallString.h"
23 #include "llvm/ADT/StringExtras.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/Config/config.h"
26 #include "llvm/IR/Constants.h"
27 #include "llvm/IR/DerivedTypes.h"
28 #include "llvm/IR/InlineAsm.h"
29 #include "llvm/IR/Instruction.h"
30 #include "llvm/IR/Instructions.h"
31 #include "llvm/IR/Intrinsics.h"
32 #include "llvm/IR/Module.h"
33 #include "llvm/IR/Operator.h"
34 #include "llvm/Pass.h"
35 #include "llvm/IR/LegacyPassManager.h"
36 #include "llvm/IR/CallSite.h"
37 #include "llvm/Support/CommandLine.h"
38 #include "llvm/Support/ErrorHandling.h"
39 #include "llvm/IR/GetElementPtrTypeIterator.h"
40 #include "llvm/Support/MathExtras.h"
41 #include "llvm/Support/TargetRegistry.h"
42 #include "llvm/IR/DebugInfo.h"
43 #include "llvm/Transforms/NaCl.h"
44 #include <algorithm>
45 #include <cstdio>
46 #include <map>
47 #include <set> // TODO: unordered_set?
48 using namespace llvm;
49
50 #include <OptPasses.h>
51 #include <Relooper.h>
52
53 #ifdef NDEBUG
54 #undef assert
55 #define assert(x) { if (!(x)) report_fatal_error(#x); }
56 #endif
57
58 raw_ostream &prettyWarning() {
59 errs().changeColor(raw_ostream::YELLOW);
60 errs() << "warning:";
61 errs().resetColor();
62 errs() << " ";
63 return errs();
64 }
65
66 static cl::opt<bool>
67 PreciseF32("emscripten-precise-f32",
68 cl::desc("Enables Math.fround usage to implement precise float32 sema ntics and performance (see emscripten PRECISE_F32 option)"),
69 cl::init(false));
70
71 static cl::opt<bool>
72 WarnOnUnaligned("emscripten-warn-unaligned",
73 cl::desc("Warns about unaligned loads and stores (which can nega tively affect performance)"),
74 cl::init(false));
75
76 static cl::opt<int>
77 ReservedFunctionPointers("emscripten-reserved-function-pointers",
78 cl::desc("Number of reserved slots in function tables f or functions to be added at runtime (see emscripten RESERVED_FUNCTION_POINTERS o ption)"),
79 cl::init(0));
80
81 static cl::opt<int>
82 EmscriptenAssertions("emscripten-assertions",
83 cl::desc("Additional JS-specific assertions (see emscripten ASSERTIONS)"),
84 cl::init(0));
85
86 static cl::opt<bool>
87 NoAliasingFunctionPointers("emscripten-no-aliasing-function-pointers",
88 cl::desc("Forces function pointers to not alias (this is more correct, but rarely needed, and has the cost of much larger function ta bles; it is useful for debugging though; see emscripten ALIASING_FUNCTION_POINTE RS option)"),
89 cl::init(false));
90
91 static cl::opt<int>
92 GlobalBase("emscripten-global-base",
93 cl::desc("Where global variables start out in memory (see emscripten GLOBAL_BASE option)"),
94 cl::init(8));
95
96
97 extern "C" void LLVMInitializeJSBackendTarget() {
98 // Register the target.
99 RegisterTargetMachine<JSTargetMachine> X(TheJSBackendTarget);
100 }
101
102 namespace {
103 #define ASM_SIGNED 0
104 #define ASM_UNSIGNED 1
105 #define ASM_NONSPECIFIC 2 // nonspecific means to not differentiate ints. |0 f or all, regardless of size and sign
106 #define ASM_FFI_IN 4 // FFI return values are limited to things that work in f fis
107 #define ASM_FFI_OUT 8 // params to FFIs are limited to things that work in ffi s
108 #define ASM_MUST_CAST 16 // this value must be explicitly cast (or be an integ er constant)
109 typedef unsigned AsmCast;
110
111 const char *const SIMDLane = "XYZW";
112 const char *const simdLane = "xyzw";
113
114 typedef std::map<const Value*,std::string> ValueMap;
115 typedef std::set<std::string> NameSet;
116 typedef std::vector<unsigned char> HeapData;
117 typedef std::pair<unsigned, unsigned> Address;
118 typedef std::map<std::string, Type *> VarMap;
119 typedef std::map<std::string, Address> GlobalAddressMap;
120 typedef std::vector<std::string> FunctionTable;
121 typedef std::map<std::string, FunctionTable> FunctionTableMap;
122 typedef std::map<std::string, std::string> StringMap;
123 typedef std::map<std::string, unsigned> NameIntMap;
124 typedef std::map<const BasicBlock*, unsigned> BlockIndexMap;
125 typedef std::map<const Function*, BlockIndexMap> BlockAddressMap;
126 typedef std::map<const BasicBlock*, Block*> LLVMToRelooperMap;
127
128 /// JSWriter - This class is the main chunk of code that converts an LLVM
129 /// module to JavaScript.
130 class JSWriter : public ModulePass {
131 raw_pwrite_stream &Out;
132 const Module *TheModule;
133 unsigned UniqueNum;
134 unsigned NextFunctionIndex; // used with NoAliasingFunctionPointers
135 ValueMap ValueNames;
136 VarMap UsedVars;
137 AllocaManager Allocas;
138 HeapData GlobalData8;
139 HeapData GlobalData32;
140 HeapData GlobalData64;
141 GlobalAddressMap GlobalAddresses;
142 NameSet Externals; // vars
143 NameSet Declares; // funcs
144 StringMap Redirects; // library function redirects actually used, needed for wrapper funcs in tables
145 std::string PostSets;
146 NameIntMap NamedGlobals; // globals that we export as metadata to JS, so it can access them by name
147 std::map<std::string, unsigned> IndexedFunctions; // name -> index
148 FunctionTableMap FunctionTables; // sig => list of functions
149 std::vector<std::string> GlobalInitializers;
150 std::vector<std::string> Exports; // additional exports
151 BlockAddressMap BlockAddresses;
152
153 std::string CantValidate;
154 bool UsesSIMD;
155 int InvokeState; // cycles between 0, 1 after preInvoke, 2 after call, 0 aga in after postInvoke. hackish, no argument there.
156 CodeGenOpt::Level OptLevel;
157 const DataLayout *DL;
158 bool StackBumped;
159
160 #include "CallHandlers.h"
161
162 public:
163 static char ID;
164 JSWriter(raw_pwrite_stream &o, CodeGenOpt::Level OptLevel)
165 : ModulePass(ID), Out(o), UniqueNum(0), NextFunctionIndex(0), CantValidate (""), UsesSIMD(false), InvokeState(0),
166 OptLevel(OptLevel), StackBumped(false) {}
167
168 virtual const char *getPassName() const { return "JavaScript backend"; }
169
170 virtual bool runOnModule(Module &M);
171
172 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
173 AU.setPreservesAll();
174 ModulePass::getAnalysisUsage(AU);
175 }
176
177 void printProgram(const std::string& fname, const std::string& modName );
178 void printModule(const std::string& fname, const std::string& modName );
179 void printFunction(const Function *F);
180
181 LLVM_ATTRIBUTE_NORETURN void error(const std::string& msg);
182
183 raw_pwrite_stream& nl(raw_pwrite_stream &Out, int delta = 0);
184
185 private:
186 void printCommaSeparated(const HeapData v);
187
188 // parsing of constants has two phases: calculate, and then emit
189 void parseConstant(const std::string& name, const Constant* CV, bool calcula te);
190
191 #define MEM_ALIGN 8
192 #define MEM_ALIGN_BITS 64
193 #define STACK_ALIGN 16
194 #define STACK_ALIGN_BITS 128
195
196 unsigned stackAlign(unsigned x) {
197 return RoundUpToAlignment(x, STACK_ALIGN);
198 }
199 std::string stackAlignStr(std::string x) {
200 return "((" + x + "+" + utostr(STACK_ALIGN-1) + ")&-" + utostr(STACK_ALIGN ) + ")";
201 }
202
203 HeapData *allocateAddress(const std::string& Name, unsigned Bits = MEM_ALIGN _BITS) {
204 assert(Bits == 64); // FIXME when we use optimal alignments
205 HeapData *GlobalData = NULL;
206 switch (Bits) {
207 case 8: GlobalData = &GlobalData8; break;
208 case 32: GlobalData = &GlobalData32; break;
209 case 64: GlobalData = &GlobalData64; break;
210 default: llvm_unreachable("Unsupported data element size");
211 }
212 while (GlobalData->size() % (Bits/8) != 0) GlobalData->push_back(0);
213 GlobalAddresses[Name] = Address(GlobalData->size(), Bits);
214 return GlobalData;
215 }
216
217 // return the absolute offset of a global
218 unsigned getGlobalAddress(const std::string &s) {
219 GlobalAddressMap::const_iterator I = GlobalAddresses.find(s);
220 if (I == GlobalAddresses.end()) {
221 report_fatal_error("cannot find global address " + Twine(s));
222 }
223 Address a = I->second;
224 assert(a.second == 64); // FIXME when we use optimal alignments
225 unsigned Ret;
226 switch (a.second) {
227 case 64:
228 assert((a.first + GlobalBase)%8 == 0);
229 Ret = a.first + GlobalBase;
230 break;
231 case 32:
232 assert((a.first + GlobalBase)%4 == 0);
233 Ret = a.first + GlobalBase + GlobalData64.size();
234 break;
235 case 8:
236 Ret = a.first + GlobalBase + GlobalData64.size() + GlobalData32.size() ;
237 break;
238 default:
239 report_fatal_error("bad global address " + Twine(s) + ": "
240 "count=" + Twine(a.first) + " "
241 "elementsize=" + Twine(a.second));
242 }
243 return Ret;
244 }
245 // returns the internal offset inside the proper block: GlobalData8, 32, 64
246 unsigned getRelativeGlobalAddress(const std::string &s) {
247 GlobalAddressMap::const_iterator I = GlobalAddresses.find(s);
248 if (I == GlobalAddresses.end()) {
249 report_fatal_error("cannot find global address " + Twine(s));
250 }
251 Address a = I->second;
252 return a.first;
253 }
254 char getFunctionSignatureLetter(Type *T) {
255 if (T->isVoidTy()) return 'v';
256 else if (T->isFloatingPointTy()) {
257 if (PreciseF32 && T->isFloatTy()) {
258 return 'f';
259 } else {
260 return 'd';
261 }
262 } else if (VectorType *VT = dyn_cast<VectorType>(T)) {
263 checkVectorType(VT);
264 if (VT->getElementType()->isIntegerTy()) {
265 return 'I';
266 } else {
267 return 'F';
268 }
269 } else {
270 return 'i';
271 }
272 }
273 std::string getFunctionSignature(const FunctionType *F, const std::string *N ame=NULL) {
274 std::string Ret;
275 Ret += getFunctionSignatureLetter(F->getReturnType());
276 for (FunctionType::param_iterator AI = F->param_begin(),
277 AE = F->param_end(); AI != AE; ++AI) {
278 Ret += getFunctionSignatureLetter(*AI);
279 }
280 return Ret;
281 }
282 FunctionTable& ensureFunctionTable(const FunctionType *FT) {
283 FunctionTable &Table = FunctionTables[getFunctionSignature(FT)];
284 unsigned MinSize = ReservedFunctionPointers ? 2*(ReservedFunctionPointers+ 1) : 1; // each reserved slot must be 2-aligned
285 while (Table.size() < MinSize) Table.push_back("0");
286 return Table;
287 }
288 unsigned getFunctionIndex(const Function *F) {
289 const std::string &Name = getJSName(F);
290 if (IndexedFunctions.find(Name) != IndexedFunctions.end()) return IndexedF unctions[Name];
291 std::string Sig = getFunctionSignature(F->getFunctionType(), &Name);
292 FunctionTable& Table = ensureFunctionTable(F->getFunctionType());
293 if (NoAliasingFunctionPointers) {
294 while (Table.size() < NextFunctionIndex) Table.push_back("0");
295 }
296 // XXX this is wrong, it's always 1. but, that's fine in the ARM-like ABI
297 // we have which allows unaligned func the one risk is if someone forces a
298 // function to be aligned, and relies on that. Could do F->getAlignment()
299 // instead.
300 unsigned Alignment = 1;
301 while (Table.size() % Alignment) Table.push_back("0");
302 unsigned Index = Table.size();
303 Table.push_back(Name);
304 IndexedFunctions[Name] = Index;
305 if (NoAliasingFunctionPointers) {
306 NextFunctionIndex = Index+1;
307 }
308
309 // invoke the callHandler for this, if there is one. the function may only be indexed but never called directly, and we may need to do things in the handl er
310 CallHandlerMap::const_iterator CH = CallHandlers.find(Name);
311 if (CH != CallHandlers.end()) {
312 (this->*(CH->second))(NULL, Name, -1);
313 }
314
315 return Index;
316 }
317
318 unsigned getBlockAddress(const Function *F, const BasicBlock *BB) {
319 BlockIndexMap& Blocks = BlockAddresses[F];
320 if (Blocks.find(BB) == Blocks.end()) {
321 Blocks[BB] = Blocks.size(); // block addresses start from 0
322 }
323 return Blocks[BB];
324 }
325
326 unsigned getBlockAddress(const BlockAddress *BA) {
327 return getBlockAddress(BA->getFunction(), BA->getBasicBlock());
328 }
329
330 const Value *resolveFully(const Value *V) {
331 bool More = true;
332 while (More) {
333 More = false;
334 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
335 V = GA->getAliasee();
336 More = true;
337 }
338 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
339 V = CE->getOperand(0); // ignore bitcasts
340 More = true;
341 }
342 }
343 return V;
344 }
345
346 // Return a constant we are about to write into a global as a numeric offset . If the
347 // value is not known at compile time, emit a postSet to that location.
348 unsigned getConstAsOffset(const Value *V, unsigned AbsoluteTarget) {
349 V = resolveFully(V);
350 if (const Function *F = dyn_cast<const Function>(V)) {
351 return getFunctionIndex(F);
352 } else if (const BlockAddress *BA = dyn_cast<const BlockAddress>(V)) {
353 return getBlockAddress(BA);
354 } else {
355 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
356 if (!GV->hasInitializer()) {
357 // We don't have a constant to emit here, so we must emit a postSet
358 // All postsets are of external values, so they are pointers, hence 32-bit
359 std::string Name = getOpName(V);
360 Externals.insert(Name);
361 PostSets += "HEAP32[" + utostr(AbsoluteTarget>>2) + "] = " + Name + ';';
362 return 0; // emit zero in there for now, until the postSet
363 }
364 }
365 return getGlobalAddress(V->getName().str());
366 }
367 }
368
369 // Test whether the given value is known to be an absolute value or one we t urn into an absolute value
370 bool isAbsolute(const Value *P) {
371 if (const IntToPtrInst *ITP = dyn_cast<IntToPtrInst>(P)) {
372 return isa<ConstantInt>(ITP->getOperand(0));
373 }
374 if (isa<ConstantPointerNull>(P) || isa<UndefValue>(P)) {
375 return true;
376 }
377 return false;
378 }
379
380 void checkVectorType(Type *T) {
381 VectorType *VT = cast<VectorType>(T);
382 // LLVM represents the results of vector comparison as vectors of i1. We
383 // represent them as vectors of integers the size of the vector elements
384 // of the compare that produced them.
385 assert(VT->getElementType()->getPrimitiveSizeInBits() == 32 ||
386 VT->getElementType()->getPrimitiveSizeInBits() == 1);
387 assert(VT->getBitWidth() <= 128);
388 assert(VT->getNumElements() <= 4);
389 UsesSIMD = true;
390 }
391
392 std::string ensureCast(std::string S, Type *T, AsmCast sign) {
393 if (sign & ASM_MUST_CAST) return getCast(S, T);
394 return S;
395 }
396
397 std::string ftostr(const ConstantFP *CFP, AsmCast sign) {
398 const APFloat &flt = CFP->getValueAPF();
399
400 // Emscripten has its own spellings for infinity and NaN.
401 if (flt.getCategory() == APFloat::fcInfinity) return ensureCast(flt.isNega tive() ? "-inf" : "inf", CFP->getType(), sign);
402 else if (flt.getCategory() == APFloat::fcNaN) return ensureCast("nan", CFP ->getType(), sign);
403
404 // Request 9 or 17 digits, aka FLT_DECIMAL_DIG or DBL_DECIMAL_DIG (our
405 // long double is the the same as our double), to avoid rounding errors.
406 SmallString<29> Str;
407 flt.toString(Str, PreciseF32 && CFP->getType()->isFloatTy() ? 9 : 17);
408
409 // asm.js considers literals to be floating-point literals when they conta in a
410 // dot, however our output may be processed by UglifyJS, which doesn't
411 // currently preserve dots in all cases. Mark floating-point literals with
412 // unary plus to force them to floating-point.
413 if (APFloat(flt).roundToIntegral(APFloat::rmNearestTiesToEven) == APFloat: :opOK) {
414 return '+' + Str.str().str();
415 }
416
417 return Str.str().str();
418 }
419
420 std::string getPtrLoad(const Value* Ptr);
421 std::string getHeapAccess(const std::string& Name, unsigned Bytes, bool Inte ger=true);
422 std::string getPtrUse(const Value* Ptr);
423 std::string getConstant(const Constant*, AsmCast sign=ASM_SIGNED);
424 std::string getConstantVector(Type *ElementType, std::string x, std::string y, std::string z, std::string w);
425 std::string getValueAsStr(const Value*, AsmCast sign=ASM_SIGNED);
426 std::string getValueAsCastStr(const Value*, AsmCast sign=ASM_SIGNED);
427 std::string getValueAsParenStr(const Value*);
428 std::string getValueAsCastParenStr(const Value*, AsmCast sign=ASM_SIGNED);
429
430 const std::string &getJSName(const Value* val);
431
432 std::string getPhiCode(const BasicBlock *From, const BasicBlock *To);
433
434 void printAttributes(const AttributeSet &PAL, const std::string &name);
435 void printType(Type* Ty);
436 void printTypes(const Module* M);
437
438 std::string getAdHocAssign(const StringRef &, Type *);
439 std::string getAssign(const Instruction *I);
440 std::string getAssignIfNeeded(const Value *V);
441 std::string getCast(const StringRef &, Type *, AsmCast sign=ASM_SIGNED);
442 std::string getParenCast(const StringRef &, Type *, AsmCast sign=ASM_SIGNED) ;
443 std::string getDoubleToInt(const StringRef &);
444 std::string getIMul(const Value *, const Value *);
445 std::string getLoad(const Instruction *I, const Value *P, Type *T, unsigned Alignment, char sep=';');
446 std::string getStore(const Instruction *I, const Value *P, Type *T, const st d::string& VS, unsigned Alignment, char sep=';');
447 std::string getStackBump(unsigned Size);
448 std::string getStackBump(const std::string &Size);
449
450 void addBlock(const BasicBlock *BB, Relooper& R, LLVMToRelooperMap& LLVMToRe looper);
451 void printFunctionBody(const Function *F);
452 void generateInsertElementExpression(const InsertElementInst *III, raw_strin g_ostream& Code);
453 void generateExtractElementExpression(const ExtractElementInst *EEI, raw_str ing_ostream& Code);
454 void generateShuffleVectorExpression(const ShuffleVectorInst *SVI, raw_strin g_ostream& Code);
455 void generateICmpExpression(const ICmpInst *I, raw_string_ostream& Code);
456 void generateFCmpExpression(const FCmpInst *I, raw_string_ostream& Code);
457 void generateShiftExpression(const BinaryOperator *I, raw_string_ostream& Co de);
458 void generateUnrolledExpression(const User *I, raw_string_ostream& Code);
459 bool generateSIMDExpression(const User *I, raw_string_ostream& Code);
460 void generateExpression(const User *I, raw_string_ostream& Code);
461
462 std::string getOpName(const Value*);
463
464 void processConstants();
465
466 // nativization
467
468 typedef std::set<const Value*> NativizedVarsMap;
469 NativizedVarsMap NativizedVars;
470
471 void calculateNativizedVars(const Function *F);
472
473 // special analyses
474
475 bool canReloop(const Function *F);
476
477 // main entry point
478
479 void printModuleBody();
480 };
481 } // end anonymous namespace.
482
483 raw_pwrite_stream &JSWriter::nl(raw_pwrite_stream &Out, int delta) {
484 Out << '\n';
485 return Out;
486 }
487
488 static inline char halfCharToHex(unsigned char half) {
489 assert(half <= 15);
490 if (half <= 9) {
491 return '0' + half;
492 } else {
493 return 'A' + half - 10;
494 }
495 }
496
497 static inline void sanitizeGlobal(std::string& str) {
498 // Global names are prefixed with "_" to prevent them from colliding with
499 // names of things in normal JS.
500 str = "_" + str;
501
502 // functions and globals should already be in C-style format,
503 // in addition to . for llvm intrinsics and possibly $ and so forth.
504 // There is a risk of collisions here, we just lower all these
505 // invalid characters to _, but this should not happen in practice.
506 // TODO: in debug mode, check for such collisions.
507 size_t OriginalSize = str.size();
508 for (size_t i = 1; i < OriginalSize; ++i) {
509 unsigned char c = str[i];
510 if (!isalnum(c) && c != '_') str[i] = '_';
511 }
512 }
513
514 static inline void sanitizeLocal(std::string& str) {
515 // Local names are prefixed with "$" to prevent them from colliding with
516 // global names.
517 str = "$" + str;
518
519 // We need to convert every string that is not a valid JS identifier into
520 // a valid one, without collisions - we cannot turn "x.a" into "x_a" while
521 // also leaving "x_a" as is, for example.
522 //
523 // We leave valid characters 0-9a-zA-Z and _ unchanged. Anything else
524 // we replace with $ and append a hex representation of that value,
525 // so for example x.a turns into x$a2e, x..a turns into x$$a2e2e.
526 //
527 // As an optimization, we replace . with $ without appending anything,
528 // unless there is another illegal character. The reason is that . is
529 // a common illegal character, and we want to avoid resizing strings
530 // for perf reasons, and we If we do see we need to append something, then
531 // for . we just append Z (one character, instead of the hex code).
532 //
533
534 size_t OriginalSize = str.size();
535 int Queued = 0;
536 for (size_t i = 1; i < OriginalSize; ++i) {
537 unsigned char c = str[i];
538 if (!isalnum(c) && c != '_') {
539 str[i] = '$';
540 if (c == '.') {
541 Queued++;
542 } else {
543 size_t s = str.size();
544 str.resize(s+2+Queued);
545 for (int i = 0; i < Queued; i++) {
546 str[s++] = 'Z';
547 }
548 Queued = 0;
549 str[s] = halfCharToHex(c >> 4);
550 str[s+1] = halfCharToHex(c & 0xf);
551 }
552 }
553 }
554 }
555
556 static inline std::string ensureFloat(const std::string &S, Type *T) {
557 if (PreciseF32 && T->isFloatTy()) {
558 return "Math_fround(" + S + ")";
559 }
560 return S;
561 }
562
563 static void emitDebugInfo(raw_ostream& Code, const Instruction *I) {
564 auto &Loc = I->getDebugLoc();
565 if (Loc) {
566 unsigned Line = Loc.getLine();
567 StringRef File = cast<MDLocation>(Loc.getScope())->getFilename();
568 Code << " //@line " << utostr(Line) << " \"" << (File.size() > 0 ? File.str( ) : "?") << "\"";
569 }
570 }
571
572 void JSWriter::error(const std::string& msg) {
573 report_fatal_error(msg);
574 }
575
576 std::string JSWriter::getPhiCode(const BasicBlock *From, const BasicBlock *To) {
577 // FIXME this is all quite inefficient, and also done once per incoming to eac h phi
578
579 // Find the phis, and generate assignments and dependencies
580 std::set<std::string> PhiVars;
581 for (BasicBlock::const_iterator I = To->begin(), E = To->end();
582 I != E; ++I) {
583 const PHINode* P = dyn_cast<PHINode>(I);
584 if (!P) break;
585 PhiVars.insert(getJSName(P));
586 }
587 typedef std::map<std::string, std::string> StringMap;
588 StringMap assigns; // variable -> assign statement
589 std::map<std::string, const Value*> values; // variable -> Value
590 StringMap deps; // variable -> dependency
591 StringMap undeps; // reverse: dependency -> variable
592 for (BasicBlock::const_iterator I = To->begin(), E = To->end();
593 I != E; ++I) {
594 const PHINode* P = dyn_cast<PHINode>(I);
595 if (!P) break;
596 int index = P->getBasicBlockIndex(From);
597 if (index < 0) continue;
598 // we found it
599 const std::string &name = getJSName(P);
600 assigns[name] = getAssign(P);
601 // Get the operand, and strip pointer casts, since normal expression
602 // translation also strips pointer casts, and we want to see the same
603 // thing so that we can detect any resulting dependencies.
604 const Value *V = P->getIncomingValue(index)->stripPointerCasts();
605 values[name] = V;
606 std::string vname = getValueAsStr(V);
607 if (const Instruction *VI = dyn_cast<const Instruction>(V)) {
608 if (VI->getParent() == To && PhiVars.find(vname) != PhiVars.end()) {
609 deps[name] = vname;
610 undeps[vname] = name;
611 }
612 }
613 }
614 // Emit assignments+values, taking into account dependencies, and breaking cyc les
615 std::string pre = "", post = "";
616 while (assigns.size() > 0) {
617 bool emitted = false;
618 for (StringMap::iterator I = assigns.begin(); I != assigns.end();) {
619 StringMap::iterator last = I;
620 std::string curr = last->first;
621 const Value *V = values[curr];
622 std::string CV = getValueAsStr(V);
623 I++; // advance now, as we may erase
624 // if we have no dependencies, or we found none to emit and are at the end (so there is a cycle), emit
625 StringMap::const_iterator dep = deps.find(curr);
626 if (dep == deps.end() || (!emitted && I == assigns.end())) {
627 if (dep != deps.end()) {
628 // break a cycle
629 std::string depString = dep->second;
630 std::string temp = curr + "$phi";
631 pre += getAdHocAssign(temp, V->getType()) + CV + ';';
632 CV = temp;
633 deps.erase(curr);
634 undeps.erase(depString);
635 }
636 post += assigns[curr] + CV + ';';
637 assigns.erase(last);
638 emitted = true;
639 }
640 }
641 }
642 return pre + post;
643 }
644
645 const std::string &JSWriter::getJSName(const Value* val) {
646 ValueMap::const_iterator I = ValueNames.find(val);
647 if (I != ValueNames.end() && I->first == val)
648 return I->second;
649
650 // If this is an alloca we've replaced with another, use the other name.
651 if (const AllocaInst *AI = dyn_cast<AllocaInst>(val)) {
652 if (AI->isStaticAlloca()) {
653 const AllocaInst *Rep = Allocas.getRepresentative(AI);
654 if (Rep != AI) {
655 return getJSName(Rep);
656 }
657 }
658 }
659
660 std::string name;
661 if (val->hasName()) {
662 name = val->getName().str();
663 } else {
664 name = utostr(UniqueNum++);
665 }
666
667 if (isa<Constant>(val)) {
668 sanitizeGlobal(name);
669 } else {
670 sanitizeLocal(name);
671 }
672
673 return ValueNames[val] = name;
674 }
675
676 std::string JSWriter::getAdHocAssign(const StringRef &s, Type *t) {
677 UsedVars[s] = t;
678 return (s + " = ").str();
679 }
680
681 std::string JSWriter::getAssign(const Instruction *I) {
682 return getAdHocAssign(getJSName(I), I->getType());
683 }
684
685 std::string JSWriter::getAssignIfNeeded(const Value *V) {
686 if (const Instruction *I = dyn_cast<Instruction>(V)) {
687 if (!I->use_empty()) return getAssign(I);
688 }
689 return std::string();
690 }
691
692 std::string JSWriter::getCast(const StringRef &s, Type *t, AsmCast sign) {
693 switch (t->getTypeID()) {
694 default: {
695 errs() << *t << "\n";
696 assert(false && "Unsupported type");
697 }
698 case Type::VectorTyID:
699 return (cast<VectorType>(t)->getElementType()->isIntegerTy() ?
700 "SIMD_int32x4_check(" + s + ")" :
701 "SIMD_float32x4_check(" + s + ")").str();
702 case Type::FloatTyID: {
703 if (PreciseF32 && !(sign & ASM_FFI_OUT)) {
704 if (sign & ASM_FFI_IN) {
705 return ("Math_fround(+(" + s + "))").str();
706 } else {
707 return ("Math_fround(" + s + ")").str();
708 }
709 }
710 // otherwise fall through to double
711 }
712 case Type::DoubleTyID: return ("+" + s).str();
713 case Type::IntegerTyID: {
714 // fall through to the end for nonspecific
715 switch (t->getIntegerBitWidth()) {
716 case 1: if (!(sign & ASM_NONSPECIFIC)) return sign == ASM_UNSIGNED ? (s + "&1").str() : (s + "<<31>>31").str();
717 case 8: if (!(sign & ASM_NONSPECIFIC)) return sign == ASM_UNSIGNED ? (s + "&255").str() : (s + "<<24>>24").str();
718 case 16: if (!(sign & ASM_NONSPECIFIC)) return sign == ASM_UNSIGNED ? (s + "&65535").str() : (s + "<<16>>16").str();
719 case 32: return (sign == ASM_SIGNED || (sign & ASM_NONSPECIFIC) ? s + "| 0" : s + ">>>0").str();
720 default: llvm_unreachable("Unsupported integer cast bitwidth");
721 }
722 }
723 case Type::PointerTyID:
724 return (sign == ASM_SIGNED || (sign & ASM_NONSPECIFIC) ? s + "|0" : s + "> >>0").str();
725 }
726 }
727
728 std::string JSWriter::getParenCast(const StringRef &s, Type *t, AsmCast sign) {
729 return getCast(("(" + s + ")").str(), t, sign);
730 }
731
732 std::string JSWriter::getDoubleToInt(const StringRef &s) {
733 return ("~~(" + s + ")").str();
734 }
735
736 std::string JSWriter::getIMul(const Value *V1, const Value *V2) {
737 const ConstantInt *CI = NULL;
738 const Value *Other = NULL;
739 if ((CI = dyn_cast<ConstantInt>(V1))) {
740 Other = V2;
741 } else if ((CI = dyn_cast<ConstantInt>(V2))) {
742 Other = V1;
743 }
744 // we ignore optimizing the case of multiplying two constants - optimizer woul d have removed those
745 if (CI) {
746 std::string OtherStr = getValueAsStr(Other);
747 unsigned C = CI->getZExtValue();
748 if (C == 0) return "0";
749 if (C == 1) return OtherStr;
750 unsigned Orig = C, Shifts = 0;
751 while (C) {
752 if ((C & 1) && (C != 1)) break; // not power of 2
753 C >>= 1;
754 Shifts++;
755 if (C == 0) return OtherStr + "<<" + utostr(Shifts-1); // power of 2, emit shift
756 }
757 if (Orig < (1<<20)) return "(" + OtherStr + "*" + utostr(Orig) + ")|0"; // s mall enough, avoid imul
758 }
759 return "Math_imul(" + getValueAsStr(V1) + ", " + getValueAsStr(V2) + ")|0"; // unknown or too large, emit imul
760 }
761
762 std::string JSWriter::getLoad(const Instruction *I, const Value *P, Type *T, uns igned Alignment, char sep) {
763 std::string Assign = getAssign(I);
764 unsigned Bytes = DL->getTypeAllocSize(T);
765 std::string text;
766 if (Bytes <= Alignment || Alignment == 0) {
767 text = Assign + getPtrLoad(P);
768 if (isAbsolute(P)) {
769 // loads from an absolute constants are either intentional segfaults (int x = *((int*)0)), or code problems
770 text += "; abort() /* segfault, load from absolute addr */";
771 }
772 } else {
773 // unaligned in some manner
774 if (WarnOnUnaligned) {
775 errs() << "emcc: warning: unaligned load in " << I->getParent()->getParen t()->getName() << ":" << *I << " | ";
776 emitDebugInfo(errs(), I);
777 errs() << "\n";
778 }
779 std::string PS = getValueAsStr(P);
780 switch (Bytes) {
781 case 8: {
782 switch (Alignment) {
783 case 4: {
784 text = "HEAP32[tempDoublePtr>>2]=HEAP32[" + PS + ">>2]" + sep +
785 "HEAP32[tempDoublePtr+4>>2]=HEAP32[" + PS + "+4>>2]";
786 break;
787 }
788 case 2: {
789 text = "HEAP16[tempDoublePtr>>1]=HEAP16[" + PS + ">>1]" + sep +
790 "HEAP16[tempDoublePtr+2>>1]=HEAP16[" + PS + "+2>>1]" + sep +
791 "HEAP16[tempDoublePtr+4>>1]=HEAP16[" + PS + "+4>>1]" + sep +
792 "HEAP16[tempDoublePtr+6>>1]=HEAP16[" + PS + "+6>>1]";
793 break;
794 }
795 case 1: {
796 text = "HEAP8[tempDoublePtr>>0]=HEAP8[" + PS + ">>0]" + sep +
797 "HEAP8[tempDoublePtr+1>>0]=HEAP8[" + PS + "+1>>0]" + sep +
798 "HEAP8[tempDoublePtr+2>>0]=HEAP8[" + PS + "+2>>0]" + sep +
799 "HEAP8[tempDoublePtr+3>>0]=HEAP8[" + PS + "+3>>0]" + sep +
800 "HEAP8[tempDoublePtr+4>>0]=HEAP8[" + PS + "+4>>0]" + sep +
801 "HEAP8[tempDoublePtr+5>>0]=HEAP8[" + PS + "+5>>0]" + sep +
802 "HEAP8[tempDoublePtr+6>>0]=HEAP8[" + PS + "+6>>0]" + sep +
803 "HEAP8[tempDoublePtr+7>>0]=HEAP8[" + PS + "+7>>0]";
804 break;
805 }
806 default: assert(0 && "bad 8 store");
807 }
808 text += sep + Assign + "+HEAPF64[tempDoublePtr>>3]";
809 break;
810 }
811 case 4: {
812 if (T->isIntegerTy() || T->isPointerTy()) {
813 switch (Alignment) {
814 case 2: {
815 text = Assign + "HEAPU16[" + PS + ">>1]|" +
816 "(HEAPU16[" + PS + "+2>>1]<<16)";
817 break;
818 }
819 case 1: {
820 text = Assign + "HEAPU8[" + PS + ">>0]|" +
821 "(HEAPU8[" + PS + "+1>>0]<<8)|" +
822 "(HEAPU8[" + PS + "+2>>0]<<16)|" +
823 "(HEAPU8[" + PS + "+3>>0]<<24)";
824 break;
825 }
826 default: assert(0 && "bad 4i store");
827 }
828 } else { // float
829 assert(T->isFloatingPointTy());
830 switch (Alignment) {
831 case 2: {
832 text = "HEAP16[tempDoublePtr>>1]=HEAP16[" + PS + ">>1]" + sep +
833 "HEAP16[tempDoublePtr+2>>1]=HEAP16[" + PS + "+2>>1]";
834 break;
835 }
836 case 1: {
837 text = "HEAP8[tempDoublePtr>>0]=HEAP8[" + PS + ">>0]" + sep +
838 "HEAP8[tempDoublePtr+1>>0]=HEAP8[" + PS + "+1>>0]" + sep +
839 "HEAP8[tempDoublePtr+2>>0]=HEAP8[" + PS + "+2>>0]" + sep +
840 "HEAP8[tempDoublePtr+3>>0]=HEAP8[" + PS + "+3>>0]";
841 break;
842 }
843 default: assert(0 && "bad 4f store");
844 }
845 text += sep + Assign + getCast("HEAPF32[tempDoublePtr>>2]", Type::getF loatTy(TheModule->getContext()));
846 }
847 break;
848 }
849 case 2: {
850 text = Assign + "HEAPU8[" + PS + ">>0]|" +
851 "(HEAPU8[" + PS + "+1>>0]<<8)";
852 break;
853 }
854 default: assert(0 && "bad store");
855 }
856 }
857 return text;
858 }
859
860 std::string JSWriter::getStore(const Instruction *I, const Value *P, Type *T, co nst std::string& VS, unsigned Alignment, char sep) {
861 assert(sep == ';'); // FIXME when we need that
862 unsigned Bytes = DL->getTypeAllocSize(T);
863 std::string text;
864 if (Bytes <= Alignment || Alignment == 0) {
865 text = getPtrUse(P) + " = " + VS;
866 if (Alignment == 536870912) text += "; abort() /* segfault */";
867 } else {
868 // unaligned in some manner
869 if (WarnOnUnaligned) {
870 errs() << "emcc: warning: unaligned store in " << I->getParent()->getParen t()->getName() << ":" << *I << " | ";
871 emitDebugInfo(errs(), I);
872 errs() << "\n";
873 }
874 std::string PS = getValueAsStr(P);
875 switch (Bytes) {
876 case 8: {
877 text = "HEAPF64[tempDoublePtr>>3]=" + VS + ';';
878 switch (Alignment) {
879 case 4: {
880 text += "HEAP32[" + PS + ">>2]=HEAP32[tempDoublePtr>>2];" +
881 "HEAP32[" + PS + "+4>>2]=HEAP32[tempDoublePtr+4>>2]";
882 break;
883 }
884 case 2: {
885 text += "HEAP16[" + PS + ">>1]=HEAP16[tempDoublePtr>>1];" +
886 "HEAP16[" + PS + "+2>>1]=HEAP16[tempDoublePtr+2>>1];" +
887 "HEAP16[" + PS + "+4>>1]=HEAP16[tempDoublePtr+4>>1];" +
888 "HEAP16[" + PS + "+6>>1]=HEAP16[tempDoublePtr+6>>1]";
889 break;
890 }
891 case 1: {
892 text += "HEAP8[" + PS + ">>0]=HEAP8[tempDoublePtr>>0];" +
893 "HEAP8[" + PS + "+1>>0]=HEAP8[tempDoublePtr+1>>0];" +
894 "HEAP8[" + PS + "+2>>0]=HEAP8[tempDoublePtr+2>>0];" +
895 "HEAP8[" + PS + "+3>>0]=HEAP8[tempDoublePtr+3>>0];" +
896 "HEAP8[" + PS + "+4>>0]=HEAP8[tempDoublePtr+4>>0];" +
897 "HEAP8[" + PS + "+5>>0]=HEAP8[tempDoublePtr+5>>0];" +
898 "HEAP8[" + PS + "+6>>0]=HEAP8[tempDoublePtr+6>>0];" +
899 "HEAP8[" + PS + "+7>>0]=HEAP8[tempDoublePtr+7>>0]";
900 break;
901 }
902 default: assert(0 && "bad 8 store");
903 }
904 break;
905 }
906 case 4: {
907 if (T->isIntegerTy() || T->isPointerTy()) {
908 switch (Alignment) {
909 case 2: {
910 text = "HEAP16[" + PS + ">>1]=" + VS + "&65535;" +
911 "HEAP16[" + PS + "+2>>1]=" + VS + ">>>16";
912 break;
913 }
914 case 1: {
915 text = "HEAP8[" + PS + ">>0]=" + VS + "&255;" +
916 "HEAP8[" + PS + "+1>>0]=(" + VS + ">>8)&255;" +
917 "HEAP8[" + PS + "+2>>0]=(" + VS + ">>16)&255;" +
918 "HEAP8[" + PS + "+3>>0]=" + VS + ">>24";
919 break;
920 }
921 default: assert(0 && "bad 4i store");
922 }
923 } else { // float
924 assert(T->isFloatingPointTy());
925 text = "HEAPF32[tempDoublePtr>>2]=" + VS + ';';
926 switch (Alignment) {
927 case 2: {
928 text += "HEAP16[" + PS + ">>1]=HEAP16[tempDoublePtr>>1];" +
929 "HEAP16[" + PS + "+2>>1]=HEAP16[tempDoublePtr+2>>1]";
930 break;
931 }
932 case 1: {
933 text += "HEAP8[" + PS + ">>0]=HEAP8[tempDoublePtr>>0];" +
934 "HEAP8[" + PS + "+1>>0]=HEAP8[tempDoublePtr+1>>0];" +
935 "HEAP8[" + PS + "+2>>0]=HEAP8[tempDoublePtr+2>>0];" +
936 "HEAP8[" + PS + "+3>>0]=HEAP8[tempDoublePtr+3>>0]";
937 break;
938 }
939 default: assert(0 && "bad 4f store");
940 }
941 }
942 break;
943 }
944 case 2: {
945 text = "HEAP8[" + PS + ">>0]=" + VS + "&255;" +
946 "HEAP8[" + PS + "+1>>0]=" + VS + ">>8";
947 break;
948 }
949 default: assert(0 && "bad store");
950 }
951 }
952 return text;
953 }
954
955 std::string JSWriter::getStackBump(unsigned Size) {
956 return getStackBump(utostr(Size));
957 }
958
959 std::string JSWriter::getStackBump(const std::string &Size) {
960 std::string ret = "STACKTOP = STACKTOP + " + Size + "|0;";
961 if (EmscriptenAssertions) {
962 ret += " if ((STACKTOP|0) >= (STACK_MAX|0)) abort();";
963 }
964 return ret;
965 }
966
967 std::string JSWriter::getOpName(const Value* V) { // TODO: remove this
968 return getJSName(V);
969 }
970
971 std::string JSWriter::getPtrLoad(const Value* Ptr) {
972 Type *t = cast<PointerType>(Ptr->getType())->getElementType();
973 return getCast(getPtrUse(Ptr), t, ASM_NONSPECIFIC);
974 }
975
976 std::string JSWriter::getHeapAccess(const std::string& Name, unsigned Bytes, boo l Integer) {
977 switch (Bytes) {
978 default: llvm_unreachable("Unsupported type");
979 case 8: return "HEAPF64[" + Name + ">>3]";
980 case 4: {
981 if (Integer) {
982 return "HEAP32[" + Name + ">>2]";
983 } else {
984 return "HEAPF32[" + Name + ">>2]";
985 }
986 }
987 case 2: return "HEAP16[" + Name + ">>1]";
988 case 1: return "HEAP8[" + Name + ">>0]";
989 }
990 }
991
992 std::string JSWriter::getPtrUse(const Value* Ptr) {
993 Type *t = cast<PointerType>(Ptr->getType())->getElementType();
994 unsigned Bytes = DL->getTypeAllocSize(t);
995 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr)) {
996 std::string text = "";
997 unsigned Addr = getGlobalAddress(GV->getName().str());
998 switch (Bytes) {
999 default: llvm_unreachable("Unsupported type");
1000 case 8: return "HEAPF64[" + utostr(Addr >> 3) + "]";
1001 case 4: {
1002 if (t->isIntegerTy() || t->isPointerTy()) {
1003 return "HEAP32[" + utostr(Addr >> 2) + "]";
1004 } else {
1005 assert(t->isFloatingPointTy());
1006 return "HEAPF32[" + utostr(Addr >> 2) + "]";
1007 }
1008 }
1009 case 2: return "HEAP16[" + utostr(Addr >> 1) + "]";
1010 case 1: return "HEAP8[" + utostr(Addr) + "]";
1011 }
1012 } else {
1013 return getHeapAccess(getValueAsStr(Ptr), Bytes, t->isIntegerTy() || t->isPoi nterTy());
1014 }
1015 }
1016
1017 std::string JSWriter::getConstant(const Constant* CV, AsmCast sign) {
1018 if (isa<ConstantPointerNull>(CV)) return "0";
1019
1020 if (const Function *F = dyn_cast<Function>(CV)) {
1021 return utostr(getFunctionIndex(F));
1022 }
1023
1024 if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
1025 if (GV->isDeclaration()) {
1026 std::string Name = getOpName(GV);
1027 Externals.insert(Name);
1028 return Name;
1029 }
1030 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(CV)) {
1031 // Since we don't currently support linking of our output, we don't need
1032 // to worry about weak or other kinds of aliases.
1033 return getConstant(GA->getAliasee(), sign);
1034 }
1035 return utostr(getGlobalAddress(GV->getName().str()));
1036 }
1037
1038 if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
1039 std::string S = ftostr(CFP, sign);
1040 if (PreciseF32 && CV->getType()->isFloatTy() && !(sign & ASM_FFI_OUT)) {
1041 S = "Math_fround(" + S + ")";
1042 }
1043 return S;
1044 } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
1045 if (sign != ASM_UNSIGNED && CI->getValue().getBitWidth() == 1) {
1046 sign = ASM_UNSIGNED; // bools must always be unsigned: either 0 or 1
1047 }
1048 return CI->getValue().toString(10, sign != ASM_UNSIGNED);
1049 } else if (isa<UndefValue>(CV)) {
1050 std::string S;
1051 if (VectorType *VT = dyn_cast<VectorType>(CV->getType())) {
1052 checkVectorType(VT);
1053 if (VT->getElementType()->isIntegerTy()) {
1054 S = "SIMD_int32x4_splat(0)";
1055 } else {
1056 S = "SIMD_float32x4_splat(Math_fround(0))";
1057 }
1058 } else {
1059 S = CV->getType()->isFloatingPointTy() ? "+0" : "0"; // XXX refactor this
1060 if (PreciseF32 && CV->getType()->isFloatTy() && !(sign & ASM_FFI_OUT)) {
1061 S = "Math_fround(" + S + ")";
1062 }
1063 }
1064 return S;
1065 } else if (isa<ConstantAggregateZero>(CV)) {
1066 if (VectorType *VT = dyn_cast<VectorType>(CV->getType())) {
1067 checkVectorType(VT);
1068 if (VT->getElementType()->isIntegerTy()) {
1069 return "SIMD_int32x4_splat(0)";
1070 } else {
1071 return "SIMD_float32x4_splat(Math_fround(0))";
1072 }
1073 } else {
1074 // something like [0 x i8*] zeroinitializer, which clang can emit for land ingpads
1075 return "0";
1076 }
1077 } else if (const ConstantDataVector *DV = dyn_cast<ConstantDataVector>(CV)) {
1078 checkVectorType(DV->getType());
1079 unsigned NumElts = cast<VectorType>(DV->getType())->getNumElements();
1080 Type *EltTy = cast<VectorType>(DV->getType())->getElementType();
1081 Constant *Undef = UndefValue::get(EltTy);
1082 return getConstantVector(EltTy,
1083 getConstant(NumElts > 0 ? DV->getElementAsConstant( 0) : Undef),
1084 getConstant(NumElts > 1 ? DV->getElementAsConstant( 1) : Undef),
1085 getConstant(NumElts > 2 ? DV->getElementAsConstant( 2) : Undef),
1086 getConstant(NumElts > 3 ? DV->getElementAsConstant( 3) : Undef));
1087 } else if (const ConstantVector *V = dyn_cast<ConstantVector>(CV)) {
1088 checkVectorType(V->getType());
1089 unsigned NumElts = cast<VectorType>(CV->getType())->getNumElements();
1090 Type *EltTy = cast<VectorType>(CV->getType())->getElementType();
1091 Constant *Undef = UndefValue::get(EltTy);
1092 return getConstantVector(cast<VectorType>(V->getType())->getElementType(),
1093 getConstant(NumElts > 0 ? V->getOperand(0) : Undef) ,
1094 getConstant(NumElts > 1 ? V->getOperand(1) : Undef) ,
1095 getConstant(NumElts > 2 ? V->getOperand(2) : Undef) ,
1096 getConstant(NumElts > 3 ? V->getOperand(3) : Undef) );
1097 } else if (const ConstantArray *CA = dyn_cast<const ConstantArray>(CV)) {
1098 // handle things like [i8* bitcast (<{ i32, i32, i32 }>* @_ZTISt9bad_alloc t o i8*)] which clang can emit for landingpads
1099 assert(CA->getNumOperands() == 1);
1100 CV = CA->getOperand(0);
1101 const ConstantExpr *CE = cast<ConstantExpr>(CV);
1102 CV = CE->getOperand(0); // ignore bitcast
1103 return getConstant(CV);
1104 } else if (const BlockAddress *BA = dyn_cast<const BlockAddress>(CV)) {
1105 return utostr(getBlockAddress(BA));
1106 } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
1107 std::string Code;
1108 raw_string_ostream CodeStream(Code);
1109 CodeStream << '(';
1110 generateExpression(CE, CodeStream);
1111 CodeStream << ')';
1112 return CodeStream.str();
1113 } else {
1114 CV->dump();
1115 llvm_unreachable("Unsupported constant kind");
1116 }
1117 }
1118
1119 std::string JSWriter::getConstantVector(Type *ElementType, std::string x, std::s tring y, std::string z, std::string w) {
1120 // Check for a splat.
1121 if (x == y && x == z && x == w) {
1122 if (ElementType->isIntegerTy()) {
1123 return "SIMD_int32x4_splat(" + x + ')';
1124 } else {
1125 return "SIMD_float32x4_splat(Math_fround(" + x + "))";
1126 }
1127 }
1128
1129 if (ElementType->isIntegerTy()) {
1130 return "SIMD_int32x4(" + x + ',' + y + ',' + z + ',' + w + ')';
1131 } else {
1132 return "SIMD_float32x4(Math_fround(" + x + "),Math_fround(" + y + "),Math_fr ound(" + z + "),Math_fround(" + w + "))";
1133 }
1134 }
1135
1136 std::string JSWriter::getValueAsStr(const Value* V, AsmCast sign) {
1137 // Skip past no-op bitcasts and zero-index geps.
1138 V = V->stripPointerCasts();
1139
1140 if (const Constant *CV = dyn_cast<Constant>(V)) {
1141 return getConstant(CV, sign);
1142 } else {
1143 return getJSName(V);
1144 }
1145 }
1146
1147 std::string JSWriter::getValueAsCastStr(const Value* V, AsmCast sign) {
1148 // Skip past no-op bitcasts and zero-index geps.
1149 V = V->stripPointerCasts();
1150
1151 if (isa<ConstantInt>(V) || isa<ConstantFP>(V)) {
1152 return getConstant(cast<Constant>(V), sign);
1153 } else {
1154 return getCast(getValueAsStr(V), V->getType(), sign);
1155 }
1156 }
1157
1158 std::string JSWriter::getValueAsParenStr(const Value* V) {
1159 // Skip past no-op bitcasts and zero-index geps.
1160 V = V->stripPointerCasts();
1161
1162 if (const Constant *CV = dyn_cast<Constant>(V)) {
1163 return getConstant(CV);
1164 } else {
1165 return "(" + getValueAsStr(V) + ")";
1166 }
1167 }
1168
1169 std::string JSWriter::getValueAsCastParenStr(const Value* V, AsmCast sign) {
1170 // Skip past no-op bitcasts and zero-index geps.
1171 V = V->stripPointerCasts();
1172
1173 if (isa<ConstantInt>(V) || isa<ConstantFP>(V) || isa<UndefValue>(V)) {
1174 return getConstant(cast<Constant>(V), sign);
1175 } else {
1176 return "(" + getCast(getValueAsStr(V), V->getType(), sign) + ")";
1177 }
1178 }
1179
1180 void JSWriter::generateInsertElementExpression(const InsertElementInst *III, raw _string_ostream& Code) {
1181 // LLVM has no vector type constructor operator; it uses chains of
1182 // insertelement instructions instead. It also has no splat operator; it
1183 // uses an insertelement followed by a shuffle instead. If this insertelement
1184 // is part of either such sequence, skip it for now; we'll process it when we
1185 // reach the end.
1186 if (III->hasOneUse()) {
1187 const User *U = *III->user_begin();
1188 if (isa<InsertElementInst>(U))
1189 return;
1190 if (isa<ShuffleVectorInst>(U) &&
1191 isa<ConstantAggregateZero>(cast<ShuffleVectorInst>(U)->getMask()) &&
1192 !isa<InsertElementInst>(III->getOperand(0)) &&
1193 isa<ConstantInt>(III->getOperand(2)) &&
1194 cast<ConstantInt>(III->getOperand(2))->isZero())
1195 {
1196 return;
1197 }
1198 }
1199
1200 // This insertelement is at the base of a chain of single-user insertelement
1201 // instructions. Collect all the inserted elements so that we can categorize
1202 // the chain as either a splat, a constructor, or an actual series of inserts.
1203 VectorType *VT = III->getType();
1204 unsigned NumElems = VT->getNumElements();
1205 unsigned NumInserted = 0;
1206 SmallVector<const Value *, 8> Operands(NumElems, NULL);
1207 const Value *Splat = III->getOperand(1);
1208 const Value *Base = III;
1209 do {
1210 const InsertElementInst *BaseIII = cast<InsertElementInst>(Base);
1211 const ConstantInt *IndexInt = cast<ConstantInt>(BaseIII->getOperand(2));
1212 unsigned Index = IndexInt->getZExtValue();
1213 if (Operands[Index] == NULL)
1214 ++NumInserted;
1215 Value *Op = BaseIII->getOperand(1);
1216 if (Operands[Index] == NULL) {
1217 Operands[Index] = Op;
1218 if (Op != Splat)
1219 Splat = NULL;
1220 }
1221 Base = BaseIII->getOperand(0);
1222 } while (Base->hasOneUse() && isa<InsertElementInst>(Base));
1223
1224 // Emit code for the chain.
1225 Code << getAssignIfNeeded(III);
1226 if (NumInserted == NumElems) {
1227 if (Splat) {
1228 // Emit splat code.
1229 if (VT->getElementType()->isIntegerTy()) {
1230 Code << "SIMD_int32x4_splat(" << getValueAsStr(Splat) << ")";
1231 } else {
1232 std::string operand = getValueAsStr(Splat);
1233 if (!PreciseF32) {
1234 // SIMD_float32x4_splat requires an actual float32 even if we're
1235 // otherwise not being precise about it.
1236 operand = "Math_fround(" + operand + ")";
1237 }
1238 Code << "SIMD_float32x4_splat(" << operand << ")";
1239 }
1240 } else {
1241 // Emit constructor code.
1242 if (VT->getElementType()->isIntegerTy()) {
1243 Code << "SIMD_int32x4(";
1244 } else {
1245 Code << "SIMD_float32x4(";
1246 }
1247 for (unsigned Index = 0; Index < NumElems; ++Index) {
1248 if (Index != 0)
1249 Code << ", ";
1250 std::string operand = getValueAsStr(Operands[Index]);
1251 if (!PreciseF32 && VT->getElementType()->isFloatTy()) {
1252 // SIMD_float32x4_splat requires an actual float32 even if we're
1253 // otherwise not being precise about it.
1254 operand = "Math_fround(" + operand + ")";
1255 }
1256 Code << operand;
1257 }
1258 Code << ")";
1259 }
1260 } else {
1261 // Emit a series of inserts.
1262 std::string Result = getValueAsStr(Base);
1263 for (unsigned Index = 0; Index < NumElems; ++Index) {
1264 std::string with;
1265 if (!Operands[Index])
1266 continue;
1267 if (VT->getElementType()->isIntegerTy()) {
1268 with = "SIMD_int32x4_with";
1269 } else {
1270 with = "SIMD_float32x4_with";
1271 }
1272 std::string operand = getValueAsStr(Operands[Index]);
1273 if (!PreciseF32) {
1274 operand = "Math_fround(" + operand + ")";
1275 }
1276 Result = with + SIMDLane[Index] + "(" + Result + ',' + operand + ')';
1277 }
1278 Code << Result;
1279 }
1280 }
1281
1282 void JSWriter::generateExtractElementExpression(const ExtractElementInst *EEI, r aw_string_ostream& Code) {
1283 VectorType *VT = cast<VectorType>(EEI->getVectorOperand()->getType());
1284 checkVectorType(VT);
1285 const ConstantInt *IndexInt = dyn_cast<const ConstantInt>(EEI->getIndexOperand ());
1286 if (IndexInt) {
1287 unsigned Index = IndexInt->getZExtValue();
1288 assert(Index <= 3);
1289 Code << getAssignIfNeeded(EEI);
1290 std::string OperandCode;
1291 raw_string_ostream CodeStream(OperandCode);
1292 CodeStream << getValueAsStr(EEI->getVectorOperand()) << '.' << simdLane[Inde x];
1293 Code << getCast(CodeStream.str(), EEI->getType());
1294 return;
1295 }
1296
1297 error("SIMD extract element with non-constant index not implemented yet");
1298 }
1299
1300 void JSWriter::generateShuffleVectorExpression(const ShuffleVectorInst *SVI, raw _string_ostream& Code) {
1301 Code << getAssignIfNeeded(SVI);
1302
1303 // LLVM has no splat operator, so it makes do by using an insert and a
1304 // shuffle. If that's what this shuffle is doing, the code in
1305 // generateInsertElementExpression will have also detected it and skipped
1306 // emitting the insert, so we can just emit a splat here.
1307 if (isa<ConstantAggregateZero>(SVI->getMask()) &&
1308 isa<InsertElementInst>(SVI->getOperand(0)))
1309 {
1310 InsertElementInst *IEI = cast<InsertElementInst>(SVI->getOperand(0));
1311 if (ConstantInt *CI = dyn_cast<ConstantInt>(IEI->getOperand(2))) {
1312 if (CI->isZero()) {
1313 std::string operand = getValueAsStr(IEI->getOperand(1));
1314 if (!PreciseF32) {
1315 // SIMD_float32x4_splat requires an actual float32 even if we're
1316 // otherwise not being precise about it.
1317 operand = "Math_fround(" + operand + ")";
1318 }
1319 if (SVI->getType()->getElementType()->isIntegerTy()) {
1320 Code << "SIMD_int32x4_splat(";
1321 } else {
1322 Code << "SIMD_float32x4_splat(";
1323 }
1324 Code << operand << ")";
1325 return;
1326 }
1327 }
1328 }
1329
1330 // Check whether can generate SIMD.js swizzle or shuffle.
1331 std::string A = getValueAsStr(SVI->getOperand(0));
1332 std::string B = getValueAsStr(SVI->getOperand(1));
1333 int OpNumElements = cast<VectorType>(SVI->getOperand(0)->getType())->getNumEle ments();
1334 int ResultNumElements = SVI->getType()->getNumElements();
1335 int Mask0 = ResultNumElements > 0 ? SVI->getMaskValue(0) : -1;
1336 int Mask1 = ResultNumElements > 1 ? SVI->getMaskValue(1) : -1;
1337 int Mask2 = ResultNumElements > 2 ? SVI->getMaskValue(2) : -1;
1338 int Mask3 = ResultNumElements > 3 ? SVI->getMaskValue(3) : -1;
1339 bool swizzleA = false;
1340 bool swizzleB = false;
1341 if ((Mask0 < OpNumElements) && (Mask1 < OpNumElements) &&
1342 (Mask2 < OpNumElements) && (Mask3 < OpNumElements)) {
1343 swizzleA = true;
1344 }
1345 if ((Mask0 < 0 || (Mask0 >= OpNumElements && Mask0 < OpNumElements * 2)) &&
1346 (Mask1 < 0 || (Mask1 >= OpNumElements && Mask1 < OpNumElements * 2)) &&
1347 (Mask2 < 0 || (Mask2 >= OpNumElements && Mask2 < OpNumElements * 2)) &&
1348 (Mask3 < 0 || (Mask3 >= OpNumElements && Mask3 < OpNumElements * 2))) {
1349 swizzleB = true;
1350 }
1351 assert(!(swizzleA && swizzleB));
1352 if (swizzleA || swizzleB) {
1353 std::string T = (swizzleA ? A : B);
1354 if (SVI->getType()->getElementType()->isIntegerTy()) {
1355 Code << "SIMD_int32x4_swizzle(" << T;
1356 } else {
1357 Code << "SIMD_float32x4_swizzle(" << T;
1358 }
1359 int i = 0;
1360 for (; i < ResultNumElements; ++i) {
1361 Code << ", ";
1362 int Mask = SVI->getMaskValue(i);
1363 if (Mask < 0) {
1364 Code << 0;
1365 } else if (Mask < OpNumElements) {
1366 Code << Mask;
1367 } else {
1368 assert(Mask < OpNumElements * 2);
1369 Code << (Mask-OpNumElements);
1370 }
1371 }
1372 for (; i < 4; ++i) {
1373 Code << ", 0";
1374 }
1375 Code << ")";
1376 return;
1377 }
1378
1379 // Emit a fully-general shuffle.
1380 if (SVI->getType()->getElementType()->isIntegerTy()) {
1381 Code << "SIMD_int32x4_shuffle(";
1382 } else {
1383 Code << "SIMD_float32x4_shuffle(";
1384 }
1385
1386 Code << A << ", " << B << ", ";
1387
1388 SmallVector<int, 16> Indices;
1389 SVI->getShuffleMask(Indices);
1390 for (unsigned int i = 0; i < Indices.size(); ++i) {
1391 if (i != 0)
1392 Code << ", ";
1393 int Mask = Indices[i];
1394 if (Mask >= OpNumElements)
1395 Mask = Mask - OpNumElements + 4;
1396 if (Mask < 0)
1397 Code << 0;
1398 else
1399 Code << Mask;
1400 }
1401
1402 Code << ")";
1403 }
1404
1405 void JSWriter::generateICmpExpression(const ICmpInst *I, raw_string_ostream& Cod e) {
1406 bool Invert = false;
1407 const char *Name;
1408 switch (cast<ICmpInst>(I)->getPredicate()) {
1409 case ICmpInst::ICMP_EQ: Name = "equal"; break;
1410 case ICmpInst::ICMP_NE: Name = "equal"; Invert = true; break;
1411 case ICmpInst::ICMP_SLE: Name = "greaterThan"; Invert = true; break;
1412 case ICmpInst::ICMP_SGE: Name = "lessThan"; Invert = true; break;
1413 case ICmpInst::ICMP_ULE: Name = "unsignedLessThanOrEqual"; break;
1414 case ICmpInst::ICMP_UGE: Name = "unsignedGreaterThanOrEqual"; break;
1415 case ICmpInst::ICMP_ULT: Name = "unsignedLessThan"; break;
1416 case ICmpInst::ICMP_SLT: Name = "lessThan"; break;
1417 case ICmpInst::ICMP_UGT: Name = "unsignedGreaterThan"; break;
1418 case ICmpInst::ICMP_SGT: Name = "greaterThan"; break;
1419 default: I->dump(); error("invalid vector icmp"); break;
1420 }
1421
1422 if (Invert)
1423 Code << "SIMD_int32x4_not(";
1424
1425 Code << getAssignIfNeeded(I) << "SIMD_int32x4_" << Name << "("
1426 << getValueAsStr(I->getOperand(0)) << ", " << getValueAsStr(I->getOperand (1)) << ")";
1427
1428 if (Invert)
1429 Code << ")";
1430 }
1431
1432 void JSWriter::generateFCmpExpression(const FCmpInst *I, raw_string_ostream& Cod e) {
1433 const char *Name;
1434 bool Invert = false;
1435 switch (cast<FCmpInst>(I)->getPredicate()) {
1436 case ICmpInst::FCMP_FALSE:
1437 Code << "SIMD_int32x4_splat(0)";
1438 return;
1439 case ICmpInst::FCMP_TRUE:
1440 Code << "SIMD_int32x4_splat(-1)";
1441 return;
1442 case ICmpInst::FCMP_ONE:
1443 Code << "SIMD_float32x4_and(SIMD_float32x4_and("
1444 "SIMD_float32x4_equal(" << getValueAsStr(I->getOperand(0)) << ", "
1445 << getValueAsStr(I->getOperand(0)) << "), " <<
1446 "SIMD_float32x4_equal(" << getValueAsStr(I->getOperand(1)) << ", "
1447 << getValueAsStr(I->getOperand(1)) << ")), " <<
1448 "SIMD_float32x4_notEqual(" << getValueAsStr(I->getOperand(0)) << " , "
1449 << getValueAsStr(I->getOperand(1)) << " ))";
1450 return;
1451 case ICmpInst::FCMP_UEQ:
1452 Code << "SIMD_float32x4_or(SIMD_float32x4_or("
1453 "SIMD_float32x4_notEqual(" << getValueAsStr(I->getOperand(0)) << " , "
1454 << getValueAsStr(I->getOperand(0)) << " ), " <<
1455 "SIMD_float32x4_notEqual(" << getValueAsStr(I->getOperand(1)) << " , "
1456 << getValueAsStr(I->getOperand(1)) << " )), " <<
1457 "SIMD_float32x4_equal(" << getValueAsStr(I->getOperand(0)) << ", "
1458 << getValueAsStr(I->getOperand(1)) << "))" ;
1459 return;
1460 case FCmpInst::FCMP_ORD:
1461 Code << "SIMD_float32x4_and("
1462 "SIMD_float32x4_equal(" << getValueAsStr(I->getOperand(0)) << ", " << getValueAsStr(I->getOperand(0)) << "), " <<
1463 "SIMD_float32x4_equal(" << getValueAsStr(I->getOperand(1)) << ", " << getValueAsStr(I->getOperand(1)) << "))";
1464 return;
1465
1466 case FCmpInst::FCMP_UNO:
1467 Code << "SIMD_float32x4_or("
1468 "SIMD_float32x4_notEqual(" << getValueAsStr(I->getOperand(0)) << " , " << getValueAsStr(I->getOperand(0)) << "), " <<
1469 "SIMD_float32x4_notEqual(" << getValueAsStr(I->getOperand(1)) << " , " << getValueAsStr(I->getOperand(1)) << "))";
1470 return;
1471
1472 case ICmpInst::FCMP_OEQ: Name = "equal"; break;
1473 case ICmpInst::FCMP_OGT: Name = "greaterThan"; break;
1474 case ICmpInst::FCMP_OGE: Name = "greaterThanOrEqual"; break;
1475 case ICmpInst::FCMP_OLT: Name = "lessThan"; break;
1476 case ICmpInst::FCMP_OLE: Name = "lessThanOrEqual"; break;
1477 case ICmpInst::FCMP_UGT: Name = "lessThanOrEqual"; Invert = true; break;
1478 case ICmpInst::FCMP_UGE: Name = "lessThan"; Invert = true; break;
1479 case ICmpInst::FCMP_ULT: Name = "greaterThanOrEqual"; Invert = true; break;
1480 case ICmpInst::FCMP_ULE: Name = "greaterThan"; Invert = true; break;
1481 case ICmpInst::FCMP_UNE: Name = "notEqual"; break;
1482 default: I->dump(); error("invalid vector fcmp"); break;
1483 }
1484
1485 if (Invert)
1486 Code << "SIMD_int32x4_not(";
1487
1488 Code << getAssignIfNeeded(I) << "SIMD_float32x4_" << Name << "("
1489 << getValueAsStr(I->getOperand(0)) << ", " << getValueAsStr(I->getOperand (1)) << ")";
1490
1491 if (Invert)
1492 Code << ")";
1493 }
1494
1495 static const Value *getElement(const Value *V, unsigned i) {
1496 if (const InsertElementInst *II = dyn_cast<InsertElementInst>(V)) {
1497 if (ConstantInt *CI = dyn_cast<ConstantInt>(II->getOperand(2))) {
1498 if (CI->equalsInt(i))
1499 return II->getOperand(1);
1500 }
1501 return getElement(II->getOperand(0), i);
1502 }
1503 return NULL;
1504 }
1505
1506 static const Value *getSplatValue(const Value *V) {
1507 if (const Constant *C = dyn_cast<Constant>(V))
1508 return C->getSplatValue();
1509
1510 VectorType *VTy = cast<VectorType>(V->getType());
1511 const Value *Result = NULL;
1512 for (unsigned i = 0; i < VTy->getNumElements(); ++i) {
1513 const Value *E = getElement(V, i);
1514 if (!E)
1515 return NULL;
1516 if (!Result)
1517 Result = E;
1518 else if (Result != E)
1519 return NULL;
1520 }
1521 return Result;
1522
1523 }
1524
1525 void JSWriter::generateShiftExpression(const BinaryOperator *I, raw_string_ostre am& Code) {
1526 // If we're shifting every lane by the same amount (shifting by a splat valu e
1527 // then we can use a ByScalar shift.
1528 const Value *Count = I->getOperand(1);
1529 if (const Value *Splat = getSplatValue(Count)) {
1530 Code << getAssignIfNeeded(I) << "SIMD_int32x4_";
1531 if (I->getOpcode() == Instruction::AShr)
1532 Code << "shiftRightArithmeticByScalar";
1533 else if (I->getOpcode() == Instruction::LShr)
1534 Code << "shiftRightLogicalByScalar";
1535 else
1536 Code << "shiftLeftByScalar";
1537 Code << "(" << getValueAsStr(I->getOperand(0)) << ", " << getValueAsStr( Splat) << ")";
1538 return;
1539 }
1540
1541 // SIMD.js does not currently have vector-vector shifts.
1542 generateUnrolledExpression(I, Code);
1543 }
1544
1545 void JSWriter::generateUnrolledExpression(const User *I, raw_string_ostream& Cod e) {
1546 VectorType *VT = cast<VectorType>(I->getType());
1547
1548 Code << getAssignIfNeeded(I);
1549
1550 if (VT->getElementType()->isIntegerTy()) {
1551 Code << "SIMD_int32x4(";
1552 } else {
1553 Code << "SIMD_float32x4(";
1554 }
1555
1556 for (unsigned Index = 0; Index < VT->getNumElements(); ++Index) {
1557 if (Index != 0)
1558 Code << ", ";
1559 if (!PreciseF32 && VT->getElementType()->isFloatTy()) {
1560 Code << "Math_fround(";
1561 }
1562 std::string Lane = VT->getNumElements() <= 4 ?
1563 std::string(".") + simdLane[Index] :
1564 ".s" + utostr(Index);
1565 switch (Operator::getOpcode(I)) {
1566 case Instruction::SDiv:
1567 Code << "(" << getValueAsStr(I->getOperand(0)) << Lane << "|0) / ("
1568 << getValueAsStr(I->getOperand(1)) << Lane << "|0)|0";
1569 break;
1570 case Instruction::UDiv:
1571 Code << "(" << getValueAsStr(I->getOperand(0)) << Lane << ">>>0) / ("
1572 << getValueAsStr(I->getOperand(1)) << Lane << ">>>0)>>>0";
1573 break;
1574 case Instruction::SRem:
1575 Code << "(" << getValueAsStr(I->getOperand(0)) << Lane << "|0) / ("
1576 << getValueAsStr(I->getOperand(1)) << Lane << "|0)|0";
1577 break;
1578 case Instruction::URem:
1579 Code << "(" << getValueAsStr(I->getOperand(0)) << Lane << ">>>0) / ("
1580 << getValueAsStr(I->getOperand(1)) << Lane << ">>>0)>>>0";
1581 break;
1582 case Instruction::AShr:
1583 Code << "(" << getValueAsStr(I->getOperand(0)) << Lane << "|0) >> ("
1584 << getValueAsStr(I->getOperand(1)) << Lane << "|0)|0";
1585 break;
1586 case Instruction::LShr:
1587 Code << "(" << getValueAsStr(I->getOperand(0)) << Lane << "|0) >>> ("
1588 << getValueAsStr(I->getOperand(1)) << Lane << "|0)|0";
1589 break;
1590 case Instruction::Shl:
1591 Code << "(" << getValueAsStr(I->getOperand(0)) << Lane << "|0) << ("
1592 << getValueAsStr(I->getOperand(1)) << Lane << "|0)|0";
1593 break;
1594 default: I->dump(); error("invalid unrolled vector instr"); break;
1595 }
1596 if (!PreciseF32 && VT->getElementType()->isFloatTy()) {
1597 Code << ")";
1598 }
1599 }
1600
1601 Code << ")";
1602 }
1603
1604 bool JSWriter::generateSIMDExpression(const User *I, raw_string_ostream& Code) {
1605 VectorType *VT;
1606 if ((VT = dyn_cast<VectorType>(I->getType()))) {
1607 // vector-producing instructions
1608 checkVectorType(VT);
1609
1610 switch (Operator::getOpcode(I)) {
1611 default: I->dump(); error("invalid vector instr"); break;
1612 case Instruction::Call: // return value is just a SIMD value, no special h andling
1613 return false;
1614 case Instruction::PHI: // handled separately - we push them back into the relooper branchings
1615 break;
1616 case Instruction::ICmp:
1617 generateICmpExpression(cast<ICmpInst>(I), Code);
1618 break;
1619 case Instruction::FCmp:
1620 generateFCmpExpression(cast<FCmpInst>(I), Code);
1621 break;
1622 case Instruction::SExt:
1623 assert(cast<VectorType>(I->getOperand(0)->getType())->getElementType()-> isIntegerTy(1) &&
1624 "sign-extension from vector of other than i1 not yet supported");
1625 // Since we represent vectors of i1 as vectors of sign extended wider in tegers,
1626 // sign extending them is a no-op.
1627 Code << getAssignIfNeeded(I) << getValueAsStr(I->getOperand(0));
1628 break;
1629 case Instruction::Select:
1630 // Since we represent vectors of i1 as vectors of sign extended wider in tegers,
1631 // selecting on them is just an elementwise select.
1632 if (isa<VectorType>(I->getOperand(0)->getType())) {
1633 if (cast<VectorType>(I->getType())->getElementType()->isIntegerTy()) {
1634 Code << getAssignIfNeeded(I) << "SIMD_int32x4_select(" << getValueAs Str(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << "," << getVal ueAsStr(I->getOperand(2)) << ")"; break;
1635 } else {
1636 Code << getAssignIfNeeded(I) << "SIMD_float32x4_select(" << getValue AsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << "," << getV alueAsStr(I->getOperand(2)) << ")"; break;
1637 }
1638 return true;
1639 }
1640 // Otherwise we have a scalar condition, so it's a ?: operator.
1641 return false;
1642 case Instruction::FAdd: Code << getAssignIfNeeded(I) << "SIMD_float32x4_ad d(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
1643 case Instruction::FMul: Code << getAssignIfNeeded(I) << "SIMD_float32x4_mu l(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
1644 case Instruction::FDiv: Code << getAssignIfNeeded(I) << "SIMD_float32x4_di v(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
1645 case Instruction::Add: Code << getAssignIfNeeded(I) << "SIMD_int32x4_add(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
1646 case Instruction::Sub: Code << getAssignIfNeeded(I) << "SIMD_int32x4_sub(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
1647 case Instruction::Mul: Code << getAssignIfNeeded(I) << "SIMD_int32x4_mul(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
1648 case Instruction::And: Code << getAssignIfNeeded(I) << "SIMD_int32x4_and(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
1649 case Instruction::Or: Code << getAssignIfNeeded(I) << "SIMD_int32x4_or(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
1650 case Instruction::Xor:
1651 // LLVM represents a not(x) as -1 ^ x
1652 Code << getAssignIfNeeded(I);
1653 if (BinaryOperator::isNot(I)) {
1654 Code << "SIMD_int32x4_not(" << getValueAsStr(BinaryOperator::getNotArg ument(I)) << ")"; break;
1655 } else {
1656 Code << "SIMD_int32x4_xor(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
1657 }
1658 break;
1659 case Instruction::FSub:
1660 // LLVM represents an fneg(x) as -0.0 - x.
1661 Code << getAssignIfNeeded(I);
1662 if (BinaryOperator::isFNeg(I)) {
1663 Code << "SIMD_float32x4_neg(" << getValueAsStr(BinaryOperator::getFNeg Argument(I)) << ")";
1664 } else {
1665 Code << "SIMD_float32x4_sub(" << getValueAsStr(I->getOperand(0)) << ", " << getValueAsStr(I->getOperand(1)) << ")";
1666 }
1667 break;
1668 case Instruction::BitCast: {
1669 Code << getAssignIfNeeded(I);
1670 if (cast<VectorType>(I->getType())->getElementType()->isIntegerTy()) {
1671 Code << "SIMD_int32x4_fromFloat32x4Bits(" << getValueAsStr(I->getOpera nd(0)) << ')';
1672 } else {
1673 Code << "SIMD_float32x4_fromInt32x4Bits(" << getValueAsStr(I->getOpera nd(0)) << ')';
1674 }
1675 break;
1676 }
1677 case Instruction::Load: {
1678 const LoadInst *LI = cast<LoadInst>(I);
1679 const Value *P = LI->getPointerOperand();
1680 std::string PS = getValueAsStr(P);
1681
1682 // Determine if this is a partial load.
1683 static const std::string partialAccess[4] = { "X", "XY", "XYZ", "" };
1684 if (VT->getNumElements() < 1 || VT->getNumElements() > 4) {
1685 error("invalid number of lanes in SIMD operation!");
1686 break;
1687 }
1688 const std::string &Part = partialAccess[VT->getNumElements() - 1];
1689
1690 Code << getAssignIfNeeded(I);
1691 if (VT->getElementType()->isIntegerTy()) {
1692 Code << "SIMD_int32x4_load" << Part << "(HEAPU8, " << PS << ")";
1693 } else {
1694 Code << "SIMD_float32x4_load" << Part << "(HEAPU8, " << PS << ")";
1695 }
1696 break;
1697 }
1698 case Instruction::InsertElement:
1699 generateInsertElementExpression(cast<InsertElementInst>(I), Code);
1700 break;
1701 case Instruction::ShuffleVector:
1702 generateShuffleVectorExpression(cast<ShuffleVectorInst>(I), Code);
1703 break;
1704 case Instruction::SDiv:
1705 case Instruction::UDiv:
1706 case Instruction::SRem:
1707 case Instruction::URem:
1708 // The SIMD API does not currently support these operations directly.
1709 // Emulate them using scalar operations (which is essentially the same
1710 // as what would happen if the API did support them, since hardware
1711 // doesn't support them).
1712 generateUnrolledExpression(I, Code);
1713 break;
1714 case Instruction::AShr:
1715 case Instruction::LShr:
1716 case Instruction::Shl:
1717 generateShiftExpression(cast<BinaryOperator>(I), Code);
1718 break;
1719 }
1720 return true;
1721 } else {
1722 // vector-consuming instructions
1723 if (Operator::getOpcode(I) == Instruction::Store && (VT = dyn_cast<VectorTyp e>(I->getOperand(0)->getType())) && VT->isVectorTy()) {
1724 checkVectorType(VT);
1725 const StoreInst *SI = cast<StoreInst>(I);
1726 const Value *P = SI->getPointerOperand();
1727 std::string PS = getOpName(P);
1728 std::string VS = getValueAsStr(SI->getValueOperand());
1729 Code << getAdHocAssign(PS, P->getType()) << getValueAsStr(P) << ';';
1730
1731 // Determine if this is a partial store.
1732 static const std::string partialAccess[4] = { "X", "XY", "XYZ", "" };
1733 if (VT->getNumElements() < 1 || VT->getNumElements() > 4) {
1734 error("invalid number of lanes in SIMD operation!");
1735 return false;
1736 }
1737 const std::string &Part = partialAccess[VT->getNumElements() - 1];
1738
1739 if (VT->getElementType()->isIntegerTy()) {
1740 Code << "SIMD_int32x4_store" << Part << "(HEAPU8, " << PS << ", " << VS << ")";
1741 } else {
1742 Code << "SIMD_float32x4_store" << Part << "(HEAPU8, " << PS << ", " << V S << ")";
1743 }
1744 return true;
1745 } else if (Operator::getOpcode(I) == Instruction::ExtractElement) {
1746 generateExtractElementExpression(cast<ExtractElementInst>(I), Code);
1747 return true;
1748 }
1749 }
1750 return false;
1751 }
1752
1753 static uint64_t LSBMask(unsigned numBits) {
1754 return numBits >= 64 ? 0xFFFFFFFFFFFFFFFFULL : (1ULL << numBits) - 1;
1755 }
1756
1757 // Generate code for and operator, either an Instruction or a ConstantExpr.
1758 void JSWriter::generateExpression(const User *I, raw_string_ostream& Code) {
1759 // To avoid emiting code and variables for the no-op pointer bitcasts
1760 // and all-zero-index geps that LLVM needs to satisfy its type system, we
1761 // call stripPointerCasts() on all values before translating them. This
1762 // includes bitcasts whose only use is lifetime marker intrinsics.
1763 assert(I == I->stripPointerCasts());
1764
1765 Type *T = I->getType();
1766 if (T->isIntegerTy() && T->getIntegerBitWidth() > 32) {
1767 errs() << *I << "\n";
1768 report_fatal_error("legalization problem");
1769 }
1770
1771 if (!generateSIMDExpression(I, Code)) switch (Operator::getOpcode(I)) {
1772 default: {
1773 I->dump();
1774 error("Invalid instruction");
1775 break;
1776 }
1777 case Instruction::Ret: {
1778 const ReturnInst* ret = cast<ReturnInst>(I);
1779 const Value *RV = ret->getReturnValue();
1780 if (StackBumped) {
1781 Code << "STACKTOP = sp;";
1782 }
1783 Code << "return";
1784 if (RV != NULL) {
1785 Code << " " << getValueAsCastParenStr(RV, ASM_NONSPECIFIC | ASM_MUST_CAST) ;
1786 }
1787 break;
1788 }
1789 case Instruction::Br:
1790 case Instruction::IndirectBr:
1791 case Instruction::Switch: return; // handled while relooping
1792 case Instruction::Unreachable: {
1793 // Typically there should be an abort right before these, so we don't emit a ny code // TODO: when ASSERTIONS are on, emit abort(0)
1794 Code << "// unreachable";
1795 break;
1796 }
1797 case Instruction::Add:
1798 case Instruction::FAdd:
1799 case Instruction::Sub:
1800 case Instruction::FSub:
1801 case Instruction::Mul:
1802 case Instruction::FMul:
1803 case Instruction::UDiv:
1804 case Instruction::SDiv:
1805 case Instruction::FDiv:
1806 case Instruction::URem:
1807 case Instruction::SRem:
1808 case Instruction::FRem:
1809 case Instruction::And:
1810 case Instruction::Or:
1811 case Instruction::Xor:
1812 case Instruction::Shl:
1813 case Instruction::LShr:
1814 case Instruction::AShr:{
1815 Code << getAssignIfNeeded(I);
1816 unsigned opcode = Operator::getOpcode(I);
1817 switch (opcode) {
1818 case Instruction::Add: Code << getParenCast(
1819 getValueAsParenStr(I->getOperand(0)) +
1820 " + " +
1821 getValueAsParenStr(I->getOperand(1)),
1822 I->getType()
1823 ); break;
1824 case Instruction::Sub: Code << getParenCast(
1825 getValueAsParenStr(I->getOperand(0)) +
1826 " - " +
1827 getValueAsParenStr(I->getOperand(1)),
1828 I->getType()
1829 ); break;
1830 case Instruction::Mul: Code << getIMul(I->getOperand(0), I->getOperand(1) ); break;
1831 case Instruction::UDiv:
1832 case Instruction::SDiv:
1833 case Instruction::URem:
1834 case Instruction::SRem: Code << "(" <<
1835 getValueAsCastParenStr(I->getOperand(0), ( opcode == Instruction::SDiv || opcode == Instruction::SRem) ? ASM_SIGNED : ASM_U NSIGNED) <<
1836 ((opcode == Instruction::UDiv || opcode == Instruction::SDiv) ? " / " : " % ") <<
1837 getValueAsCastParenStr(I->getOperand(1), ( opcode == Instruction::SDiv || opcode == Instruction::SRem) ? ASM_SIGNED : ASM_U NSIGNED) <<
1838 ")&-1"; break;
1839 case Instruction::And: Code << getValueAsStr(I->getOperand(0)) << " & " < < getValueAsStr(I->getOperand(1)); break;
1840 case Instruction::Or: Code << getValueAsStr(I->getOperand(0)) << " | " < < getValueAsStr(I->getOperand(1)); break;
1841 case Instruction::Xor: Code << getValueAsStr(I->getOperand(0)) << " ^ " < < getValueAsStr(I->getOperand(1)); break;
1842 case Instruction::Shl: {
1843 std::string Shifted = getValueAsStr(I->getOperand(0)) + " << " + getVal ueAsStr(I->getOperand(1));
1844 if (I->getType()->getIntegerBitWidth() < 32) {
1845 Shifted = getParenCast(Shifted, I->getType(), ASM_UNSIGNED); // remove bits that are shifted beyond the size of this value
1846 }
1847 Code << Shifted;
1848 break;
1849 }
1850 case Instruction::AShr:
1851 case Instruction::LShr: {
1852 std::string Input = getValueAsStr(I->getOperand(0));
1853 if (I->getType()->getIntegerBitWidth() < 32) {
1854 Input = '(' + getCast(Input, I->getType(), opcode == Instruction::AShr ? ASM_SIGNED : ASM_UNSIGNED) + ')'; // fill in high bits, as shift needs those and is done in 32-bit
1855 }
1856 Code << Input << (opcode == Instruction::AShr ? " >> " : " >>> ") << ge tValueAsStr(I->getOperand(1));
1857 break;
1858 }
1859
1860 case Instruction::FAdd: Code << ensureFloat(getValueAsStr(I->getOperand(0) ) + " + " + getValueAsStr(I->getOperand(1)), I->getType()); break;
1861 case Instruction::FMul: Code << ensureFloat(getValueAsStr(I->getOperand(0) ) + " * " + getValueAsStr(I->getOperand(1)), I->getType()); break;
1862 case Instruction::FDiv: Code << ensureFloat(getValueAsStr(I->getOperand(0) ) + " / " + getValueAsStr(I->getOperand(1)), I->getType()); break;
1863 case Instruction::FRem: Code << ensureFloat(getValueAsStr(I->getOperand(0) ) + " % " + getValueAsStr(I->getOperand(1)), I->getType()); break;
1864 case Instruction::FSub:
1865 // LLVM represents an fneg(x) as -0.0 - x.
1866 if (BinaryOperator::isFNeg(I)) {
1867 Code << ensureFloat("-" + getValueAsStr(BinaryOperator::getFNegArgumen t(I)), I->getType());
1868 } else {
1869 Code << ensureFloat(getValueAsStr(I->getOperand(0)) + " - " + getValue AsStr(I->getOperand(1)), I->getType());
1870 }
1871 break;
1872 default: error("bad binary opcode"); break;
1873 }
1874 break;
1875 }
1876 case Instruction::FCmp: {
1877 Code << getAssignIfNeeded(I);
1878 switch (cast<FCmpInst>(I)->getPredicate()) {
1879 // Comparisons which are simple JS operators.
1880 case FCmpInst::FCMP_OEQ: Code << getValueAsStr(I->getOperand(0)) << " == " << getValueAsStr(I->getOperand(1)); break;
1881 case FCmpInst::FCMP_UNE: Code << getValueAsStr(I->getOperand(0)) << " != " << getValueAsStr(I->getOperand(1)); break;
1882 case FCmpInst::FCMP_OGT: Code << getValueAsStr(I->getOperand(0)) << " > " << getValueAsStr(I->getOperand(1)); break;
1883 case FCmpInst::FCMP_OGE: Code << getValueAsStr(I->getOperand(0)) << " >= " << getValueAsStr(I->getOperand(1)); break;
1884 case FCmpInst::FCMP_OLT: Code << getValueAsStr(I->getOperand(0)) << " < " << getValueAsStr(I->getOperand(1)); break;
1885 case FCmpInst::FCMP_OLE: Code << getValueAsStr(I->getOperand(0)) << " <= " << getValueAsStr(I->getOperand(1)); break;
1886
1887 // Comparisons which are inverses of JS operators.
1888 case FCmpInst::FCMP_UGT:
1889 Code << "!(" << getValueAsStr(I->getOperand(0)) << " <= " << getValueAsS tr(I->getOperand(1)) << ")";
1890 break;
1891 case FCmpInst::FCMP_UGE:
1892 Code << "!(" << getValueAsStr(I->getOperand(0)) << " < " << getValueAsS tr(I->getOperand(1)) << ")";
1893 break;
1894 case FCmpInst::FCMP_ULT:
1895 Code << "!(" << getValueAsStr(I->getOperand(0)) << " >= " << getValueAsS tr(I->getOperand(1)) << ")";
1896 break;
1897 case FCmpInst::FCMP_ULE:
1898 Code << "!(" << getValueAsStr(I->getOperand(0)) << " > " << getValueAsS tr(I->getOperand(1)) << ")";
1899 break;
1900
1901 // Comparisons which require explicit NaN checks.
1902 case FCmpInst::FCMP_UEQ:
1903 Code << "(" << getValueAsStr(I->getOperand(0)) << " != " << getValueAsSt r(I->getOperand(0)) << ") | " <<
1904 "(" << getValueAsStr(I->getOperand(1)) << " != " << getValueAsSt r(I->getOperand(1)) << ") |" <<
1905 "(" << getValueAsStr(I->getOperand(0)) << " == " << getValueAsSt r(I->getOperand(1)) << ")";
1906 break;
1907 case FCmpInst::FCMP_ONE:
1908 Code << "(" << getValueAsStr(I->getOperand(0)) << " == " << getValueAsSt r(I->getOperand(0)) << ") & " <<
1909 "(" << getValueAsStr(I->getOperand(1)) << " == " << getValueAsSt r(I->getOperand(1)) << ") &" <<
1910 "(" << getValueAsStr(I->getOperand(0)) << " != " << getValueAsSt r(I->getOperand(1)) << ")";
1911 break;
1912
1913 // Simple NaN checks.
1914 case FCmpInst::FCMP_ORD: Code << "(" << getValueAsStr(I->getOperand(0)) << " == " << getValueAsStr(I->getOperand(0)) << ") & " <<
1915 "(" << getValueAsStr(I->getOperand(1)) << " == " << getValueAsStr(I->getOperand(1)) << ")"; break;
1916 case FCmpInst::FCMP_UNO: Code << "(" << getValueAsStr(I->getOperand(0)) << " != " << getValueAsStr(I->getOperand(0)) << ") | " <<
1917 "(" << getValueAsStr(I->getOperand(1)) << " != " << getValueAsStr(I->getOperand(1)) << ")"; break;
1918
1919 // Simple constants.
1920 case FCmpInst::FCMP_FALSE: Code << "0"; break;
1921 case FCmpInst::FCMP_TRUE : Code << "1"; break;
1922
1923 default: error("bad fcmp"); break;
1924 }
1925 break;
1926 }
1927 case Instruction::ICmp: {
1928 unsigned predicate = isa<ConstantExpr>(I) ?
1929 cast<ConstantExpr>(I)->getPredicate() :
1930 cast<ICmpInst>(I)->getPredicate();
1931 AsmCast sign = CmpInst::isUnsigned(predicate) ? ASM_UNSIGNED : ASM_SIGNED;
1932 Code << getAssignIfNeeded(I) << "(" <<
1933 getValueAsCastStr(I->getOperand(0), sign) <<
1934 ")";
1935 switch (predicate) {
1936 case ICmpInst::ICMP_EQ: Code << "=="; break;
1937 case ICmpInst::ICMP_NE: Code << "!="; break;
1938 case ICmpInst::ICMP_ULE: Code << "<="; break;
1939 case ICmpInst::ICMP_SLE: Code << "<="; break;
1940 case ICmpInst::ICMP_UGE: Code << ">="; break;
1941 case ICmpInst::ICMP_SGE: Code << ">="; break;
1942 case ICmpInst::ICMP_ULT: Code << "<"; break;
1943 case ICmpInst::ICMP_SLT: Code << "<"; break;
1944 case ICmpInst::ICMP_UGT: Code << ">"; break;
1945 case ICmpInst::ICMP_SGT: Code << ">"; break;
1946 default: llvm_unreachable("Invalid ICmp predicate");
1947 }
1948 Code << "(" <<
1949 getValueAsCastStr(I->getOperand(1), sign) <<
1950 ")";
1951 break;
1952 }
1953 case Instruction::Alloca: {
1954 const AllocaInst* AI = cast<AllocaInst>(I);
1955
1956 // We've done an alloca, so we'll have bumped the stack and will
1957 // need to restore it.
1958 // Yes, we shouldn't have to bump it for nativized vars, however
1959 // they are included in the frame offset, so the restore is still
1960 // needed until that is fixed.
1961 StackBumped = true;
1962
1963 if (NativizedVars.count(AI)) {
1964 // nativized stack variable, we just need a 'var' definition
1965 UsedVars[getJSName(AI)] = AI->getType()->getElementType();
1966 return;
1967 }
1968
1969 // Fixed-size entry-block allocations are allocated all at once in the
1970 // function prologue.
1971 if (AI->isStaticAlloca()) {
1972 uint64_t Offset;
1973 if (Allocas.getFrameOffset(AI, &Offset)) {
1974 Code << getAssign(AI);
1975 if (Allocas.getMaxAlignment() <= STACK_ALIGN) {
1976 Code << "sp";
1977 } else {
1978 Code << "sp_a"; // aligned base of stack is different, use that
1979 }
1980 if (Offset != 0) {
1981 Code << " + " << Offset << "|0";
1982 }
1983 break;
1984 }
1985 // Otherwise, this alloca is being represented by another alloca, so
1986 // there's nothing to print.
1987 return;
1988 }
1989
1990 assert(AI->getAlignment() <= STACK_ALIGN); // TODO
1991
1992 Type *T = AI->getAllocatedType();
1993 std::string Size;
1994 uint64_t BaseSize = DL->getTypeAllocSize(T);
1995 const Value *AS = AI->getArraySize();
1996 if (const ConstantInt *CI = dyn_cast<ConstantInt>(AS)) {
1997 Size = Twine(stackAlign(BaseSize * CI->getZExtValue())).str();
1998 } else {
1999 Size = stackAlignStr("((" + utostr(BaseSize) + '*' + getValueAsStr(AS) + " )|0)");
2000 }
2001 Code << getAssign(AI) << "STACKTOP; " << getStackBump(Size);
2002 break;
2003 }
2004 case Instruction::Load: {
2005 const LoadInst *LI = cast<LoadInst>(I);
2006 const Value *P = LI->getPointerOperand();
2007 unsigned Alignment = LI->getAlignment();
2008 if (NativizedVars.count(P)) {
2009 Code << getAssign(LI) << getValueAsStr(P);
2010 } else {
2011 Code << getLoad(LI, P, LI->getType(), Alignment);
2012 }
2013 break;
2014 }
2015 case Instruction::Store: {
2016 const StoreInst *SI = cast<StoreInst>(I);
2017 const Value *P = SI->getPointerOperand();
2018 const Value *V = SI->getValueOperand();
2019 unsigned Alignment = SI->getAlignment();
2020 std::string VS = getValueAsStr(V);
2021 if (NativizedVars.count(P)) {
2022 Code << getValueAsStr(P) << " = " << VS;
2023 } else {
2024 Code << getStore(SI, P, V->getType(), VS, Alignment);
2025 }
2026
2027 Type *T = V->getType();
2028 if (T->isIntegerTy() && T->getIntegerBitWidth() > 32) {
2029 errs() << *I << "\n";
2030 report_fatal_error("legalization problem");
2031 }
2032 break;
2033 }
2034 case Instruction::GetElementPtr: {
2035 Code << getAssignIfNeeded(I);
2036 const GEPOperator *GEP = cast<GEPOperator>(I);
2037 gep_type_iterator GTI = gep_type_begin(GEP);
2038 int32_t ConstantOffset = 0;
2039 std::string text = getValueAsParenStr(GEP->getPointerOperand());
2040
2041 GetElementPtrInst::const_op_iterator I = GEP->op_begin();
2042 I++;
2043 for (GetElementPtrInst::const_op_iterator E = GEP->op_end();
2044 I != E; ++I) {
2045 const Value *Index = *I;
2046 if (StructType *STy = dyn_cast<StructType>(*GTI++)) {
2047 // For a struct, add the member offset.
2048 unsigned FieldNo = cast<ConstantInt>(Index)->getZExtValue();
2049 uint32_t Offset = DL->getStructLayout(STy)->getElementOffset(FieldNo);
2050 ConstantOffset = (uint32_t)ConstantOffset + Offset;
2051 } else {
2052 // For an array, add the element offset, explicitly scaled.
2053 uint32_t ElementSize = DL->getTypeAllocSize(*GTI);
2054 if (const ConstantInt *CI = dyn_cast<ConstantInt>(Index)) {
2055 ConstantOffset = (uint32_t)ConstantOffset + (uint32_t)CI->getSExtValue () * ElementSize;
2056 } else {
2057 text = "(" + text + " + (" + getIMul(Index, ConstantInt::get(Type::get Int32Ty(GEP->getContext()), ElementSize)) + ")|0)";
2058 }
2059 }
2060 }
2061 if (ConstantOffset != 0) {
2062 text = "(" + text + " + " + itostr(ConstantOffset) + "|0)";
2063 }
2064 Code << text;
2065 break;
2066 }
2067 case Instruction::PHI: {
2068 // handled separately - we push them back into the relooper branchings
2069 return;
2070 }
2071 case Instruction::PtrToInt:
2072 case Instruction::IntToPtr:
2073 Code << getAssignIfNeeded(I) << getValueAsStr(I->getOperand(0));
2074 break;
2075 case Instruction::Trunc:
2076 case Instruction::ZExt:
2077 case Instruction::SExt:
2078 case Instruction::FPTrunc:
2079 case Instruction::FPExt:
2080 case Instruction::FPToUI:
2081 case Instruction::FPToSI:
2082 case Instruction::UIToFP:
2083 case Instruction::SIToFP: {
2084 Code << getAssignIfNeeded(I);
2085 switch (Operator::getOpcode(I)) {
2086 case Instruction::Trunc: {
2087 //unsigned inBits = V->getType()->getIntegerBitWidth();
2088 unsigned outBits = I->getType()->getIntegerBitWidth();
2089 Code << getValueAsStr(I->getOperand(0)) << "&" << utostr(LSBMask(outBits)) ;
2090 break;
2091 }
2092 case Instruction::SExt: {
2093 std::string bits = utostr(32 - I->getOperand(0)->getType()->getIntegerBitW idth());
2094 Code << getValueAsStr(I->getOperand(0)) << " << " << bits << " >> " << bit s;
2095 break;
2096 }
2097 case Instruction::ZExt: {
2098 Code << getValueAsCastStr(I->getOperand(0), ASM_UNSIGNED);
2099 break;
2100 }
2101 case Instruction::FPExt: {
2102 if (PreciseF32) {
2103 Code << "+" << getValueAsStr(I->getOperand(0)); break;
2104 } else {
2105 Code << getValueAsStr(I->getOperand(0)); break;
2106 }
2107 break;
2108 }
2109 case Instruction::FPTrunc: {
2110 Code << ensureFloat(getValueAsStr(I->getOperand(0)), I->getType());
2111 break;
2112 }
2113 case Instruction::SIToFP: Code << '(' << getCast(getValueAsCastParenStr(I- >getOperand(0), ASM_SIGNED), I->getType()) << ')'; break;
2114 case Instruction::UIToFP: Code << '(' << getCast(getValueAsCastParenStr(I- >getOperand(0), ASM_UNSIGNED), I->getType()) << ')'; break;
2115 case Instruction::FPToSI: Code << '(' << getDoubleToInt(getValueAsParenStr (I->getOperand(0))) << ')'; break;
2116 case Instruction::FPToUI: Code << '(' << getCast(getDoubleToInt(getValueAs ParenStr(I->getOperand(0))), I->getType(), ASM_UNSIGNED) << ')'; break;
2117 case Instruction::PtrToInt: Code << '(' << getValueAsStr(I->getOperand(0)) < < ')'; break;
2118 case Instruction::IntToPtr: Code << '(' << getValueAsStr(I->getOperand(0)) < < ')'; break;
2119 default: llvm_unreachable("Unreachable");
2120 }
2121 break;
2122 }
2123 case Instruction::BitCast: {
2124 Code << getAssignIfNeeded(I);
2125 // Most bitcasts are no-ops for us. However, the exception is int to float a nd float to int
2126 Type *InType = I->getOperand(0)->getType();
2127 Type *OutType = I->getType();
2128 std::string V = getValueAsStr(I->getOperand(0));
2129 if (InType->isIntegerTy() && OutType->isFloatingPointTy()) {
2130 assert(InType->getIntegerBitWidth() == 32);
2131 Code << "(HEAP32[tempDoublePtr>>2]=" << V << "," << getCast("HEAPF32[tempD oublePtr>>2]", Type::getFloatTy(TheModule->getContext())) << ")";
2132 } else if (OutType->isIntegerTy() && InType->isFloatingPointTy()) {
2133 assert(OutType->getIntegerBitWidth() == 32);
2134 Code << "(HEAPF32[tempDoublePtr>>2]=" << V << "," "HEAP32[tempDoublePtr>>2 ]|0)";
2135 } else {
2136 Code << V;
2137 }
2138 break;
2139 }
2140 case Instruction::Call: {
2141 const CallInst *CI = cast<CallInst>(I);
2142 std::string Call = handleCall(CI);
2143 if (Call.empty()) return;
2144 Code << Call;
2145 break;
2146 }
2147 case Instruction::Select: {
2148 Code << getAssignIfNeeded(I) << getValueAsStr(I->getOperand(0)) << " ? " <<
2149 getValueAsStr(I->getOperand(1)) << " : " <<
2150 getValueAsStr(I->getOperand(2));
2151 break;
2152 }
2153 case Instruction::AtomicRMW: {
2154 const AtomicRMWInst *rmwi = cast<AtomicRMWInst>(I);
2155 const Value *P = rmwi->getOperand(0);
2156 const Value *V = rmwi->getOperand(1);
2157 std::string VS = getValueAsStr(V);
2158 Code << getLoad(rmwi, P, I->getType(), 0) << ';';
2159 // Most bitcasts are no-ops for us. However, the exception is int to float a nd float to int
2160 switch (rmwi->getOperation()) {
2161 case AtomicRMWInst::Xchg: Code << getStore(rmwi, P, I->getType(), VS, 0); break;
2162 case AtomicRMWInst::Add: Code << getStore(rmwi, P, I->getType(), "((" + g etJSName(I) + '+' + VS + ")|0)", 0); break;
2163 case AtomicRMWInst::Sub: Code << getStore(rmwi, P, I->getType(), "((" + g etJSName(I) + '-' + VS + ")|0)", 0); break;
2164 case AtomicRMWInst::And: Code << getStore(rmwi, P, I->getType(), "(" + ge tJSName(I) + '&' + VS + ")", 0); break;
2165 case AtomicRMWInst::Nand: Code << getStore(rmwi, P, I->getType(), "(~(" + getJSName(I) + '&' + VS + "))", 0); break;
2166 case AtomicRMWInst::Or: Code << getStore(rmwi, P, I->getType(), "(" + ge tJSName(I) + '|' + VS + ")", 0); break;
2167 case AtomicRMWInst::Xor: Code << getStore(rmwi, P, I->getType(), "(" + ge tJSName(I) + '^' + VS + ")", 0); break;
2168 case AtomicRMWInst::Max:
2169 case AtomicRMWInst::Min:
2170 case AtomicRMWInst::UMax:
2171 case AtomicRMWInst::UMin:
2172 case AtomicRMWInst::BAD_BINOP: llvm_unreachable("Bad atomic operation");
2173 }
2174 break;
2175 }
2176 case Instruction::Fence: // no threads, so nothing to do here
2177 Code << "/* fence */";
2178 break;
2179 }
2180
2181 if (const Instruction *Inst = dyn_cast<Instruction>(I)) {
2182 Code << ';';
2183 // append debug info
2184 emitDebugInfo(Code, Inst);
2185 Code << '\n';
2186 }
2187 }
2188
2189 // Checks whether to use a condition variable. We do so for switches and for ind irectbrs
2190 static const Value *considerConditionVar(const Instruction *I) {
2191 if (const IndirectBrInst *IB = dyn_cast<const IndirectBrInst>(I)) {
2192 return IB->getAddress();
2193 }
2194 const SwitchInst *SI = dyn_cast<SwitchInst>(I);
2195 if (!SI) return NULL;
2196 // use a switch if the range is not too big or sparse
2197 int64_t Minn = INT64_MAX, Maxx = INT64_MIN;
2198 for (SwitchInst::ConstCaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
2199 int64_t Curr = i.getCaseValue()->getSExtValue();
2200 if (Curr < Minn) Minn = Curr;
2201 if (Curr > Maxx) Maxx = Curr;
2202 }
2203 int64_t Range = Maxx - Minn;
2204 int Num = SI->getNumCases();
2205 return Num < 5 || Range > 10*1024 || (Range/Num) > 1024 ? NULL : SI->getCondit ion(); // heuristics
2206 }
2207
2208 void JSWriter::addBlock(const BasicBlock *BB, Relooper& R, LLVMToRelooperMap& LL VMToRelooper) {
2209 std::string Code;
2210 raw_string_ostream CodeStream(Code);
2211 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
2212 I != E; ++I) {
2213 if (I->stripPointerCasts() == I) {
2214 generateExpression(I, CodeStream);
2215 }
2216 }
2217 CodeStream.flush();
2218 const Value* Condition = considerConditionVar(BB->getTerminator());
2219 Block *Curr = new Block(Code.c_str(), Condition ? getValueAsCastStr(Condition) .c_str() : NULL);
2220 LLVMToRelooper[BB] = Curr;
2221 R.AddBlock(Curr);
2222 }
2223
2224 void JSWriter::printFunctionBody(const Function *F) {
2225 assert(!F->isDeclaration());
2226
2227 // Prepare relooper
2228 Relooper::MakeOutputBuffer(1024*1024);
2229 Relooper R;
2230 //if (!canReloop(F)) R.SetEmulate(true);
2231 if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute::Mi nSize) ||
2232 F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute::Op timizeForSize)) {
2233 R.SetMinSize(true);
2234 }
2235 R.SetAsmJSMode(1);
2236 Block *Entry = NULL;
2237 LLVMToRelooperMap LLVMToRelooper;
2238
2239 // Create relooper blocks with their contents. TODO: We could optimize
2240 // indirectbr by emitting indexed blocks first, so their indexes
2241 // match up with the label index.
2242 for (Function::const_iterator BI = F->begin(), BE = F->end();
2243 BI != BE; ++BI) {
2244 InvokeState = 0; // each basic block begins in state 0; the previous may not have cleared it, if e.g. it had a throw in the middle and the rest of it was de capitated
2245 addBlock(BI, R, LLVMToRelooper);
2246 if (!Entry) Entry = LLVMToRelooper[BI];
2247 }
2248 assert(Entry);
2249
2250 // Create branchings
2251 for (Function::const_iterator BI = F->begin(), BE = F->end();
2252 BI != BE; ++BI) {
2253 const TerminatorInst *TI = BI->getTerminator();
2254 switch (TI->getOpcode()) {
2255 default: {
2256 report_fatal_error("invalid branch instr " + Twine(TI->getOpcodeName())) ;
2257 break;
2258 }
2259 case Instruction::Br: {
2260 const BranchInst* br = cast<BranchInst>(TI);
2261 if (br->getNumOperands() == 3) {
2262 BasicBlock *S0 = br->getSuccessor(0);
2263 BasicBlock *S1 = br->getSuccessor(1);
2264 std::string P0 = getPhiCode(&*BI, S0);
2265 std::string P1 = getPhiCode(&*BI, S1);
2266 LLVMToRelooper[&*BI]->AddBranchTo(LLVMToRelooper[&*S0], getValueAsStr( TI->getOperand(0)).c_str(), P0.size() > 0 ? P0.c_str() : NULL);
2267 LLVMToRelooper[&*BI]->AddBranchTo(LLVMToRelooper[&*S1], NULL, P1.size() > 0 ? P1.c_str() : NULL);
2268 } else if (br->getNumOperands() == 1) {
2269 BasicBlock *S = br->getSuccessor(0);
2270 std::string P = getPhiCode(&*BI, S);
2271 LLVMToRelooper[&*BI]->AddBranchTo(LLVMToRelooper[&*S], NULL, P.size() > 0 ? P.c_str() : NULL);
2272 } else {
2273 error("Branch with 2 operands?");
2274 }
2275 break;
2276 }
2277 case Instruction::IndirectBr: {
2278 const IndirectBrInst* br = cast<IndirectBrInst>(TI);
2279 unsigned Num = br->getNumDestinations();
2280 std::set<const BasicBlock*> Seen; // sadly llvm allows the same block to appear multiple times
2281 bool SetDefault = false; // pick the first and make it the default, llvm gives no reasonable default here
2282 for (unsigned i = 0; i < Num; i++) {
2283 const BasicBlock *S = br->getDestination(i);
2284 if (Seen.find(S) != Seen.end()) continue;
2285 Seen.insert(S);
2286 std::string P = getPhiCode(&*BI, S);
2287 std::string Target;
2288 if (!SetDefault) {
2289 SetDefault = true;
2290 } else {
2291 Target = "case " + utostr(getBlockAddress(F, S)) + ": ";
2292 }
2293 LLVMToRelooper[&*BI]->AddBranchTo(LLVMToRelooper[&*S], Target.size() > 0 ? Target.c_str() : NULL, P.size() > 0 ? P.c_str() : NULL);
2294 }
2295 break;
2296 }
2297 case Instruction::Switch: {
2298 const SwitchInst* SI = cast<SwitchInst>(TI);
2299 bool UseSwitch = !!considerConditionVar(SI);
2300 BasicBlock *DD = SI->getDefaultDest();
2301 std::string P = getPhiCode(&*BI, DD);
2302 LLVMToRelooper[&*BI]->AddBranchTo(LLVMToRelooper[&*DD], NULL, P.size() > 0 ? P.c_str() : NULL);
2303 typedef std::map<const BasicBlock*, std::string> BlockCondMap;
2304 BlockCondMap BlocksToConditions;
2305 for (SwitchInst::ConstCaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
2306 const BasicBlock *BB = i.getCaseSuccessor();
2307 std::string Curr = i.getCaseValue()->getValue().toString(10, true);
2308 std::string Condition;
2309 if (UseSwitch) {
2310 Condition = "case " + Curr + ": ";
2311 } else {
2312 Condition = "(" + getValueAsCastParenStr(SI->getCondition()) + " == " + Curr + ")";
2313 }
2314 BlocksToConditions[BB] = Condition + (!UseSwitch && BlocksToConditions [BB].size() > 0 ? " | " : "") + BlocksToConditions[BB];
2315 }
2316 for (BlockCondMap::const_iterator I = BlocksToConditions.begin(), E = Bl ocksToConditions.end(); I != E; ++I) {
2317 const BasicBlock *BB = I->first;
2318 if (BB == DD) continue; // ok to eliminate this, default dest will get there anyhow
2319 std::string P = getPhiCode(&*BI, BB);
2320 LLVMToRelooper[&*BI]->AddBranchTo(LLVMToRelooper[&*BB], I->second.c_st r(), P.size() > 0 ? P.c_str() : NULL);
2321 }
2322 break;
2323 }
2324 case Instruction::Ret:
2325 case Instruction::Unreachable: break;
2326 }
2327 }
2328
2329 // Calculate relooping and print
2330 R.Calculate(Entry);
2331 R.Render();
2332
2333 // Emit local variables
2334 UsedVars["sp"] = Type::getInt32Ty(F->getContext());
2335 unsigned MaxAlignment = Allocas.getMaxAlignment();
2336 if (MaxAlignment > STACK_ALIGN) {
2337 UsedVars["sp_a"] = Type::getInt32Ty(F->getContext());
2338 }
2339 UsedVars["label"] = Type::getInt32Ty(F->getContext());
2340 if (!UsedVars.empty()) {
2341 unsigned Count = 0;
2342 for (VarMap::const_iterator VI = UsedVars.begin(); VI != UsedVars.end(); ++V I) {
2343 if (Count == 20) {
2344 Out << ";\n";
2345 Count = 0;
2346 }
2347 if (Count == 0) Out << " var ";
2348 if (Count > 0) {
2349 Out << ", ";
2350 }
2351 Count++;
2352 Out << VI->first << " = ";
2353 switch (VI->second->getTypeID()) {
2354 default:
2355 llvm_unreachable("unsupported variable initializer type");
2356 case Type::PointerTyID:
2357 case Type::IntegerTyID:
2358 Out << "0";
2359 break;
2360 case Type::FloatTyID:
2361 if (PreciseF32) {
2362 Out << "Math_fround(0)";
2363 break;
2364 }
2365 // otherwise fall through to double
2366 case Type::DoubleTyID:
2367 Out << "+0";
2368 break;
2369 case Type::VectorTyID:
2370 if (cast<VectorType>(VI->second)->getElementType()->isIntegerTy()) {
2371 Out << "SIMD_int32x4(0,0,0,0)";
2372 } else {
2373 Out << "SIMD_float32x4(0,0,0,0)";
2374 }
2375 break;
2376 }
2377 }
2378 Out << ";";
2379 nl(Out);
2380 }
2381
2382 {
2383 static bool Warned = false;
2384 if (!Warned && OptLevel < 2 && UsedVars.size() > 2000) {
2385 prettyWarning() << "emitted code will contain very large numbers of local variables, which is bad for performance (build to JS with -O2 or above to avoid this - make sure to do so both on source files, and during 'linking')\n";
2386 Warned = true;
2387 }
2388 }
2389
2390 // Emit stack entry
2391 Out << " " << getAdHocAssign("sp", Type::getInt32Ty(F->getContext())) << "STAC KTOP;";
2392 if (uint64_t FrameSize = Allocas.getFrameSize()) {
2393 if (MaxAlignment > STACK_ALIGN) {
2394 // We must align this entire stack frame to something higher than the defa ult
2395 Out << "\n ";
2396 Out << "sp_a = STACKTOP = (STACKTOP + " << utostr(MaxAlignment-1) << ")&-" << utostr(MaxAlignment) << ";";
2397 }
2398 Out << "\n ";
2399 Out << getStackBump(FrameSize);
2400 }
2401
2402 // Emit (relooped) code
2403 char *buffer = Relooper::GetOutputBuffer();
2404 nl(Out) << buffer;
2405
2406 // Ensure a final return if necessary
2407 Type *RT = F->getFunctionType()->getReturnType();
2408 if (!RT->isVoidTy()) {
2409 char *LastCurly = strrchr(buffer, '}');
2410 if (!LastCurly) LastCurly = buffer;
2411 char *FinalReturn = strstr(LastCurly, "return ");
2412 if (!FinalReturn) {
2413 Out << " return " << getParenCast(getConstant(UndefValue::get(RT)), RT, AS M_NONSPECIFIC) << ";\n";
2414 }
2415 }
2416 }
2417
2418 void JSWriter::processConstants() {
2419 // First, calculate the address of each constant
2420 for (Module::const_global_iterator I = TheModule->global_begin(),
2421 E = TheModule->global_end(); I != E; ++I) {
2422 if (I->hasInitializer()) {
2423 parseConstant(I->getName().str(), I->getInitializer(), true);
2424 }
2425 }
2426 // Second, allocate their contents
2427 for (Module::const_global_iterator I = TheModule->global_begin(),
2428 E = TheModule->global_end(); I != E; ++I) {
2429 if (I->hasInitializer()) {
2430 parseConstant(I->getName().str(), I->getInitializer(), false);
2431 }
2432 }
2433 }
2434
2435 void JSWriter::printFunction(const Function *F) {
2436 ValueNames.clear();
2437
2438 // Prepare and analyze function
2439
2440 UsedVars.clear();
2441 UniqueNum = 0;
2442
2443 // When optimizing, the regular optimizer (mem2reg, SROA, GVN, and others)
2444 // will have already taken all the opportunities for nativization.
2445 if (OptLevel == CodeGenOpt::None)
2446 calculateNativizedVars(F);
2447
2448 // Do alloca coloring at -O1 and higher.
2449 Allocas.analyze(*F, *DL, OptLevel != CodeGenOpt::None);
2450
2451 // Emit the function
2452
2453 std::string Name = F->getName();
2454 sanitizeGlobal(Name);
2455 Out << "function " << Name << "(";
2456 for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
2457 AI != AE; ++AI) {
2458 if (AI != F->arg_begin()) Out << ",";
2459 Out << getJSName(AI);
2460 }
2461 Out << ") {";
2462 nl(Out);
2463 for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
2464 AI != AE; ++AI) {
2465 std::string name = getJSName(AI);
2466 Out << " " << name << " = " << getCast(name, AI->getType(), ASM_NONSPECIFIC) << ";";
2467 nl(Out);
2468 }
2469 printFunctionBody(F);
2470 Out << "}";
2471 nl(Out);
2472
2473 Allocas.clear();
2474 StackBumped = false;
2475 }
2476
2477 void JSWriter::printModuleBody() {
2478 processConstants();
2479
2480 // Emit function bodies.
2481 nl(Out) << "// EMSCRIPTEN_START_FUNCTIONS"; nl(Out);
2482 for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
2483 I != E; ++I) {
2484 if (!I->isDeclaration()) printFunction(I);
2485 }
2486 Out << "function runPostSets() {\n";
2487 Out << " " << PostSets << "\n";
2488 Out << "}\n";
2489 PostSets = "";
2490 Out << "// EMSCRIPTEN_END_FUNCTIONS\n\n";
2491
2492 assert(GlobalData32.size() == 0 && GlobalData8.size() == 0); // FIXME when we use optimal constant alignments
2493
2494 // TODO fix commas
2495 Out << "/* memory initializer */ allocate([";
2496 printCommaSeparated(GlobalData64);
2497 if (GlobalData64.size() > 0 && GlobalData32.size() + GlobalData8.size() > 0) {
2498 Out << ",";
2499 }
2500 printCommaSeparated(GlobalData32);
2501 if (GlobalData32.size() > 0 && GlobalData8.size() > 0) {
2502 Out << ",";
2503 }
2504 printCommaSeparated(GlobalData8);
2505 Out << "], \"i8\", ALLOC_NONE, Runtime.GLOBAL_BASE);";
2506
2507 // Emit metadata for emcc driver
2508 Out << "\n\n// EMSCRIPTEN_METADATA\n";
2509 Out << "{\n";
2510
2511 Out << "\"declares\": [";
2512 bool first = true;
2513 for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
2514 I != E; ++I) {
2515 if (I->isDeclaration() && !I->use_empty()) {
2516 // Ignore intrinsics that are always no-ops or expanded into other code
2517 // which doesn't require the intrinsic function itself to be declared.
2518 if (I->isIntrinsic()) {
2519 switch (I->getIntrinsicID()) {
2520 case Intrinsic::dbg_declare:
2521 case Intrinsic::dbg_value:
2522 case Intrinsic::lifetime_start:
2523 case Intrinsic::lifetime_end:
2524 case Intrinsic::invariant_start:
2525 case Intrinsic::invariant_end:
2526 case Intrinsic::prefetch:
2527 case Intrinsic::memcpy:
2528 case Intrinsic::memset:
2529 case Intrinsic::memmove:
2530 case Intrinsic::expect:
2531 case Intrinsic::flt_rounds:
2532 continue;
2533 }
2534 }
2535
2536 if (first) {
2537 first = false;
2538 } else {
2539 Out << ", ";
2540 }
2541 Out << "\"" << I->getName() << "\"";
2542 }
2543 }
2544 for (NameSet::const_iterator I = Declares.begin(), E = Declares.end();
2545 I != E; ++I) {
2546 if (first) {
2547 first = false;
2548 } else {
2549 Out << ", ";
2550 }
2551 Out << "\"" << *I << "\"";
2552 }
2553 Out << "],";
2554
2555 Out << "\"redirects\": {";
2556 first = true;
2557 for (StringMap::const_iterator I = Redirects.begin(), E = Redirects.end();
2558 I != E; ++I) {
2559 if (first) {
2560 first = false;
2561 } else {
2562 Out << ", ";
2563 }
2564 Out << "\"_" << I->first << "\": \"" << I->second << "\"";
2565 }
2566 Out << "},";
2567
2568 Out << "\"externs\": [";
2569 first = true;
2570 for (NameSet::const_iterator I = Externals.begin(), E = Externals.end();
2571 I != E; ++I) {
2572 if (first) {
2573 first = false;
2574 } else {
2575 Out << ", ";
2576 }
2577 Out << "\"" << *I << "\"";
2578 }
2579 Out << "],";
2580
2581 Out << "\"implementedFunctions\": [";
2582 first = true;
2583 for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
2584 I != E; ++I) {
2585 if (!I->isDeclaration()) {
2586 if (first) {
2587 first = false;
2588 } else {
2589 Out << ", ";
2590 }
2591 std::string name = I->getName();
2592 sanitizeGlobal(name);
2593 Out << "\"" << name << '"';
2594 }
2595 }
2596 Out << "],";
2597
2598 Out << "\"tables\": {";
2599 unsigned Num = FunctionTables.size();
2600 for (FunctionTableMap::iterator I = FunctionTables.begin(), E = FunctionTables .end(); I != E; ++I) {
2601 Out << " \"" << I->first << "\": \"var FUNCTION_TABLE_" << I->first << " = [";
2602 FunctionTable &Table = I->second;
2603 // ensure power of two
2604 unsigned Size = 1;
2605 while (Size < Table.size()) Size <<= 1;
2606 while (Table.size() < Size) Table.push_back("0");
2607 for (unsigned i = 0; i < Table.size(); i++) {
2608 Out << Table[i];
2609 if (i < Table.size()-1) Out << ",";
2610 }
2611 Out << "];\"";
2612 if (--Num > 0) Out << ",";
2613 Out << "\n";
2614 }
2615 Out << "},";
2616
2617 Out << "\"initializers\": [";
2618 first = true;
2619 for (unsigned i = 0; i < GlobalInitializers.size(); i++) {
2620 if (first) {
2621 first = false;
2622 } else {
2623 Out << ", ";
2624 }
2625 Out << "\"" << GlobalInitializers[i] << "\"";
2626 }
2627 Out << "],";
2628
2629 Out << "\"exports\": [";
2630 first = true;
2631 for (unsigned i = 0; i < Exports.size(); i++) {
2632 if (first) {
2633 first = false;
2634 } else {
2635 Out << ", ";
2636 }
2637 Out << "\"" << Exports[i] << "\"";
2638 }
2639 Out << "],";
2640
2641 Out << "\"cantValidate\": \"" << CantValidate << "\",";
2642
2643 Out << "\"simd\": ";
2644 Out << (UsesSIMD ? "1" : "0");
2645 Out << ",";
2646
2647 Out << "\"namedGlobals\": {";
2648 first = true;
2649 for (NameIntMap::const_iterator I = NamedGlobals.begin(), E = NamedGlobals.end (); I != E; ++I) {
2650 if (first) {
2651 first = false;
2652 } else {
2653 Out << ", ";
2654 }
2655 Out << "\"_" << I->first << "\": \"" << utostr(I->second) << "\"";
2656 }
2657 Out << "}";
2658
2659 Out << "\n}\n";
2660 }
2661
2662 void JSWriter::parseConstant(const std::string& name, const Constant* CV, bool c alculate) {
2663 if (isa<GlobalValue>(CV))
2664 return;
2665 //errs() << "parsing constant " << name << "\n";
2666 // TODO: we repeat some work in both calculate and emit phases here
2667 // FIXME: use the proper optimal alignments
2668 if (const ConstantDataSequential *CDS =
2669 dyn_cast<ConstantDataSequential>(CV)) {
2670 assert(CDS->isString());
2671 if (calculate) {
2672 HeapData *GlobalData = allocateAddress(name);
2673 StringRef Str = CDS->getAsString();
2674 for (unsigned int i = 0; i < Str.size(); i++) {
2675 GlobalData->push_back(Str.data()[i]);
2676 }
2677 }
2678 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
2679 APFloat APF = CFP->getValueAPF();
2680 if (CFP->getType() == Type::getFloatTy(CFP->getContext())) {
2681 if (calculate) {
2682 HeapData *GlobalData = allocateAddress(name);
2683 union flt { float f; unsigned char b[sizeof(float)]; } flt;
2684 flt.f = APF.convertToFloat();
2685 for (unsigned i = 0; i < sizeof(float); ++i) {
2686 GlobalData->push_back(flt.b[i]);
2687 }
2688 }
2689 } else if (CFP->getType() == Type::getDoubleTy(CFP->getContext())) {
2690 if (calculate) {
2691 HeapData *GlobalData = allocateAddress(name);
2692 union dbl { double d; unsigned char b[sizeof(double)]; } dbl;
2693 dbl.d = APF.convertToDouble();
2694 for (unsigned i = 0; i < sizeof(double); ++i) {
2695 GlobalData->push_back(dbl.b[i]);
2696 }
2697 }
2698 } else {
2699 assert(false && "Unsupported floating-point type");
2700 }
2701 } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
2702 if (calculate) {
2703 union { uint64_t i; unsigned char b[sizeof(uint64_t)]; } integer;
2704 integer.i = *CI->getValue().getRawData();
2705 unsigned BitWidth = 64; // CI->getValue().getBitWidth();
2706 assert(BitWidth == 32 || BitWidth == 64);
2707 HeapData *GlobalData = allocateAddress(name);
2708 // assuming compiler is little endian
2709 for (unsigned i = 0; i < BitWidth / 8; ++i) {
2710 GlobalData->push_back(integer.b[i]);
2711 }
2712 }
2713 } else if (isa<ConstantPointerNull>(CV)) {
2714 assert(false && "Unlowered ConstantPointerNull");
2715 } else if (isa<ConstantAggregateZero>(CV)) {
2716 if (calculate) {
2717 unsigned Bytes = DL->getTypeStoreSize(CV->getType());
2718 HeapData *GlobalData = allocateAddress(name);
2719 for (unsigned i = 0; i < Bytes; ++i) {
2720 GlobalData->push_back(0);
2721 }
2722 // FIXME: create a zero section at the end, avoid filling meminit with zer os
2723 }
2724 } else if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) {
2725 if (calculate) {
2726 for (Constant::const_user_iterator UI = CV->user_begin(), UE = CV->user_en d(); UI != UE; ++UI) {
2727 if ((*UI)->getName() == "llvm.used") {
2728 // export the kept-alives
2729 for (unsigned i = 0; i < CA->getNumOperands(); i++) {
2730 const Constant *C = CA->getOperand(i);
2731 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
2732 C = CE->getOperand(0); // ignore bitcasts
2733 }
2734 Exports.push_back(getJSName(C));
2735 }
2736 } else if ((*UI)->getName() == "llvm.global.annotations") {
2737 // llvm.global.annotations can be ignored.
2738 } else {
2739 llvm_unreachable("Unexpected constant array");
2740 }
2741 break; // we assume one use here
2742 }
2743 }
2744 } else if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(CV)) {
2745 if (name == "__init_array_start") {
2746 // this is the global static initializer
2747 if (calculate) {
2748 unsigned Num = CS->getNumOperands();
2749 for (unsigned i = 0; i < Num; i++) {
2750 const Value* C = CS->getOperand(i);
2751 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
2752 C = CE->getOperand(0); // ignore bitcasts
2753 }
2754 GlobalInitializers.push_back(getJSName(C));
2755 }
2756 }
2757 } else if (calculate) {
2758 HeapData *GlobalData = allocateAddress(name);
2759 unsigned Bytes = DL->getTypeStoreSize(CV->getType());
2760 for (unsigned i = 0; i < Bytes; ++i) {
2761 GlobalData->push_back(0);
2762 }
2763 } else {
2764 // Per the PNaCl abi, this must be a packed struct of a very specific type
2765 // https://chromium.googlesource.com/native_client/pnacl-llvm/+/7287c45c13 dc887cebe3db6abfa2f1080186bb97/lib/Transforms/NaCl/FlattenGlobals.cpp
2766 assert(CS->getType()->isPacked());
2767 // This is the only constant where we cannot just emit everything during t he first phase, 'calculate', as we may refer to other globals
2768 unsigned Num = CS->getNumOperands();
2769 unsigned Offset = getRelativeGlobalAddress(name);
2770 unsigned OffsetStart = Offset;
2771 unsigned Absolute = getGlobalAddress(name);
2772 for (unsigned i = 0; i < Num; i++) {
2773 const Constant* C = CS->getOperand(i);
2774 if (isa<ConstantAggregateZero>(C)) {
2775 unsigned Bytes = DL->getTypeStoreSize(C->getType());
2776 Offset += Bytes; // zeros, so just skip
2777 } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
2778 const Value *V = CE->getOperand(0);
2779 unsigned Data = 0;
2780 if (CE->getOpcode() == Instruction::PtrToInt) {
2781 Data = getConstAsOffset(V, Absolute + Offset - OffsetStart);
2782 } else if (CE->getOpcode() == Instruction::Add) {
2783 V = cast<ConstantExpr>(V)->getOperand(0);
2784 Data = getConstAsOffset(V, Absolute + Offset - OffsetStart);
2785 ConstantInt *CI = cast<ConstantInt>(CE->getOperand(1));
2786 Data += *CI->getValue().getRawData();
2787 } else {
2788 CE->dump();
2789 llvm_unreachable("Unexpected constant expr kind");
2790 }
2791 union { unsigned i; unsigned char b[sizeof(unsigned)]; } integer;
2792 integer.i = Data;
2793 assert(Offset+4 <= GlobalData64.size());
2794 for (unsigned i = 0; i < 4; ++i) {
2795 GlobalData64[Offset++] = integer.b[i];
2796 }
2797 } else if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequ ential>(C)) {
2798 assert(CDS->isString());
2799 StringRef Str = CDS->getAsString();
2800 assert(Offset+Str.size() <= GlobalData64.size());
2801 for (unsigned int i = 0; i < Str.size(); i++) {
2802 GlobalData64[Offset++] = Str.data()[i];
2803 }
2804 } else {
2805 C->dump();
2806 llvm_unreachable("Unexpected constant kind");
2807 }
2808 }
2809 }
2810 } else if (isa<ConstantVector>(CV)) {
2811 assert(false && "Unlowered ConstantVector");
2812 } else if (isa<BlockAddress>(CV)) {
2813 assert(false && "Unlowered BlockAddress");
2814 } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
2815 if (name == "__init_array_start") {
2816 // this is the global static initializer
2817 if (calculate) {
2818 const Value *V = CE->getOperand(0);
2819 GlobalInitializers.push_back(getJSName(V));
2820 // is the func
2821 }
2822 } else if (name == "__fini_array_start") {
2823 // nothing to do
2824 } else {
2825 // a global equal to a ptrtoint of some function, so a 32-bit integer for us
2826 if (calculate) {
2827 HeapData *GlobalData = allocateAddress(name);
2828 for (unsigned i = 0; i < 4; ++i) {
2829 GlobalData->push_back(0);
2830 }
2831 } else {
2832 unsigned Data = 0;
2833
2834 // Deconstruct lowered getelementptrs.
2835 if (CE->getOpcode() == Instruction::Add) {
2836 Data = cast<ConstantInt>(CE->getOperand(1))->getZExtValue();
2837 CE = cast<ConstantExpr>(CE->getOperand(0));
2838 }
2839 const Value *V = CE;
2840 if (CE->getOpcode() == Instruction::PtrToInt) {
2841 V = CE->getOperand(0);
2842 }
2843
2844 // Deconstruct getelementptrs.
2845 int64_t BaseOffset;
2846 V = GetPointerBaseWithConstantOffset(V, BaseOffset, *DL);
2847 Data += (uint64_t)BaseOffset;
2848
2849 Data += getConstAsOffset(V, getGlobalAddress(name));
2850 union { unsigned i; unsigned char b[sizeof(unsigned)]; } integer;
2851 integer.i = Data;
2852 unsigned Offset = getRelativeGlobalAddress(name);
2853 assert(Offset+4 <= GlobalData64.size());
2854 for (unsigned i = 0; i < 4; ++i) {
2855 GlobalData64[Offset++] = integer.b[i];
2856 }
2857 }
2858 }
2859 } else if (isa<UndefValue>(CV)) {
2860 assert(false && "Unlowered UndefValue");
2861 } else {
2862 CV->dump();
2863 assert(false && "Unsupported constant kind");
2864 }
2865 }
2866
2867 // nativization
2868
2869 void JSWriter::calculateNativizedVars(const Function *F) {
2870 NativizedVars.clear();
2871
2872 for (Function::const_iterator BI = F->begin(), BE = F->end(); BI != BE; ++BI) {
2873 for (BasicBlock::const_iterator II = BI->begin(), E = BI->end(); II != E; ++ II) {
2874 const Instruction *I = &*II;
2875 if (const AllocaInst *AI = dyn_cast<const AllocaInst>(I)) {
2876 if (AI->getAllocatedType()->isVectorTy()) continue; // we do not nativiz e vectors, we rely on the LLVM optimizer to avoid load/stores on them
2877 if (AI->getAllocatedType()->isAggregateType()) continue; // we do not na tivize aggregates either
2878 // this is on the stack. if its address is never used nor escaped, we ca n nativize it
2879 bool Fail = false;
2880 for (Instruction::const_user_iterator UI = I->user_begin(), UE = I->user _end(); UI != UE && !Fail; ++UI) {
2881 const Instruction *U = dyn_cast<Instruction>(*UI);
2882 if (!U) { Fail = true; break; } // not an instruction, not cool
2883 switch (U->getOpcode()) {
2884 case Instruction::Load: break; // load is cool
2885 case Instruction::Store: {
2886 if (U->getOperand(0) == I) Fail = true; // store *of* it is not co ol; store *to* it is fine
2887 break;
2888 }
2889 default: { Fail = true; break; } // anything that is "not" "cool", i s "not cool"
2890 }
2891 }
2892 if (!Fail) NativizedVars.insert(I);
2893 }
2894 }
2895 }
2896 }
2897
2898 // special analyses
2899
2900 bool JSWriter::canReloop(const Function *F) {
2901 return true;
2902 }
2903
2904 // main entry
2905
2906 void JSWriter::printCommaSeparated(const HeapData data) {
2907 for (HeapData::const_iterator I = data.begin();
2908 I != data.end(); ++I) {
2909 if (I != data.begin()) {
2910 Out << ",";
2911 }
2912 Out << (int)*I;
2913 }
2914 }
2915
2916 void JSWriter::printProgram(const std::string& fname,
2917 const std::string& mName) {
2918 printModule(fname,mName);
2919 }
2920
2921 void JSWriter::printModule(const std::string& fname,
2922 const std::string& mName) {
2923 printModuleBody();
2924 }
2925
2926 bool JSWriter::runOnModule(Module &M) {
2927 TheModule = &M;
2928 DL = &M.getDataLayout();
2929
2930 setupCallHandlers();
2931
2932 printProgram("", "");
2933
2934 return false;
2935 }
2936
2937 char JSWriter::ID = 0;
2938
2939 class CheckTriple : public ModulePass {
2940 public:
2941 static char ID;
2942 CheckTriple() : ModulePass(ID) {}
2943 virtual bool runOnModule(Module &M) {
2944 if (M.getTargetTriple() != "asmjs-unknown-emscripten") {
2945 prettyWarning() << "incorrect target triple '" << M.getTargetTriple() << " ' (did you use emcc/em++ on all source files and not clang directly?)\n";
2946 }
2947 return false;
2948 }
2949 };
2950
2951 char CheckTriple::ID;
2952
2953 Pass *createCheckTriplePass() {
2954 return new CheckTriple();
2955 }
2956
2957 //===----------------------------------------------------------------------===//
2958 // External Interface declaration
2959 //===----------------------------------------------------------------------===//
2960
2961 bool JSTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
2962 raw_pwrite_stream &o,
2963 CodeGenFileType FileType,
2964 bool DisableVerify,
2965 AnalysisID StartAfter,
2966 AnalysisID StopAfter) {
2967 assert(FileType == TargetMachine::CGFT_AssemblyFile);
2968
2969 PM.add(createCheckTriplePass());
2970 PM.add(createExpandInsertExtractElementPass());
2971 PM.add(createExpandI64Pass());
2972
2973 CodeGenOpt::Level OptLevel = getOptLevel();
2974
2975 // When optimizing, there shouldn't be any opportunities for SimplifyAllocas
2976 // because the regular optimizer should have taken them all (GVN, and possibly
2977 // also SROA).
2978 if (OptLevel == CodeGenOpt::None)
2979 PM.add(createEmscriptenSimplifyAllocasPass());
2980
2981 PM.add(new JSWriter(o, OptLevel));
2982
2983 return false;
2984 }
OLDNEW
« no previous file with comments | « lib/Target/JSBackend/JS.h ('k') | lib/Target/JSBackend/JSTargetMachine.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698