Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Pthreads #67

Merged
merged 31 commits into from
Jun 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3294faa
Make memory initializer allocation aware of whether running in a pthr…
juj Aug 11, 2014
2c387ab
Implement volatile loads and stores to use Atomics.load and store to …
juj Sep 5, 2014
ecf31f6
Add support for LLVM atomics.
juj Nov 30, 2014
9198866
Implement Atomic compare-and-exchange support.
juj Nov 30, 2014
b4a3db7
Implement Atomic fence support
juj Nov 30, 2014
1ed5faa
Add support for AtomicCmpXchg instruction for pthreads.
juj Jan 19, 2015
4b51d3f
Make Atomics API asm.js compliant.
juj Jan 19, 2015
f6980c0
Add call handlers to built-in functions emscripten_atomic_cas_* so th…
juj Jan 19, 2015
2cb9593
Add direct asm.js call handlers for Atomics operations.
juj Jan 19, 2015
9eeb1e8
Emulate HEAPF32 and HEAPF64 Atomic loads and stores in the absence of…
juj Feb 10, 2015
a0804f0
Add a backend command line parameter -emscripten-enable-pthreads to c…
juj Feb 21, 2015
b4bcbe2
Implement support for AtomicCmpXchg when not compiling with pthreads …
juj Feb 21, 2015
9e2c3ab
Add missing check for not emitting atomic loads when not building wit…
juj Feb 21, 2015
61e6276
Apply review formatting.
juj Mar 24, 2015
402699e
Register the variables required to implement Instruction::AtomicCmpXc…
juj Mar 24, 2015
0b4e68c
Align whitespace in AtomicRMWInst switch-cases in JSBackend.cpp.
juj Mar 24, 2015
173e6f6
Clarify comment in Instruction::Fence() for JSBackend.cpp.
juj Mar 24, 2015
900826d
Do not emit "if (!ENVIRONMENT_IS_PTHREAD)" at all when not building w…
juj Mar 24, 2015
dac3535
Fix asm.js validation when code emits atomic operations to f32 and f6…
juj Apr 15, 2015
afb0efb
Add support for more emulated 64bit operations.
juj Apr 28, 2015
7ec89a9
Add support for expanding 64-bit atomic add and sub instructions from…
juj May 4, 2015
c4ad168
Fix asm.js validation of 64-bit atomic stores.
juj May 5, 2015
91a6044
Add support for asm.js validating emscripten_atomic_exchange intrinsics.
juj May 13, 2015
25ecc3a
Fix emscripten atomic exchange to call correct atomic intrinsic.
juj May 13, 2015
ff25c5e
Fix the number of params to emscripten_atomic_exchange intrinsic.
juj May 14, 2015
91f7005
HACK: Atomics.exchange() is not yet implemented, so as a temp workaro…
juj May 14, 2015
ecc1252
Add missing relocateGlobal() in getAddressAsString(). Remove unused a…
juj Jun 1, 2015
3c942ae
Remove code duplication between the different methods for accessing m…
juj Jun 1, 2015
91e09dc
Remove getByteAddressAsStr() as a duplicate of getValueAsStr().
juj Jun 1, 2015
c439cf2
Use PNaCl intrinsics based approach for handling atomic cmpxchg.
juj Jun 1, 2015
63bf6b6
Rename getAddressAsString() to getShiftedPtr() and reuse its implemen…
juj Jun 1, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 202 additions & 7 deletions lib/Target/JSBackend/CallHandlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,16 +314,21 @@ DEF_CALL_HANDLER(llvm_nacl_atomic_store_i32, {
return "HEAP32[" + getValueAsStr(CI->getOperand(0)) + ">>2]=" + getValueAsStr(CI->getOperand(1));
})

#define CMPXCHG_HANDLER(name) \
#define CMPXCHG_HANDLER(name, HeapName) \
DEF_CALL_HANDLER(name, { \
const Value *P = CI->getOperand(0); \
return getLoad(CI, P, CI->getType(), 0) + ';' + \
"if ((" + getCast(getJSName(CI), CI->getType()) + ") == " + getValueAsCastParenStr(CI->getOperand(1)) + ") " + \
getStore(CI, P, CI->getType(), getValueAsStr(CI->getOperand(2)), 0); \
if (EnablePthreads) { \
return getAssign(CI) + "Atomics_compareExchange(" HeapName ", " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ", " + getValueAsStr(CI->getOperand(2)) + ")"; \
} else { \
return getLoad(CI, P, CI->getType(), 0) + ';' + \
"if ((" + getCast(getJSName(CI), CI->getType()) + ") == " + getValueAsCastParenStr(CI->getOperand(1)) + ") " + \
getStore(CI, P, CI->getType(), getValueAsStr(CI->getOperand(2)), 0); \
} \
})
CMPXCHG_HANDLER(llvm_nacl_atomic_cmpxchg_i8);
CMPXCHG_HANDLER(llvm_nacl_atomic_cmpxchg_i16);
CMPXCHG_HANDLER(llvm_nacl_atomic_cmpxchg_i32);

