diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-07-16 20:57:52 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-07-16 20:57:52 -0700 |
commit | ab56efe76e94a0508d3983e9430e2aa18b1e2667 (patch) | |
tree | fa09903a81b61b1dbfb2f6e148e3d23e78b87607 | |
parent | 7cfc95807c12a3351c640ad5dde954cba1d3ea4d (diff) |
refactor and simplify library loading in order to make type info available there
-rw-r--r-- | src/compiler.js | 12 | ||||
-rw-r--r-- | src/jsifier.js | 15 | ||||
-rw-r--r-- | src/library.js | 82 | ||||
-rw-r--r-- | src/library_browser.js | 2 | ||||
-rw-r--r-- | src/library_gl.js | 2 | ||||
-rw-r--r-- | src/library_sdl.js | 2 | ||||
-rw-r--r-- | src/modules.js | 16 | ||||
-rw-r--r-- | src/runtime.js | 85 |
8 files changed, 109 insertions, 107 deletions
diff --git a/src/compiler.js b/src/compiler.js index 4fe68e88..8cb023d9 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -56,7 +56,7 @@ load('parseTools.js'); load('intertyper.js'); load('analyzer.js'); load('jsifier.js'); -load('runtime.js'); +eval(processMacros(preprocess(read('runtime.js')))); //=============================== // Main @@ -74,13 +74,5 @@ do { // Do it -var inter = intertyper(lines); - -// Load library, with preprocessing and macros. Must be done after intertyper, so we know if we have debug info or not -for (suffix in set('', '_sdl', '_gl', '_browser')) { - eval(processMacros(preprocess(read('library' + suffix + '.js'), CONSTANTS))); -} -LibraryManager.init(); - -JSify(analyzer(inter)); +JSify(analyzer(intertyper(lines))); diff --git a/src/jsifier.js b/src/jsifier.js index dfd1f08d..b712e7ae 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -7,10 +7,11 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { // Add additional necessary items for the main pass if (mainPass) { + LibraryManager.load(); var libFuncsToInclude; if (INCLUDE_FULL_LIBRARY) { assert(!BUILD_AS_SHARED_LIB, 'Cannot have both INCLUDE_FULL_LIBRARY and BUILD_AS_SHARED_LIB set.') - libFuncsToInclude = keys(Library); + libFuncsToInclude = keys(LibraryManager.library); } else { libFuncsToInclude = ['memset', 'malloc', 'free']; } @@ -248,7 +249,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { if (BUILD_AS_SHARED_LIB) { // Shared libraries reuse the runtime of their parents. item.JS = ''; - } else if (Library.hasOwnProperty(shortident)) { + } else if (LibraryManager.library.hasOwnProperty(shortident)) { function addFromLibrary(ident) { if (ident in addedLibraryItems) return ''; // Don't replace implemented functions with library ones (which can happen when we add dependencies). @@ -256,12 +257,12 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { if (('_' + ident) in moduleFunctions) return ''; addedLibraryItems[ident] = true; - var snippet = Library[ident]; + var snippet = LibraryManager.library[ident]; var redirectedIdent = null; - var deps = Library[ident + '__deps'] || []; + var deps = LibraryManager.library[ident + '__deps'] || []; if (typeof snippet === 'string') { - if (Library[snippet]) { + if (LibraryManager.library[snippet]) { // Redirection for aliases. We include the parent, and at runtime make ourselves equal to it. // This avoid having duplicate functions with identical content. redirectedIdent = snippet; @@ -291,7 +292,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { } var postsetId = ident + '__postset'; - var postset = Library[postsetId]; + var postset = LibraryManager.library[postsetId]; if (postset && !addedLibraryItems[postsetId]) { addedLibraryItems[postsetId] = true; ret.push({ @@ -301,7 +302,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { } if (redirectedIdent) { - deps = deps.concat(Library[redirectedIdent + '__deps'] || []); + deps = deps.concat(LibraryManager.library[redirectedIdent + '__deps'] || []); } // $ident's are special, we do not prefix them with a '_'. if (ident[0] === '$') { diff --git a/src/library.js b/src/library.js index 21078c3c..c900c90d 100644 --- a/src/library.js +++ b/src/library.js @@ -13,7 +13,7 @@ // object. For convenience, the short name appears here. Note that if you add a // new function with an '_', it will not be found. -var Library = { +LibraryManager.library = { // ========================================================================== // stdio.h // ========================================================================== @@ -1801,19 +1801,10 @@ var Library = { return time1 - time0; }, - __tm_struct_layout: Runtime.generateStructInfo([ - ['i32', 'tm_sec'], - ['i32', 'tm_min'], - ['i32', 'tm_hour'], - ['i32', 'tm_mday'], - ['i32', 'tm_mon'], - ['i32', 'tm_year'], - ['i32', 'tm_wday'], - ['i32', 'tm_yday'], - ['i32', 'tm_isdst'], - ['i32', 'tm_gmtoff'], - ['i8*', 'tm_zone'], - ]), + __tm_struct_layout: Runtime.generateStructInfo( + ['tm_sec', 'tm_min', 'tm_hour', 'tm_mday', 'tm_mon', 'tm_year', 'tm_wday', 'tm_yday', 'tm_isdst', 'tm_gmtoff', 'tm_zone'], + '%struct.tm' + ), // Statically allocated time struct. __tm_current: 0, // Statically allocated timezone strings. @@ -2290,66 +2281,3 @@ var Library = { } }; - -// 'Runtime' functions that need preprocessor parsing like library functions - -// Converts a value we have as signed, into an unsigned value. For -// example, -1 in int32 would be a very large number as unsigned. -function unSign(value, bits, ignore, sig) { - if (value >= 0) { -#if CHECK_SIGNS - if (!ignore) CorrectionsMonitor.note('UnSign', 1, sig); -#endif - return value; - } -#if CHECK_SIGNS - if (!ignore) CorrectionsMonitor.note('UnSign', 0, sig); -#endif - return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts - : Math.pow(2, bits) + value; - // TODO: clean up previous line -} - -// Converts a value we have as unsigned, into a signed value. For -// example, 200 in a uint8 would be a negative number. -function reSign(value, bits, ignore, sig) { - if (value <= 0) { -#if CHECK_SIGNS - if (!ignore) CorrectionsMonitor.note('ReSign', 1, sig); -#endif - return value; - } - var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 - : Math.pow(2, bits-1); -#if CHECK_SIGNS - var noted = false; -#endif - if (value >= half) { -#if CHECK_SIGNS - if (!ignore) { - CorrectionsMonitor.note('ReSign', 0, sig); - noted = true; - } -#endif - value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts - } -#if CHECK_SIGNS - // If this is a 32-bit value, then it should be corrected at this point. And, - // without CHECK_SIGNS, we would just do the |0 shortcut, so check that that - // would indeed give the exact same result. - if (bits === 32 && (value|0) !== value && typeof value !== 'boolean') { - if (!ignore) { - CorrectionsMonitor.note('ReSign', 0, sig); - noted = true; - } - } - if (!noted) CorrectionsMonitor.note('ReSign', 1, sig); -#endif - return value; -} - -// Just a stub. We don't care about noting compile-time corrections. But they are called. -var CorrectionsMonitor = { - note: function(){} -}; - diff --git a/src/library_browser.js b/src/library_browser.js index d24854f9..c4d1d768 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -1,6 +1,6 @@ // Utilities for browser environments -mergeInto(Library, { +mergeInto(LibraryManager.library, { $Browser: { // Given binary data for an image, in a format like PNG or JPG, we convert it // to flat pixel data. We do so using the browser's native code. diff --git a/src/library_gl.js b/src/library_gl.js index 9d5f14fa..20197141 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -89,5 +89,5 @@ var LibraryGL = { }); }); -mergeInto(Library, LibraryGL); +mergeInto(LibraryManager.library, LibraryGL); diff --git a/src/library_sdl.js b/src/library_sdl.js index 6c70f9f6..57a98e64 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -81,7 +81,7 @@ // solution here is to have a singleIteration() function which is a single loop // iteration, and from JS to do something like setInterval(_singleIteration, 1/30) -mergeInto(Library, { +mergeInto(LibraryManager.library, { $SDL__deps: ['$Browser'], $SDL: { defaults: { diff --git a/src/modules.js b/src/modules.js index f1f5f487..dc4a296d 100644 --- a/src/modules.js +++ b/src/modules.js @@ -171,22 +171,26 @@ var Functions = { }; var LibraryManager = { - ready: false, + library: null, - init: function() { - this.ready = true; + load: function() { + assert(!this.library); + + for (suffix in set('', '_sdl', '_gl', '_browser')) { + eval(processMacros(preprocess(read('library' + suffix + '.js'), CONSTANTS))); + } }, // Given an ident, see if it is an alias for something, and so forth, returning // the earliest ancestor (the root) getRootIdent: function(ident) { - if (!this.ready) return null; - var ret = Library[ident]; + if (!this.library) return null; + var ret = LibraryManager.library[ident]; if (!ret) return null; var last = ident; while (typeof ret === 'string') { last = ret; - ret = Library[ret]; + ret = LibraryManager.library[ret]; } return last; } diff --git a/src/runtime.js b/src/runtime.js index 4246ad1c..8acb9260 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -160,15 +160,30 @@ Runtime = { // ] // ) will return // { field1: 0, field2: 4 } (depending on QUANTUM_SIZE) - generateStructInfo: function(struct) { + // + // You can optionally provide a type name as a second parameter. In that + // case, you do not need to provide the types (but you do still need to + // provide the names, since they are not present in the .ll), for example, + // generateStructInfo(['field1', 'field2'], '%struct.UserStructType'); + // (Note that you will need the full %struct.* name here at compile time, + // but not at runtime. The reason is that during compilation we cannot simplify + // the type names yet.) + generateStructInfo: function(struct, typeName) { var fields = struct.map(function(item) { return item[0] }); - var type = { fields: fields }; - var alignment = Runtime.calculateStructAlignment(type); + var type, alignment; + if (typeName) { + type = Types.types[typeName]; + if (!type) return null; + alignment = type.flatIndexes; + } else { + var type = { fields: fields }; + alignment = Runtime.calculateStructAlignment(type); + } var ret = { __size__: type.flatSize }; struct.forEach(function(item, i) { - ret[item[1]] = alignment[i]; + ret[typeof item === 'string' ? item : item[1]] = alignment[i]; }); return ret; } @@ -193,3 +208,65 @@ function getRuntime() { return ret + ' __dummy__: 0\n}\n'; } +// Additional runtime elements, that need preprocessing + +// Converts a value we have as signed, into an unsigned value. For +// example, -1 in int32 would be a very large number as unsigned. +function unSign(value, bits, ignore, sig) { + if (value >= 0) { +#if CHECK_SIGNS + if (!ignore) CorrectionsMonitor.note('UnSign', 1, sig); +#endif + return value; + } +#if CHECK_SIGNS + if (!ignore) CorrectionsMonitor.note('UnSign', 0, sig); +#endif + return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts + : Math.pow(2, bits) + value; + // TODO: clean up previous line +} + +// Converts a value we have as unsigned, into a signed value. For +// example, 200 in a uint8 would be a negative number. +function reSign(value, bits, ignore, sig) { + if (value <= 0) { +#if CHECK_SIGNS + if (!ignore) CorrectionsMonitor.note('ReSign', 1, sig); +#endif + return value; + } + var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 + : Math.pow(2, bits-1); +#if CHECK_SIGNS + var noted = false; +#endif + if (value >= half) { +#if CHECK_SIGNS + if (!ignore) { + CorrectionsMonitor.note('ReSign', 0, sig); + noted = true; + } +#endif + value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts + } +#if CHECK_SIGNS + // If this is a 32-bit value, then it should be corrected at this point. And, + // without CHECK_SIGNS, we would just do the |0 shortcut, so check that that + // would indeed give the exact same result. + if (bits === 32 && (value|0) !== value && typeof value !== 'boolean') { + if (!ignore) { + CorrectionsMonitor.note('ReSign', 0, sig); + noted = true; + } + } + if (!noted) CorrectionsMonitor.note('ReSign', 1, sig); +#endif + return value; +} + +// Just a stub. We don't care about noting compile-time corrections. But they are called. +var CorrectionsMonitor = { + note: function(){} +}; + |