aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-01-17 14:52:05 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-01-17 14:52:05 -0800
commit074e5f54d468730b3719fac72710322170a20535 (patch)
tree62c1f335e1ac360c32ad57e54677bb5c9a39b2d2
parent76ddb8091266741ae046d1b6fdeef4f782617d5b (diff)
handle atomic operations appearing in libc++
-rw-r--r--src/intertyper.js17
-rw-r--r--src/jsifier.js14
-rw-r--r--tests/runner.py46
3 files changed, 52 insertions, 25 deletions
diff --git a/src/intertyper.js b/src/intertyper.js
index 7bc23653..6b46cdbb 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -366,6 +366,8 @@ function intertyper(data, sidePass, baseLineNums) {
return '/dev/null';
if (tokensLength >= 3 && token0Text == 'invoke')
return 'Invoke';
+ if (tokensLength >= 3 && token0Text == 'atomicrmw' || token0Text == 'cmpxchg')
+ return 'Atomic';
} else {
// Already intertyped
if (item.parentSlot)
@@ -739,6 +741,21 @@ function intertyper(data, sidePass, baseLineNums) {
return result.ret;
}
});
+ substrate.addActor('Atomic', {
+ processItem: function(item) {
+ item.intertype = 'atomic';
+ if (item.tokens[0].text == 'atomicrmw') {
+ item.op = item.tokens[1].text;
+ item.tokens.splice(1, 1);
+ } else {
+ assert(item.tokens[0].text == 'cmpxchg')
+ item.op = 'cmpxchg';
+ }
+ var last = getTokenIndexByText(item.tokens, ';');
+ item.params = splitTokenList(item.tokens.slice(1, last)).map(parseLLVMSegment);
+ this.forwardItem(item, 'Reintegrator');
+ }
+ });
// 'landingpad' - just a stub implementation
substrate.addActor('Landingpad', {
processItem: function(item) {
diff --git a/src/jsifier.js b/src/jsifier.js
index db6936f6..69a64d1a 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -944,6 +944,20 @@ function JSify(data, functionsOnly, givenFunctions) {
+ ' } else { ' + getPhiSetsForLabel(phiSets, item.unwindLabel) + makeBranch(item.unwindLabel, item.currLabelId) + ' }';
return ret;
});
+ makeFuncLineActor('atomic', function(item) {
+ var type = item.params[0].type;
+ var param1 = finalizeLLVMParameter(item.params[0]);
+ var param2 = finalizeLLVMParameter(item.params[1]);
+ switch (item.op) {
+ case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue+' + param2, type) + ',tempValue)';
+ case 'xchg': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, param2, type) + ',tempValue)';
+ case 'cmpxchg': {
+ var param3 = finalizeLLVMParameter(item.params[2]);
+ return '(tempValue=' + makeGetValue(param1, 0, type) + ',(' + makeGetValue(param1, 0, type) + '==' + param2 + ' && (' + makeSetValue(param1, 0, param3, type) + ')),tempValue)';
+ }
+ default: throw 'unhandled atomic op: ' + item.op;
+ }
+ });
makeFuncLineActor('landingpad', function(item) {
// Just a stub
return '{ f0: ' + makeGetValue('_llvm_eh_exception.buf', '0', 'void*') +
diff --git a/tests/runner.py b/tests/runner.py
index d0056400..6db5aaf3 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -3820,33 +3820,29 @@ def process(filename):
self.do_run(src, expected)
CORRECT_SIGNS = 0
- def test_atomic_builtins(self): # XXX TODO
+ def test_atomic(self):
src = '''
- type __sync_fetch_and_add (type *ptr, type value, ...)
- type __sync_fetch_and_sub (type *ptr, type value, ...)
- type __sync_fetch_and_or (type *ptr, type value, ...)
- type __sync_fetch_and_and (type *ptr, type value, ...)
- type __sync_fetch_and_xor (type *ptr, type value, ...)
- type __sync_fetch_and_nand (type *ptr, type value, ...)
-
- type __sync_add_and_fetch (type *ptr, type value, ...)
- type __sync_sub_and_fetch (type *ptr, type value, ...)
- type __sync_or_and_fetch (type *ptr, type value, ...)
- type __sync_and_and_fetch (type *ptr, type value, ...)
- type __sync_xor_and_fetch (type *ptr, type value, ...)
- type __sync_nand_and_fetch (type *ptr, type value, ...)
-
- bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
- type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
-
- __sync_synchronize (...)
-
- type __sync_lock_test_and_set (type *ptr, type value, ...)
-
- void __sync_lock_release (type *ptr, ...)
- '''
+ #include <stdio.h>
+ int main() {
+ int x = 10;
+ int y = __sync_add_and_fetch(&x, 5);
+ printf("*%d,%d*\\n", x, y);
+ x = 10;
+ y = __sync_fetch_and_add(&x, 5);
+ printf("*%d,%d*\\n", x, y);
+ x = 10;
+ y = __sync_lock_test_and_set(&x, 6);
+ printf("*%d,%d*\\n", x, y);
+ x = 10;
+ y = __sync_bool_compare_and_swap(&x, 9, 7);
+ printf("*%d,%d*\\n", x, y);
+ y = __sync_bool_compare_and_swap(&x, 10, 7);
+ printf("*%d,%d*\\n", x, y);
+ return 0;
+ }
+ '''
- self.do_run(src, 'hello world\n77.\n',
+ self.do_run(src, '*15,15*\n*15,10*\n*6,10*\n*10,0*\n*7,1*')
# libc++ tests