CMPXCHG_HANDLER(llvm_nacl_atomic_cmpxchg_i8, "HEAP8");
CMPXCHG_HANDLER(llvm_nacl_atomic_cmpxchg_i16, "HEAP16");
CMPXCHG_HANDLER(llvm_nacl_atomic_cmpxchg_i32, "HEAP32");

#define UNROLL_LOOP_MAX 8
#define WRITE_LOOP_MAX 128
Expand Down Expand Up @@ -549,6 +554,145 @@ DEF_CALL_HANDLER(emscripten_asm_const_double, {
return getAssign(CI) + getCast(handleAsmConst(CI), Type::getDoubleTy(CI->getContext()));
})

/* TODO: Uncomment once https://bugzilla.mozilla.org/show_bug.cgi?id=1141986 is implemented!

DEF_CALL_HANDLER(emscripten_atomic_exchange_u8, {
return getAssign(CI) + "Atomics_exchange(HEAP8, " + getValueAsStr(CI->getOperand(0)) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_exchange_u16, {
return getAssign(CI) + "Atomics_exchange(HEAP16, " + getShiftedPtr(CI->getOperand(0), 2) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_exchange_u32, {
return getAssign(CI) + "Atomics_exchange(HEAP32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_exchange_f32, {
return getAssign(CI) + "Atomics_exchange(HEAPF32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_exchange_f64, {
return getAssign(CI) + "Atomics_exchange(HEAPF64, " + getShiftedPtr(CI->getOperand(0), 8) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
*/

