aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemar4
-rwxr-xr-xemcc26
-rw-r--r--src/analyzer.js60
-rw-r--r--src/library.js12
-rw-r--r--src/parseTools.js24
-rw-r--r--src/runtime.js10
-rw-r--r--src/utility.js2
-rw-r--r--system/include/libcxx/__locale15
-rw-r--r--system/lib/libcxx/locale.cpp13
-rw-r--r--system/lib/libcxx/symbols1
-rw-r--r--tests/cases/legalizer_ta2.ll15
-rw-r--r--tests/cases/legalizer_ta2.txt1
-rw-r--r--tests/cases/unaligneddouble.ll24
-rw-r--r--tests/openjpeg/CMakeLists.txt2
-rwxr-xr-xtests/runner.py177
-rw-r--r--tools/shared.py62
16 files changed, 373 insertions, 75 deletions
diff --git a/emar b/emar
index 49d995bd..e64cd8b9 100755
--- a/emar
+++ b/emar
@@ -12,11 +12,11 @@ from tools import shared
DEBUG = os.environ.get('EMCC_DEBUG')
-newargs = [shared.LLVM_LINK] + sys.argv[3:] + ['-o='+sys.argv[2]]
+newargs = [shared.LLVM_AR] + sys.argv[1:]
if DEBUG:
print >> sys.stderr, 'emar:', sys.argv, ' ==> ', newargs
if len(newargs) > 2:
- os.execvp(shared.LLVM_LINK, newargs)
+ os.execvp(shared.LLVM_AR, newargs)
diff --git a/emcc b/emcc
index b8e2489c..b59dd36a 100755
--- a/emcc
+++ b/emcc
@@ -239,7 +239,8 @@ if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += EMMAKEN_CFLAGS.split(' ')
# ---------------- Utilities ---------------
SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc')
-BITCODE_SUFFIXES = ('.bc', '.o', '.a', '.dylib', '.so', '.dll')
+BITCODE_SUFFIXES = ('.bc', '.o')
+SHAREDLIB_SUFFIXES = ('.dylib', '.so', '.dll')
ASSEMBLY_SUFFIXES = ('.ll',)
def unsuffixed(name):
@@ -377,7 +378,7 @@ try:
for i in range(len(newargs)): # find input files XXX this a simple heuristic. we should really analyze based on a full understanding of gcc params,
# right now we just assume that what is left contains no more |-x OPT| things
arg = newargs[i]
- if arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + ASSEMBLY_SUFFIXES): # we already removed -o <target>, so all these should be inputs
+ if arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + SHAREDLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
newargs[i] = ''
if os.path.exists(arg):
if arg.endswith(SOURCE_SUFFIXES):
@@ -425,11 +426,14 @@ try:
if DEBUG: print >> sys.stderr, 'emcc: compiling to bitcode'
+ temp_files = []
+
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
for input_file in input_files:
if input_file.endswith(SOURCE_SUFFIXES):
if DEBUG: print >> sys.stderr, 'emcc: compiling source file: ', input_file
output_file = in_temp(unsuffixed_basename(input_file) + '.o')
+ temp_files.append(output_file)
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
if DEBUG: print >> sys.stderr, "emcc running:", call, ' '.join(args)
Popen([call] + args).communicate() # let compiler frontend print directly, so colors are saved (PIPE kills that)
@@ -439,13 +443,22 @@ try:
else: # bitcode
if input_file.endswith(BITCODE_SUFFIXES):
if DEBUG: print >> sys.stderr, 'emcc: copying bitcode file: ', input_file
- shutil.copyfile(input_file, in_temp(unsuffixed_basename(input_file) + '.o'))
+ temp_file = in_temp(unsuffixed_basename(input_file) + '.o')
+ shutil.copyfile(input_file, temp_file)
+ temp_files.append(temp_file)
+ elif input_file.endswith(SHAREDLIB_SUFFIXES) or shared.Building.is_ar(input_file):
+ if DEBUG: print >> sys.stderr, 'emcc: copying library file: ', input_file
+ temp_file = in_temp(os.path.basename(input_file))
+ shutil.copyfile(input_file, temp_file)
+ temp_files.append(temp_file)
else: #.ll
if not LEAVE_INPUTS_RAW:
# Note that by assembling the .ll file, then disassembling it later, we will
# remove annotations which is a good thing for compilation time
if DEBUG: print >> sys.stderr, 'emcc: assembling assembly file: ', input_file
- shared.Building.llvm_as(input_file, in_temp(unsuffixed_basename(input_file) + '.o'))
+ temp_file = in_temp(unsuffixed_basename(input_file) + '.o')
+ shared.Building.llvm_as(input_file, temp_file)
+ temp_files.append(temp_file)
# If we were just asked to generate bitcode, stop there
if final_suffix not in ['js', 'html']:
@@ -461,11 +474,10 @@ try:
assert not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv)
# We have a specified target (-o <target>), which is not JavaScript or HTML, and
# we have multiple files: Link them TODO: llvm link-time opts?
- ld_args = map(lambda input_file: in_temp(unsuffixed_basename(input_file) + '.o'), input_files) + \
- ['-o', specified_target]
+ ld_args = temp_files + ['-b', specified_target]
#[arg.split('-Wl,')[1] for arg in filter(lambda arg: arg.startswith('-Wl,'), sys.argv)]
if DEBUG: print >> sys.stderr, 'emcc: link: ' + str(ld_args)
- Popen([shared.LLVM_LINK] + ld_args).communicate()
+ Popen([shared.LLVM_LD, '-disable-opt'] + ld_args).communicate()
exit(0)
## Continue on to create JavaScript
diff --git a/src/analyzer.js b/src/analyzer.js
index e1f2f6c1..729d4607 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -169,6 +169,15 @@ function analyzer(data, sidePass) {
item[slot] = { intertype: 'value', ident: tempIdent, type: item[slot].type };
return i+1;
}
+ function removeAndAdd(lines, i, toAdd) {
+ var item = lines[i];
+ var interp = getInterp(lines, i, toAdd.length);
+ for (var k = 0; k < toAdd.length; k++) {
+ toAdd[k].lineNum = item.lineNum + (k*interp);
+ }
+ Array.prototype.splice.apply(lines, [i, 1].concat(toAdd));
+ return toAdd.length;
+ }
// Assuming we will replace the item at line i, with num items, returns
// the right factor to multiply line numbers by so that they fit in between
// the removed line and the line after it
@@ -184,16 +193,15 @@ function analyzer(data, sidePass) {
if (item.intertype == 'store') {
if (isIllegalType(item.valueType)) {
dprint('legalizer', 'Legalizing store at line ' + item.lineNum);
+ var toAdd = [];
bits = getBits(item.valueType);
i = unfold(label.lines, i, item, 'value');
- var interp = getInterp(label.lines, i, Math.ceil(bits/32));
- label.lines.splice(i, 1);
var elements;
elements = getLegalVars(item.value.ident, bits);
var j = 0;
elements.forEach(function(element) {
var tempVar = '$st$' + i + '$' + j;
- label.lines.splice(i+j*2, 0, {
+ toAdd.push({
intertype: 'getelementptr',
assignTo: tempVar,
ident: item.pointer.ident,
@@ -203,10 +211,9 @@ function analyzer(data, sidePass) {
{ intertype: 'value', ident: '0', type: 'i32' },
{ intertype: 'value', ident: j.toString(), type: 'i32' }
],
- lineNum: item.lineNum + (j*interp)
});
var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits
- label.lines.splice(i+j*2+1, 0, {
+ toAdd.push({
intertype: 'store',
valueType: actualSizeType,
value: { intertype: 'value', ident: element.ident, type: actualSizeType },
@@ -214,12 +221,11 @@ function analyzer(data, sidePass) {
ident: tempVar,
pointerType: actualSizeType + '*',
align: item.align,
- lineNum: item.lineNum + ((j+0.5)*interp)
});
j++;
});
Types.needAnalysis['[0 x i32]'] = 0;
- i += j*2;
+ i += removeAndAdd(label.lines, i, toAdd);
continue;
}
} else if (item.assignTo) {
@@ -267,6 +273,38 @@ function analyzer(data, sidePass) {
i += j*2;
continue;
}
+ break;
+ }
+ case 'phi': {
+ if (isIllegalType(value.type)) {
+ dprint('legalizer', 'Legalizing phi at line ' + item.lineNum);
+ bits = getBits(value.type);
+ var toAdd = [];
+ var elements = getLegalVars(item.assignTo, bits);
+ var j = 0;
+ elements.forEach(function(element) {
+ toAdd.push({
+ intertype: 'phi',
+ assignTo: element.ident,
+ type: 'i' + element.bits,
+ params: value.params.map(function(param) {
+ return {
+ intertype: 'phiparam',
+ label: param.label,
+ value: { // TODO: unfolding
+ intertype: 'value',
+ ident: param.value.ident + '$' + j,
+ type: 'i' + element.bits,
+ }
+ };
+ })
+ });
+ j++;
+ });
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
+ break;
}
case 'mathop': {
if (isIllegalType(value.type)) {
@@ -412,14 +450,10 @@ function analyzer(data, sidePass) {
legalValue.assignTo = item.assignTo;
toAdd.push(legalValue);
}
- var interp = getInterp(label.lines, i, toAdd.length);
- for (var k = 0; k < toAdd.length; k++) {
- toAdd[k].lineNum = item.lineNum + (k*interp);
- }
- Array.prototype.splice.apply(label.lines, [i, 1].concat(toAdd));
- i += toAdd.length;
+ i += removeAndAdd(label.lines, i, toAdd);
continue;
}
+ break;
}
}
}
diff --git a/src/library.js b/src/library.js
index 6385507c..86c499a7 100644
--- a/src/library.js
+++ b/src/library.js
@@ -4392,7 +4392,7 @@ LibraryManager.library = {
__cxa_free_exception: function(ptr) {
return _free(ptr);
},
- __cxa_throw__deps: ['llvm_eh_exception'],
+ __cxa_throw__deps: ['llvm_eh_exception', '_ZSt18uncaught_exceptionv'],
__cxa_throw: function(ptr, type, destructor) {
#if EXCEPTION_DEBUG
print('Compiled code throwing an exception, ' + [ptr,type,destructor] + ', at ' + new Error().stack);
@@ -4400,6 +4400,11 @@ LibraryManager.library = {
{{{ makeSetValue('_llvm_eh_exception.buf', '0', 'ptr', 'void*') }}}
{{{ makeSetValue('_llvm_eh_exception.buf', QUANTUM_SIZE, 'type', 'void*') }}}
{{{ makeSetValue('_llvm_eh_exception.buf', 2 * QUANTUM_SIZE, 'destructor', 'void*') }}}
+ if (!("uncaught_exception" in __ZSt18uncaught_exceptionv)) {
+ __ZSt18uncaught_exceptionv.uncaught_exception = 1;
+ } else {
+ __ZSt18uncaught_exceptionv.uncaught_exception++;
+ }
throw ptr;
},
__cxa_rethrow__deps: ['llvm_eh_exception', '__cxa_end_catch'],
@@ -4425,7 +4430,9 @@ LibraryManager.library = {
_Unwind_Resume_or_Rethrow: function(ptr) {
throw ptr;
},
+ __cxa_begin_catch__deps: ['_ZSt18uncaught_exceptionv'],
__cxa_begin_catch: function(ptr) {
+ __ZSt18uncaught_exceptionv.uncaught_exception--;
return ptr;
},
__cxa_end_catch__deps: ['llvm_eh_exception', '__cxa_free_exception'],
@@ -4455,6 +4462,9 @@ LibraryManager.library = {
__cxa_get_exception_ptr: function(ptr) {
return ptr;
},
+ _ZSt18uncaught_exceptionv: function() { // std::uncaught_exception()
+ return !!__ZSt18uncaught_exceptionv.uncaught_exception;
+ },
__cxa_call_unexpected: function(exception) {
ABORT = true;
diff --git a/src/parseTools.js b/src/parseTools.js
index a5752e67..3cc17cc4 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -962,32 +962,32 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
if (DOUBLE_MODE == 1 && USE_TYPED_ARRAYS == 2 && type == 'double') {
return '(tempDoubleF64[0]=' + value + ',' +
- makeSetValue(ptr, pos, 'tempDoubleI32[0]', 'i32', noNeedFirst, ignore, align) + ',' +
- makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempDoubleI32[1]', 'i32', noNeedFirst, ignore, align) + ')';
+ makeSetValue(ptr, pos, 'tempDoubleI32[0]', 'i32', noNeedFirst, ignore, align, noSafe, ',') + ',' +
+ makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempDoubleI32[1]', 'i32', noNeedFirst, ignore, align, noSafe, ',') + ')';
}
- if (USE_TYPED_ARRAYS == 2 && align) {
- // Alignment is important here. May need to split this up
+ var needSplitting = isIntImplemented(type) && !isPowerOfTwo(getBits(type)); // an unnatural type like i24
+ if (USE_TYPED_ARRAYS == 2 && (align || needSplitting)) {
+ // Alignment is important here, or we need to split this up for other reasons.
var bytes = Runtime.getNativeTypeSize(type);
- if (bytes > align) {
+ if (bytes > align || needSplitting) {
var ret = '';
if (isIntImplemented(type)) {
if (bytes == 4 && align == 2) {
// Special case that we can optimize
ret += 'tempBigInt=' + value + sep;
ret += makeSetValue(ptr, pos, 'tempBigInt&0xffff', 'i16', noNeedFirst, ignore, 2) + sep;
- ret += makeSetValue(ptr, getFastValue(pos, '+', 2), 'tempBigInt>>16', 'i16', noNeedFirst, ignore, 2) + sep;
- } else if (bytes <= 4) {
+ ret += makeSetValue(ptr, getFastValue(pos, '+', 2), 'tempBigInt>>16', 'i16', noNeedFirst, ignore, 2);
+ } else if (bytes != 8) {
ret += 'tempBigInt=' + value + sep;
for (var i = 0; i < bytes; i++) {
- ret += makeSetValue(ptr, getFastValue(pos, '+', i), 'tempBigInt&0xff', 'i8', noNeedFirst, ignore, 1) + sep;
- if (i < bytes-1) ret += 'tempBigInt>>=8' + sep;
+ ret += makeSetValue(ptr, getFastValue(pos, '+', i), 'tempBigInt&0xff', 'i8', noNeedFirst, ignore, 1);
+ if (i < bytes-1) ret += sep + 'tempBigInt>>=8' + sep;
}
- } else {
- assert(bytes == 8);
+ } else { // bytes == 8, specific optimization
ret += 'tempPair=' + ensureI64_1(value) + sep;
ret += makeSetValue(ptr, pos, 'tempPair[0]', 'i32', noNeedFirst, ignore, align) + sep;
- ret += makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempPair[1]', 'i32', noNeedFirst, ignore, align) + sep;
+ ret += makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempPair[1]', 'i32', noNeedFirst, ignore, align);
}
} else {
ret += makeSetValue('tempDoublePtr', 0, value, type, noNeedFirst, ignore, 8) + sep;
diff --git a/src/runtime.js b/src/runtime.js
index 190260e6..b5663045 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -185,8 +185,14 @@ var Runtime = {
"%float": 4,
"%double": 8
}['%'+type]; // add '%' since float and double confuse Closure compiler as keys, and also spidermonkey as a compiler will remove 's from '_i8' etc
- if (!size && type[type.length-1] == '*') {
- size = Runtime.QUANTUM_SIZE; // A pointer
+ if (!size) {
+ if (type[type.length-1] == '*') {
+ size = Runtime.QUANTUM_SIZE; // A pointer
+ } else if (type[0] == 'i') {
+ var bits = parseInt(type.substr(1));
+ assert(bits % 8 == 0);
+ size = bits/8;
+ }
}
return size;
},
diff --git a/src/utility.js b/src/utility.js
index 5ddccfd4..31eff100 100644
--- a/src/utility.js
+++ b/src/utility.js
@@ -21,7 +21,7 @@ function dump(item) {
ret.push(i + ': [?]');
}
}
- return lineify(ret.join(', '));
+ return ret.join(',\n');
}
}
diff --git a/system/include/libcxx/__locale b/system/include/libcxx/__locale
index f63815c3..7b7cfcd7 100644
--- a/system/include/libcxx/__locale
+++ b/system/include/libcxx/__locale
@@ -330,8 +330,21 @@ public:
static const mask punct = _PUNCT;
static const mask xdigit = _HEX;
static const mask blank = _BLANK;
+#elif defined( EMSCRIPTEN )
+ #define _ISbit(bit) ((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8))
+ typedef __uint16_t mask;
+ static const mask upper = _ISbit( 0 );
+ static const mask lower = _ISbit( 1 );
+ static const mask alpha = _ISbit( 2 );
+ static const mask digit = _ISbit( 3 );
+ static const mask xdigit = _ISbit( 4 );
+ static const mask space = _ISbit( 5 );
+ static const mask print = _ISbit( 6 );
+ static const mask blank = _ISbit( 8 );
+ static const mask cntrl = _ISbit( 9 );
+ static const mask punct = _ISbit( 10 );
#else // __GLIBC__ || _WIN32
-#if defined(__APPLE__) || defined(EMSCRIPTEN)
+#if defined(__APPLE__)
typedef __uint32_t mask;
#elif __FreeBSD__
typedef unsigned long mask;
diff --git a/system/lib/libcxx/locale.cpp b/system/lib/libcxx/locale.cpp
index 388660d2..4675fec3 100644
--- a/system/lib/libcxx/locale.cpp
+++ b/system/lib/libcxx/locale.cpp
@@ -909,6 +909,11 @@ ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault,
return low;
}
+// XXX Emscripten define local table
+extern "C" const unsigned short ** __ctype_b_loc();
+extern "C" const int ** __ctype_tolower_loc();
+extern "C" const int ** __ctype_toupper_loc();
+
const ctype<char>::mask*
ctype<char>::classic_table() _NOEXCEPT
{
@@ -918,6 +923,8 @@ ctype<char>::classic_table() _NOEXCEPT
return __cloc()->__ctype_b;
// This is assumed to be safe, which is a nonsense assumption because we're
// going to end up dereferencing it later...
+#elif defined(EMSCRIPTEN)
+ return *__ctype_b_loc();
#else
return NULL;
#endif
@@ -931,6 +938,8 @@ ctype<char>::__classic_lower_table() _NOEXCEPT
return _DefaultRuneLocale.__maplower;
#elif defined(__GLIBC__)
return __cloc()->__ctype_tolower;
+#elif defined(EMSCRIPTEN)
+ return *__ctype_tolower_loc();
#else
return NULL;
#endif
@@ -943,6 +952,8 @@ ctype<char>::__classic_upper_table() _NOEXCEPT
return _DefaultRuneLocale.__mapupper;
#elif defined(__GLIBC__)
return __cloc()->__ctype_toupper;
+#elif defined(EMSCRIPTEN)
+ return *__ctype_toupper_loc();
#else
return NULL;
#endif
@@ -1041,7 +1052,7 @@ ctype_byname<wchar_t>::do_is(mask m, char_type c) const
#ifdef _LIBCPP_WCTYPE_IS_MASK
return static_cast<bool>(iswctype_l(c, m, __l));
#else
- // FIXME: This is broken for things that test more than one flag.
+ // FIXME: This is broken for things that test more than one flag.
if (m & space && !iswspace_l(c, __l)) return false;
if (m & print && !iswprint_l(c, __l)) return false;
if (m & cntrl && !iswcntrl_l(c, __l)) return false;
diff --git a/system/lib/libcxx/symbols b/system/lib/libcxx/symbols
index 0cea51cb..23d4a7a4 100644
--- a/system/lib/libcxx/symbols
+++ b/system/lib/libcxx/symbols
@@ -2577,7 +2577,6 @@
T _ZSt17current_exceptionv
T _ZSt17rethrow_exceptionSt13exception_ptr
C _ZSt18make_exception_ptrINSt3__112future_errorEESt13exception_ptrT_
- T _ZSt18uncaught_exceptionv
D _ZSt7nothrow
D _ZTCNSt3__110istrstreamE0_NS_13basic_istreamIcNS_11char_traitsIcEEEE
D _ZTCNSt3__110ostrstreamE0_NS_13basic_ostreamIcNS_11char_traitsIcEEEE
diff --git a/tests/cases/legalizer_ta2.ll b/tests/cases/legalizer_ta2.ll
index a877c683..67cd9feb 100644
--- a/tests/cases/legalizer_ta2.ll
+++ b/tests/cases/legalizer_ta2.ll
@@ -101,6 +101,21 @@ entry:
store i80 %loaded.short, i80* bitcast ([300 x i8]* @globaliz to i80*), align 4
call i32 (i8*)* @puts(i8* bitcast ([300 x i8]* @globaliz to i8*))
+; phi
+ %if = trunc i104 %ander to i1
+ %first = trunc i104 %xored to i88
+ br i1 %if, label %a17, label %a26
+
+a17:
+ %second = trunc i104 %loaded to i88
+ br label %a26
+
+a26:
+ %a27 = phi i88 [ %first, %entry ], [ %second, %a17 ]
+ store i104 0, i104* %bundled, align 4 ; wipe it out
+ store i88 %a27, i88* bitcast ([300 x i8]* @globaliz to i88*), align 4
+ call i32 (i8*)* @puts(i8* bitcast ([300 x i8]* @globaliz to i8*))
+
ret i32 1
}
diff --git a/tests/cases/legalizer_ta2.txt b/tests/cases/legalizer_ta2.txt
index e05a4816..e25076e6 100644
--- a/tests/cases/legalizer_ta2.txt
+++ b/tests/cases/legalizer_ta2.txt
@@ -15,3 +15,4 @@ hellon worod
hello, war`d
hello, wor-d
hello, wor
+hello, worl
diff --git a/tests/cases/unaligneddouble.ll b/tests/cases/unaligneddouble.ll
new file mode 100644
index 00000000..22b92741
--- /dev/null
+++ b/tests/cases/unaligneddouble.ll
@@ -0,0 +1,24 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ %doub = alloca double, align 4
+ store i32 0, i32* %retval
+ %0 = bitcast double* %doub to i32
+ %1 = uitofp i32 %0 to double
+ store double %1, double* %doub, align 1
+ store double %1, double* %doub, align 2
+ store double %1, double* %doub, align 4
+ store double %1, double* %doub, align 8
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32]
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
diff --git a/tests/openjpeg/CMakeLists.txt b/tests/openjpeg/CMakeLists.txt
index 52150f5f..d8671fed 100644
--- a/tests/openjpeg/CMakeLists.txt
+++ b/tests/openjpeg/CMakeLists.txt
@@ -22,6 +22,8 @@ STRING(TOLOWER ${OPENJPEG_NAMESPACE} OPENJPEG_LIBRARY_NAME)
PROJECT(${OPENJPEG_NAMESPACE} C)
+include(CMakeDetermineSystem)
+
# Do full dependency headers.
INCLUDE_REGULAR_EXPRESSION("^.*$")
diff --git a/tests/runner.py b/tests/runner.py
index ea7a72f4..b8927332 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -260,11 +260,13 @@ process(sys.argv[1])
if self.library_cache is not None:
if cache and self.library_cache.get(cache_name):
print >> sys.stderr, '<load build from cache> ',
- bc_file = os.path.join(output_dir, 'lib' + name + '.bc')
- f = open(bc_file, 'wb')
- f.write(self.library_cache[cache_name])
- f.close()
- return bc_file
+ generated_libs = []
+ for bc_file in self.library_cache[cache_name]:
+ f = open(bc_file, 'wb')
+ f.write(self.library_cache[cache_name][bc_file])
+ f.close()
+ generated_libs.append(bc_file)
+ return generated_libs
print >> sys.stderr, '<building and saving into cache> ',
@@ -917,6 +919,46 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
'''
self.do_run(src, '*1 2*')
+ def test_multiply_defined_symbols(self):
+ a1 = "int f() { return 1; }"
+ a1_name = os.path.join(self.get_dir(), 'a1.c')
+ open(a1_name, 'w').write(a1)
+ a2 = "void x() {}"
+ a2_name = os.path.join(self.get_dir(), 'a2.c')
+ open(a2_name, 'w').write(a2)
+ b1 = "int f() { return 2; }"
+ b1_name = os.path.join(self.get_dir(), 'b1.c')
+ open(b1_name, 'w').write(b1)
+ b2 = "void y() {}"
+ b2_name = os.path.join(self.get_dir(), 'b2.c')
+ open(b2_name, 'w').write(b2)
+ main = r'''
+ #include <stdio.h>
+ int f();
+ int main() {
+ printf("result: %d\n", f());
+ return 0;
+ }
+ '''
+ main_name = os.path.join(self.get_dir(), 'main.c')
+ open(main_name, 'w').write(main)
+
+ Building.emcc(a1_name)
+ Building.emcc(a2_name)
+ Building.emcc(b1_name)
+ Building.emcc(b2_name)
+ Building.emcc(main_name)
+
+ liba_name = os.path.join(self.get_dir(), 'liba.a')
+ Building.emar('cr', liba_name, [a1_name + '.o', a2_name + '.o'])
+ libb_name = os.path.join(self.get_dir(), 'libb.a')
+ Building.emar('cr', libb_name, [b1_name + '.o', b2_name + '.o'])
+
+ all_name = os.path.join(self.get_dir(), 'all.bc')
+ Building.link([main_name + '.o', liba_name, libb_name], all_name)
+
+ self.do_ll_run(all_name, 'result: 1')
+
def test_if(self):
src = '''
#include <stdio.h>
@@ -1360,6 +1402,32 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
Settings.DISABLE_EXCEPTION_CATCHING = 0
self.do_run(src, 'Throw...Construct...Catched...Destruct...Throw...Construct...Copy...Catched...Destruct...Destruct...')
+ def test_uncaught_exception(self):
+ Settings.EXCEPTION_DEBUG = 0 # Messes up expected output.
+ Settings.DISABLE_EXCEPTION_CATCHING = 0
+
+ src = r'''
+ #include <stdio.h>
+ #include <exception>
+ struct X {
+ ~X() {
+ printf("exception? %s\n", std::uncaught_exception() ? "yes" : "no");
+ }
+ };
+ int main() {
+ printf("exception? %s\n", std::uncaught_exception() ? "yes" : "no");
+ try {
+ X x;
+ throw 1;
+ } catch(...) {
+ printf("exception? %s\n", std::uncaught_exception() ? "yes" : "no");
+ }
+ printf("exception? %s\n", std::uncaught_exception() ? "yes" : "no");
+ return 0;
+ }
+ '''
+ self.do_run(src, 'exception? no\nexception? yes\nexception? no\nexception? no\n')
+
def test_typed_exceptions(self):
return self.skip('TODO: fix this for llvm 3.0')
@@ -3742,6 +3810,28 @@ def process(filename):
}
'''
self.do_run(src, "some string constant")
+
+ def test_istream(self):
+ if self.emcc_args is None: return self.skip('requires libcxx')
+
+ src = '''
+ #include <string>
+ #include <sstream>
+ #include <iostream>
+
+ int main()
+ {
+ std::string mystring("1 2 3");
+ std::istringstream is(mystring);
+ int one, two, three;
+
+ is >> one >> two >> three;
+
+ printf( "%i %i %i", one, two, three );
+ }
+ '''
+ self.do_run(src, "1 2 3")
+
def test_fs_base(self):
Settings.INCLUDE_FULL_LIBRARY = 1
@@ -4298,7 +4388,7 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'freetype', 'main.c'), 'r').read(),
open(path_from_root('tests', 'freetype', 'ref.txt'), 'r').read(),
['font.ttf', 'test!', '150', '120', '25'],
- libraries=[self.get_freetype()],
+ libraries=self.get_freetype(),
includes=[path_from_root('tests', 'freetype', 'include')],
post_build=post)
#build_ll_hook=self.do_autodebug)
@@ -4339,7 +4429,7 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'zlib', 'example.c'), 'r').read(),
open(path_from_root('tests', 'zlib', 'ref.txt'), 'r').read(),
- libraries=[self.get_library('zlib', os.path.join('libz.a'), make_args=['libz.a'])],
+ libraries=self.get_library('zlib', os.path.join('libz.a'), make_args=['libz.a']),
includes=[path_from_root('tests', 'zlib')],
force_c=True)
@@ -4356,10 +4446,10 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
[open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings
open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read()],
- libraries=[self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletCollision.a'),
- os.path.join('src', '.libs', 'libBulletDynamics.a'),
+ libraries=self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletDynamics.a'),
+ os.path.join('src', '.libs', 'libBulletCollision.a'),
os.path.join('src', '.libs', 'libLinearMath.a')],
- configure_args=['--disable-demos','--disable-dependency-tracking'])],
+ configure_args=['--disable-demos','--disable-dependency-tracking']),
includes=[path_from_root('tests', 'bullet', 'src')],
js_engines=[SPIDERMONKEY_ENGINE]) # V8 issue 1407
@@ -4400,15 +4490,15 @@ def process(filename):
freetype = self.get_freetype()
poppler = self.get_library('poppler',
- [os.path.join('poppler', '.libs', self.get_shared_library_name('libpoppler.so.13')),
- os.path.join('utils', 'pdftoppm.o'),
- os.path.join('utils', 'parseargs.o')],
- configure_args=['--disable-libjpeg', '--disable-libpng', '--disable-poppler-qt', '--disable-poppler-qt4', '--disable-cms'])
+ [os.path.join('utils', 'pdftoppm.o'),
+ os.path.join('utils', 'parseargs.o'),
+ os.path.join('poppler', '.libs', 'libpoppler.a')],
+ configure_args=['--disable-libjpeg', '--disable-libpng', '--disable-poppler-qt', '--disable-poppler-qt4', '--disable-cms', '--disable-cairo-output', '--disable-abiword-output', '--enable-shared=no'])
# Combine libraries
combined = os.path.join(self.get_dir(), 'poppler-combined.bc')
- Building.link([freetype, poppler], combined)
+ Building.link(poppler + freetype, combined)
self.do_ll_run(combined,
map(ord, open(path_from_root('tests', 'poppler', 'ref.ppm'), 'r').read()).__str__().replace(' ', ''),
@@ -4442,11 +4532,11 @@ def process(filename):
shutil.copy(path_from_root('tests', 'openjpeg', 'opj_config.h'), self.get_dir())
lib = self.get_library('openjpeg',
- [os.path.join('bin', self.get_shared_library_name('libopenjpeg.so.1.4.0')),
- os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/index.c.o'.split('/')),
+ [os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/index.c.o'.split('/')),
os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/convert.c.o'.split('/')),
os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/__/common/color.c.o'.split('/')),
- os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/__/common/getopt.c.o'.split('/'))],
+ os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/__/common/getopt.c.o'.split('/')),
+ os.path.join('bin', self.get_shared_library_name('libopenjpeg.so.1.4.0'))],
configure=['cmake', '.'],
#configure_args=['--enable-tiff=no', '--enable-jp3d=no', '--enable-png=no'],
make_args=[]) # no -j 2, since parallel builds can fail
@@ -4490,7 +4580,7 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'openjpeg', 'codec', 'j2k_to_image.c'), 'r').read(),
'Successfully generated', # The real test for valid output is in image_compare
'-i image.j2k -o image.raw'.split(' '),
- libraries=[lib],
+ libraries=lib,
includes=[path_from_root('tests', 'openjpeg', 'libopenjpeg'),
path_from_root('tests', 'openjpeg', 'codec'),
path_from_root('tests', 'openjpeg', 'common'),
@@ -5552,9 +5642,9 @@ Options that are modified or new in %s include:
# XXX find a way to test this: assert ('& 255' in generated or '&255' in generated) == (opt_level <= 2), 'corrections should be in opt <= 2'
assert ('(__label__)' in generated) == (opt_level <= 1), 'relooping should be in opt >= 2'
assert ('assert(STACKTOP < STACK_MAX' in generated) == (opt_level == 0), 'assertions should be in opt == 0'
- assert 'var $i;' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or 'var $i_04;' in generated, 'micro opts should always be on'
+ assert 'var $i;' in generated or 'var $i_01;' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or 'var $i_04;' in generated, 'micro opts should always be on'
if opt_level >= 1:
- assert 'HEAP8[HEAP32[' in generated or 'HEAP8[$vla1 + $storemerge4 / 2 | 0]' in generated or 'HEAP8[$vla1 + ($storemerge4 / 2 | 0)]' in generated or 'HEAP8[$vla1 + $i_04 / 2 | 0]' in generated or 'HEAP8[$vla1 + ($i_04 / 2 | 0)]' in generated, 'eliminator should create compound expressions, and fewer one-time vars'
+ assert 'HEAP8[HEAP32[' in generated or 'HEAP8[$vla1 + $storemerge4 / 2 | 0]' in generated or 'HEAP8[$vla1 + ($storemerge4 / 2 | 0)]' in generated or 'HEAP8[$vla1 + $i_04 / 2 | 0]' in generated or 'HEAP8[$vla1 + ($i_04 / 2 | 0)]' in generated or 'HEAP8[$1 + $i_01 / 2 | 0]' in generated or 'HEAP8[$1 + ($i_01 / 2 | 0)]' in generated, 'eliminator should create compoun