DEF_CALL_HANDLER(emscripten_atomic_cas_u8, {
return getAssign(CI) + "Atomics_compareExchange(HEAP8, " + getValueAsStr(CI->getOperand(0)) + ", " + getValueAsStr(CI->getOperand(1)) + ", " + getValueAsStr(CI->getOperand(2)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_cas_u16, {
return getAssign(CI) + "Atomics_compareExchange(HEAP16, " + getShiftedPtr(CI->getOperand(0), 2) + ", " + getValueAsStr(CI->getOperand(1)) + ", " + getValueAsStr(CI->getOperand(2)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_cas_u32, {
return getAssign(CI) + "Atomics_compareExchange(HEAP32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ", " + getValueAsStr(CI->getOperand(2)) + ")";
})

DEF_CALL_HANDLER(emscripten_atomic_load_u8, {
return getAssign(CI) + "Atomics_load(HEAP8, " + getValueAsStr(CI->getOperand(0)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_load_u16, {
return getAssign(CI) + "Atomics_load(HEAP16, " + getShiftedPtr(CI->getOperand(0), 2) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_load_u32, {
return getAssign(CI) + "Atomics_load(HEAP32, " + getShiftedPtr(CI->getOperand(0), 4) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_load_f32, {
// TODO: If https://bugzilla.mozilla.org/show_bug.cgi?id=1131613 is implemented, we could use the commented out version. Until then,
// we must emulate manually.
return getAssign(CI) + (PreciseF32 ? "Math_fround(" : "+") + "__Atomics_load_f32_emulated(" + getShiftedPtr(CI->getOperand(0), 4) + (PreciseF32 ? "))" : ")");
// return getAssign(CI) + "Atomics_load(HEAPF32, " + getShiftedPtr(CI->getOperand(0), 4) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_load_f64, {
// TODO: If https://bugzilla.mozilla.org/show_bug.cgi?id=1131624 is implemented, we could use the commented out version. Until then,
// we must emulate manually.
return getAssign(CI) + "+_emscripten_atomic_load_f64(" + getShiftedPtr(CI->getOperand(0), 8) + ")";
// return getAssign(CI) + "Atomics_load(HEAPF64, " + getShiftedPtr(CI->getOperand(0), 8) + ")";
})

DEF_CALL_HANDLER(emscripten_atomic_store_u8, {
return getAssign(CI) + "Atomics_store(HEAP8, " + getValueAsStr(CI->getOperand(0)) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_store_u16, {
return getAssign(CI) + "Atomics_store(HEAP16, " + getShiftedPtr(CI->getOperand(0), 2) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_store_u32, {
return getAssign(CI) + "Atomics_store(HEAP32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_store_f32, {
// TODO: If https://bugzilla.mozilla.org/show_bug.cgi?id=1131613 is implemented, we could use the commented out version. Until then,
// we must emulate manually.
return getAssign(CI) + "_emscripten_atomic_store_f32(" + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
// return getAssign(CI) + "Atomics_store(HEAPF32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_store_f64, {
// TODO: If https://bugzilla.mozilla.org/show_bug.cgi?id=1131624 is implemented, we could use the commented out version. Until then,
// we must emulate manually.
return getAssign(CI) + "+_emscripten_atomic_store_f64(" + getShiftedPtr(CI->getOperand(0), 8) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
// return getAssign(CI) + "Atomics_store(HEAPF64, " + getShiftedPtr(CI->getOperand(0), 8) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})

DEF_CALL_HANDLER(emscripten_atomic_add_u8, {
return getAssign(CI) + "Atomics_add(HEAP8, " + getValueAsStr(CI->getOperand(0)) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_add_u16, {
return getAssign(CI) + "Atomics_add(HEAP16, " + getShiftedPtr(CI->getOperand(0), 2) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_add_u32, {
return getAssign(CI) + "Atomics_add(HEAP32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_add_f32, {
errs() << "emcc: warning: float32 atomic add is not supported!" << CI->getParent()->getParent()->getName() << ":" << *CI << "\n";
return getAssign(CI) + "Atomics_add(HEAPF32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_add_f64, {
errs() << "emcc: warning: float64 atomic add is not supported!" << CI->getParent()->getParent()->getName() << ":" << *CI << "\n";
return getAssign(CI) + "Atomics_add(HEAPF64, " + getShiftedPtr(CI->getOperand(0), 8) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})

DEF_CALL_HANDLER(emscripten_atomic_sub_u8, {
return getAssign(CI) + "Atomics_sub(HEAP8, " + getValueAsStr(CI->getOperand(0)) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_sub_u16, {
return getAssign(CI) + "Atomics_sub(HEAP16, " + getShiftedPtr(CI->getOperand(0), 2) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_sub_u32, {
return getAssign(CI) + "Atomics_sub(HEAP32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_sub_f32, {
errs() << "emcc: warning: float32 atomic sub is not supported!" << CI->getParent()->getParent()->getName() << ":" << *CI << "\n";
return getAssign(CI) + "Atomics_sub(HEAPF32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_sub_f64, {
errs() << "emcc: warning: float64 atomic sub is not supported!" << CI->getParent()->getParent()->getName() << ":" << *CI << "\n";
return getAssign(CI) + "Atomics_sub(HEAPF64, " + getShiftedPtr(CI->getOperand(0), 8) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})

DEF_CALL_HANDLER(emscripten_atomic_and_u8, {
return getAssign(CI) + "Atomics_and(HEAP8, " + getValueAsStr(CI->getOperand(0)) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_and_u16, {
return getAssign(CI) + "Atomics_and(HEAP16, " + getShiftedPtr(CI->getOperand(0), 2) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_and_u32, {
return getAssign(CI) + "Atomics_and(HEAP32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})

DEF_CALL_HANDLER(emscripten_atomic_or_u8, {
return getAssign(CI) + "Atomics_or(HEAP8, " + getValueAsStr(CI->getOperand(0)) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_or_u16, {
return getAssign(CI) + "Atomics_or(HEAP16, " + getShiftedPtr(CI->getOperand(0), 2) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_or_u32, {
return getAssign(CI) + "Atomics_or(HEAP32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})

DEF_CALL_HANDLER(emscripten_atomic_xor_u8, {
return getAssign(CI) + "Atomics_xor(HEAP8, " + getValueAsStr(CI->getOperand(0)) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_xor_u16, {
return getAssign(CI) + "Atomics_xor(HEAP16, " + getShiftedPtr(CI->getOperand(0), 2) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})
DEF_CALL_HANDLER(emscripten_atomic_xor_u32, {
return getAssign(CI) + "Atomics_xor(HEAP32, " + getShiftedPtr(CI->getOperand(0), 4) + ", " + getValueAsStr(CI->getOperand(1)) + ")";
})

#define DEF_BUILTIN_HANDLER(name, to) \
DEF_CALL_HANDLER(name, { \
return CH___default__(CI, #to); \
Expand Down Expand Up @@ -637,6 +781,7 @@ DEF_BUILTIN_HANDLER(emscripten_int32x4_greaterThanOrEqual, SIMD_int32x4_greaterT
DEF_BUILTIN_HANDLER(emscripten_int32x4_select, SIMD_int32x4_select);
DEF_BUILTIN_HANDLER(emscripten_int32x4_fromFloat32x4Bits, SIMD_int32x4_fromFloat32x4Bits);
DEF_BUILTIN_HANDLER(emscripten_int32x4_fromFloat32x4, SIMD_int32x4_fromFloat32x4);
DEF_BUILTIN_HANDLER(emscripten_atomic_fence, Atomics_fence);

// Setups

Expand Down Expand Up @@ -727,6 +872,56 @@ void setupCallHandlers() {
SETUP_CALL_HANDLER(emscripten_asm_const_int);
SETUP_CALL_HANDLER(emscripten_asm_const_double);

/* TODO: Uncomment once https://bugzilla.mozilla.org/show_bug.cgi?id=1141986 is implemented!
SETUP_CALL_HANDLER(emscripten_atomic_exchange_u8);
SETUP_CALL_HANDLER(emscripten_atomic_exchange_u16);
SETUP_CALL_HANDLER(emscripten_atomic_exchange_u32);
SETUP_CALL_HANDLER(emscripten_atomic_exchange_f32);
SETUP_CALL_HANDLER(emscripten_atomic_exchange_f64);
*/

SETUP_CALL_HANDLER(emscripten_atomic_cas_u8);
SETUP_CALL_HANDLER(emscripten_atomic_cas_u16);
SETUP_CALL_HANDLER(emscripten_atomic_cas_u32);

SETUP_CALL_HANDLER(emscripten_atomic_load_u8);
SETUP_CALL_HANDLER(emscripten_atomic_load_u16);
SETUP_CALL_HANDLER(emscripten_atomic_load_u32);
SETUP_CALL_HANDLER(emscripten_atomic_load_f32);
SETUP_CALL_HANDLER(emscripten_atomic_load_f64);

SETUP_CALL_HANDLER(emscripten_atomic_store_u8);
SETUP_CALL_HANDLER(emscripten_atomic_store_u16);
SETUP_CALL_HANDLER(emscripten_atomic_store_u32);
SETUP_CALL_HANDLER(emscripten_atomic_store_f32);
SETUP_CALL_HANDLER(emscripten_atomic_store_f64);

SETUP_CALL_HANDLER(emscripten_atomic_add_u8);
SETUP_CALL_HANDLER(emscripten_atomic_add_u16);
SETUP_CALL_HANDLER(emscripten_atomic_add_u32);
SETUP_CALL_HANDLER(emscripten_atomic_add_f32);
SETUP_CALL_HANDLER(emscripten_atomic_add_f64);

SETUP_CALL_HANDLER(emscripten_atomic_sub_u8);
SETUP_CALL_HANDLER(emscripten_atomic_sub_u16);
SETUP_CALL_HANDLER(emscripten_atomic_sub_u32);
SETUP_CALL_HANDLER(emscripten_atomic_sub_f32);
SETUP_CALL_HANDLER(emscripten_atomic_sub_f64);

SETUP_CALL_HANDLER(emscripten_atomic_and_u8);
SETUP_CALL_HANDLER(emscripten_atomic_and_u16);
SETUP_CALL_HANDLER(emscripten_atomic_and_u32);

SETUP_CALL_HANDLER(emscripten_atomic_or_u8);
SETUP_CALL_HANDLER(emscripten_atomic_or_u16);
SETUP_CALL_HANDLER(emscripten_atomic_or_u32);

SETUP_CALL_HANDLER(emscripten_atomic_xor_u8);
SETUP_CALL_HANDLER(emscripten_atomic_xor_u16);
SETUP_CALL_HANDLER(emscripten_atomic_xor_u32);

SETUP_CALL_HANDLER(emscripten_atomic_fence);

SETUP_CALL_HANDLER(abs);
SETUP_CALL_HANDLER(labs);
SETUP_CALL_HANDLER(cos);
Expand Down
Loading