summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc1
-rw-r--r--src/jsifier.js1
-rw-r--r--src/library.js1
-rw-r--r--src/library_gl.js14
-rw-r--r--src/parseTools.js5
-rw-r--r--src/relooper/Relooper.cpp127
-rw-r--r--src/relooper/Relooper.h7
-rw-r--r--src/relooper/fuzzer.py4
-rw-r--r--src/relooper/test.cpp41
-rw-r--r--src/relooper/test.txt27
-rw-r--r--src/relooper/test4.txt1
-rw-r--r--src/relooper/test_debug.txt76
-rw-r--r--src/relooper/test_fuzz1.txt11
-rw-r--r--src/relooper/test_fuzz5.txt24
-rw-r--r--src/relooper/test_fuzz6.txt1
-rwxr-xr-xsrc/relooper/testit.sh2
-rwxr-xr-xsrc/relooper/updateit.sh2
-rw-r--r--tests/cases/fp80_ta2.ll (renamed from tests/cases/fp80.ll)0
-rw-r--r--tests/cases/muli33_ta2.ll (renamed from tests/cases/muli33.ll)0
-rw-r--r--tests/cases/muli33_ta2.txt (renamed from tests/cases/muli33.txt)0
-rw-r--r--tests/cases/philoop_ta2.ll (renamed from tests/cases/philoop.ll)0
-rw-r--r--tests/cases/philoop_ta2.txt (renamed from tests/cases/philoop.txt)0
-rw-r--r--tests/files.cpp3
-rw-r--r--tests/full_es2_sdlproc.c727
-rwxr-xr-xtests/runner.py63
-rw-r--r--tools/shared.py2
26 files changed, 1020 insertions, 120 deletions
diff --git a/emcc b/emcc
index 65dec978..9feba1b1 100755
--- a/emcc
+++ b/emcc
@@ -995,6 +995,7 @@ try:
key, value = change.split('=')
if value[0] == '@':
value = '"@' + os.path.abspath(value[1:]) + '"'
+ value = value.replace('\\\\', '/').replace('\\', '/') # Convert backslash paths to forward slashes on Windows as well, since the JS compiler otherwise needs the backslashes escaped (alternative is to escape all input paths passing to JS, which feels clumsier to read)
exec('shared.Settings.' + key + ' = ' + value)
# Apply effects from settings
diff --git a/src/jsifier.js b/src/jsifier.js
index 77aff895..156fd65d 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -460,6 +460,7 @@ function JSify(data, functionsOnly, givenFunctions) {
} else {
ident = '_' + ident;
}
+ if (VERBOSE) printErr('adding ' + ident + ' and deps ' + deps);
var depsText = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : '');
var contentText = isFunction ? snippet : ('var ' + ident + '=' + snippet + ';');
if (ASM_JS) {
diff --git a/src/library.js b/src/library.js
index e65754ba..51c4c5cb 100644
--- a/src/library.js
+++ b/src/library.js
@@ -560,6 +560,7 @@ LibraryManager.library = {
var stdout = FS.createDevice(devFolder, 'stdout', null, output);
var stderr = FS.createDevice(devFolder, 'stderr', null, error);
FS.createDevice(devFolder, 'tty', input, output);
+ FS.createDevice(devFolder, 'null', function(){}, function(){});
// Create default streams.
FS.streams[1] = {
diff --git a/src/library_gl.js b/src/library_gl.js
index 5055f9e1..1fa0cc9c 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -1280,10 +1280,17 @@ var LibraryGL = {
hasRunInit: false,
init: function() {
+ // Do not activate immediate/emulation code (e.g. replace glDrawElements) when in FULL_ES2 mode.
+ // We do not need full emulation, we instead emulate client-side arrays etc. in FULL_ES2 code in
+ // a straightforward manner, and avoid not having a bound buffer be ambiguous between es2 emulation
+ // code and legacy gl emulation code.
+#if FULL_ES2
+ return;
+#endif
+
if (GLEmulation.hasRunInit) {
return;
}
-
GLEmulation.hasRunInit = true;
GLEmulation.fogColor = new Float32Array(4);
@@ -1983,7 +1990,10 @@ var LibraryGL = {
// GL Immediate mode
+ // See comment in GLEmulation.init()
+#if FULL_ES2 == 0
$GLImmediate__postset: 'GL.immediate.setupFuncs(); Browser.moduleContextCreatedCallbacks.push(function() { GL.immediate.init() });',
+#endif
$GLImmediate__deps: ['$Browser', '$GL', '$GLEmulation'],
$GLImmediate: {
MapTreeLib: null,
@@ -3955,7 +3965,7 @@ var LibraryGL = {
},
// Vertex array object (VAO) support. TODO: when the WebGL extension is popular, use that and remove this code and GL.vaos
- glGenVertexArrays__deps: ['$GLEMulation'],
+ glGenVertexArrays__deps: ['$GLEmulation'],
glGenVertexArrays__sig: 'vii',
glGenVertexArrays: function(n, vaos) {
for (var i = 0; i < n; i++) {
diff --git a/src/parseTools.js b/src/parseTools.js
index 090d85ac..3949491e 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -2047,8 +2047,9 @@ function processMathop(item) {
if ((type == 'i64' || paramTypes[0] == 'i64' || paramTypes[1] == 'i64' || idents[1] == '(i64)' || rawBits > 32) && USE_TYPED_ARRAYS == 2) {
// this code assumes i64 for the most part
- if (ASSERTIONS && rawBits < 64) {
- warnOnce('processMathop processing illegal non-i64 value: ' + [type, paramTypes, idents])
+ if (ASSERTIONS && rawBits > 1 && rawBits < 64) {
+ warnOnce('processMathop processing illegal non-i64 value');
+ if (VERBOSE) printErr([op, item.type, rawBits, type, paramTypes, idents]);
}
var warnI64_1 = function() {
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index 61daed79..8c72b0a6 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -104,9 +104,6 @@ Block::Block(const char *CodeInit) : Parent(NULL), Id(Block::IdCounter++), Defau
Block::~Block() {
if (Code) free((void*)Code);
- for (BlockBranchMap::iterator iter = ProcessedBranchesIn.begin(); iter != ProcessedBranchesIn.end(); iter++) {
- delete iter->second;
- }
for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) {
delete iter->second;
}
@@ -139,10 +136,6 @@ void Block::Render(bool InLoop) {
bool SetLabel = true; // in some cases it is clear we can avoid setting label, see later
- if (ProcessedBranchesOut.size() == 1 && ProcessedBranchesOut.begin()->second->Type == Branch::Direct) {
- SetLabel = false;
- }
-
// A setting of the label variable (label = x) is necessary if it can
// cause an impact. The main case is where we set label to x, then elsewhere
// we check if label is equal to that value, i.e., that label is an entry
@@ -379,22 +372,47 @@ void Relooper::Calculate(Block *Entry) {
Block *Curr = *iter;
TotalCodeSize += strlen(Curr->Code);
}
-
+ BlockSet Splits;
+ BlockSet Removed;
+ //DebugDump(Live, "before");
for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) {
Block *Original = *iter;
- if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue;
+ if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue; // only dead ends, for now
+ if (Original->BranchesOut.find(Original) != Original->BranchesOut.end()) continue; // cannot split a looping node
if (strlen(Original->Code)*(Original->BranchesIn.size()-1) > TotalCodeSize/5) continue; // if splitting increases raw code size by a significant amount, abort
// Split the node (for simplicity, we replace all the blocks, even though we could have reused the original)
- for (BlockBranchMap::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) {
- Block *Prior = iter->first;
+ PrintDebug("Splitting block %d\n", Original->Id);
+ for (BlockSet::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) {
+ Block *Prior = *iter;
Block *Split = new Block(Original->Code);
- Split->BranchesIn[Prior] = new Branch(NULL);
- Prior->BranchesOut[Split] = new Branch(Prior->BranchesOut[Original]->Condition, Prior->BranchesOut[Original]->Code);
+ Parent->Blocks.push_back(Split);
+ PrintDebug(" to %d\n", Split->Id);
+ Split->BranchesIn.insert(Prior);
+ Branch *Details = Prior->BranchesOut[Original];
+ Prior->BranchesOut[Split] = new Branch(Details->Condition, Details->Code);
Prior->BranchesOut.erase(Original);
- Parent->AddBlock(Split);
- Live.insert(Split);
+ for (BlockBranchMap::iterator iter = Original->BranchesOut.begin(); iter != Original->BranchesOut.end(); iter++) {
+ Block *Post = iter->first;
+ Branch *Details = iter->second;
+ Split->BranchesOut[Post] = new Branch(Details->Condition, Details->Code);
+ Post->BranchesIn.insert(Split);
+ }
+ Splits.insert(Split);
+ Removed.insert(Original);
+ }
+ for (BlockBranchMap::iterator iter = Original->BranchesOut.begin(); iter != Original->BranchesOut.end(); iter++) {
+ Block *Post = iter->first;
+ Post->BranchesIn.erase(Original);
}
+ //DebugDump(Live, "mid");
+ }
+ for (BlockSet::iterator iter = Splits.begin(); iter != Splits.end(); iter++) {
+ Live.insert(*iter);
+ }
+ for (BlockSet::iterator iter = Removed.begin(); iter != Removed.end(); iter++) {
+ Live.erase(*iter);
}
+ //DebugDump(Live, "after");
}
};
PreOptimizer Pre(this);
@@ -405,7 +423,7 @@ void Relooper::Calculate(Block *Entry) {
Block *Curr = Blocks[i];
if (Pre.Live.find(Curr) == Pre.Live.end()) continue;
for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
- iter->first->BranchesIn[Curr] = new Branch(NULL);
+ iter->first->BranchesIn.insert(Curr);
}
}
@@ -435,22 +453,21 @@ void Relooper::Calculate(Block *Entry) {
void Solipsize(Block *Target, Branch::FlowType Type, Shape *Ancestor, BlockSet &From) {
PrintDebug("Solipsizing branches into %d\n", Target->Id);
DebugDump(From, " relevant to solipsize: ");
- for (BlockBranchMap::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) {
- Block *Prior = iter->first;
+ for (BlockSet::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) {
+ Block *Prior = *iter;
if (From.find(Prior) == From.end()) {
iter++;
continue;
}
- Branch *TargetIn = iter->second;
Branch *PriorOut = Prior->BranchesOut[Target];
- PriorOut->Ancestor = Ancestor; // Do we need this info
- PriorOut->Type = Type; // on TargetIn too?
+ PriorOut->Ancestor = Ancestor;
+ PriorOut->Type = Type;
if (MultipleShape *Multiple = Shape::IsMultiple(Ancestor)) {
Multiple->NeedLoop++; // We are breaking out of this Multiple, so need a loop
}
iter++; // carefully increment iter before erasing
Target->BranchesIn.erase(Prior);
- Target->ProcessedBranchesIn[Prior] = TargetIn;
+ Target->ProcessedBranchesIn.insert(Prior);
Prior->BranchesOut.erase(Target);
Prior->ProcessedBranchesOut[Target] = PriorOut;
PrintDebug(" eliminated branch from %d\n", Prior->Id);
@@ -488,8 +505,8 @@ void Relooper::Calculate(Block *Entry) {
InnerBlocks.insert(Curr);
Blocks.erase(Curr);
// Add the elements prior to it
- for (BlockBranchMap::iterator iter = Curr->BranchesIn.begin(); iter != Curr->BranchesIn.end(); iter++) {
- Queue.insert(iter->first);
+ for (BlockSet::iterator iter = Curr->BranchesIn.begin(); iter != Curr->BranchesIn.end(); iter++) {
+ Queue.insert(*iter);
}
}
}
@@ -620,8 +637,8 @@ void Relooper::Calculate(Block *Entry) {
BlockList ToInvalidate;
for (BlockSet::iterator iter = CurrGroup.begin(); iter != CurrGroup.end(); iter++) {
Block *Child = *iter;
- for (BlockBranchMap::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) {
- Block *Parent = iter->first;
+ for (BlockSet::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) {
+ Block *Parent = *iter;
if (Helper.Ownership[Parent] != Helper.Ownership[Child]) {
ToInvalidate.push_back(Child);
}
@@ -751,8 +768,8 @@ void Relooper::Calculate(Block *Entry) {
Block *Entry = iter->first;
BlockSet &Group = iter->second;
BlockBlockSetMap::iterator curr = iter++; // iterate carefully, we may delete
- for (BlockBranchMap::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) {
- Block *Origin = iterBranch->first;
+ for (BlockSet::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) {
+ Block *Origin = *iterBranch;
if (Group.find(Origin) == Group.end()) {
// Reached from outside the group, so we cannot handle this
PrintDebug("Cannot handle group with entry %d because of incoming branch from %d\n", Entry->Id, Origin->Id);
@@ -821,13 +838,11 @@ void Relooper::Calculate(Block *Entry) {
// Main
BlockSet AllBlocks;
- for (int i = 0; i < Blocks.size(); i++) {
- AllBlocks.insert(Blocks[i]);
+ for (BlockSet::iterator iter = Pre.Live.begin(); iter != Pre.Live.end(); iter++) {
+ Block *Curr = *iter;
+ AllBlocks.insert(Curr);
#if DEBUG
- PrintDebug("Adding block %d (%s)\n", Blocks[i]->Id, Blocks[i]->Code);
- for (BlockBranchMap::iterator iter = Blocks[i]->BranchesOut.begin(); iter != Blocks[i]->BranchesOut.end(); iter++) {
- PrintDebug(" with branch out to %d\n", iter->first->Id);
- }
+ PrintDebug("Adding block %d (%s)\n", Curr->Id, Curr->Code);
#endif
}
@@ -874,10 +889,26 @@ void Relooper::Calculate(Block *Entry) {
func(Loop->Next); \
}
+ // Find the blocks that natural control flow can get us directly to, or through a multiple that we ignore
+ void FollowNaturalFlow(Shape *S, BlockSet &Out) {
+ SHAPE_SWITCH(S, {
+ Out.insert(Simple->Inner);
+ }, {
+ for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ FollowNaturalFlow(iter->second, Out);
+ }
+ FollowNaturalFlow(Multiple->Next, Out);
+ }, {
+ FollowNaturalFlow(Loop->Inner, Out);
+ });
+ }
+
// Remove unneeded breaks and continues.
// A flow operation is trivially unneeded if the shape we naturally get to by normal code
// execution is the same as the flow forces us to.
void RemoveUnneededFlows(Shape *Root, Shape *Natural=NULL) {
+ BlockSet NaturalBlocks;
+ FollowNaturalFlow(Natural, NaturalBlocks);
Shape *Next = Root;
while (Next) {
Root = Next;
@@ -892,7 +923,7 @@ void Relooper::Calculate(Block *Entry) {
for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) {
Block *Target = iter->first;
Branch *Details = iter->second;
- if (Details->Type != Branch::Direct && Target->Parent == Natural) {
+ if (Details->Type != Branch::Direct && NaturalBlocks.find(Target) != NaturalBlocks.end()) { // note: cannot handle split blocks
Details->Type = Branch::Direct;
if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
Multiple->NeedLoop--;
@@ -1007,12 +1038,32 @@ void Relooper::SetAsmJSMode(int On) {
#if DEBUG
// Debugging
-void DebugDump(BlockSet &Blocks, const char *prefix) {
+void Debugging::Dump(BlockSet &Blocks, const char *prefix) {
if (prefix) printf("%s ", prefix);
for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) {
- printf("%d ", (*iter)->Id);
+ Block *Curr = *iter;
+ printf("%d:\n", Curr->Id);
+ for (BlockBranchMap::iterator iter2 = Curr->BranchesOut.begin(); iter2 != Curr->BranchesOut.end(); iter2++) {
+ Block *Other = iter2->first;
+ printf(" -> %d\n", Other->Id);
+ assert(Other->BranchesIn.find(Curr) != Other->BranchesIn.end());
+ }
}
- printf("\n");
+}
+
+void Debugging::Dump(Shape *S, const char *prefix) {
+ if (prefix) printf("%s ", prefix);
+ printf(" %d ", S->Id);
+ SHAPE_SWITCH(S, {
+ printf("<< Simple with block %d\n", Simple->Inner->Id);
+ }, {
+ printf("<< Multiple\n");
+ for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ printf(" with entry %d\n", iter->first->Id);
+ }
+ }, {
+ printf("<< Loop\n");
+ });
}
static void PrintDebug(const char *Format, ...) {
diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h
index eac03738..34b6db08 100644
--- a/src/relooper/Relooper.h
+++ b/src/relooper/Relooper.h
@@ -41,6 +41,7 @@ struct Branch {
void Render(Block *Target, bool SetLabel);
};
+typedef std::set<Block*> BlockSet;
typedef std::map<Block*, Branch*> BlockBranchMap;
// Represents a basic block of code - some instructions that end with a
@@ -52,9 +53,9 @@ struct Block {
// processed branches.
// Blocks own the Branch objects they use, and destroy them when done.
BlockBranchMap BranchesOut;
- BlockBranchMap BranchesIn; // TODO: make this just a list of Incoming, without branch info - should be just on BranchesOut
+ BlockSet BranchesIn;
BlockBranchMap ProcessedBranchesOut;
- BlockBranchMap ProcessedBranchesIn;
+ BlockSet ProcessedBranchesIn;
Shape *Parent; // The shape we are directly inside
int Id; // A unique identifier
const char *Code; // The string representation of the code in this block. Owning pointer (we copy the input)
@@ -205,12 +206,12 @@ struct Relooper {
static void SetAsmJSMode(int On);
};
-typedef std::set<Block*> BlockSet;
typedef std::map<Block*, BlockSet> BlockBlockSetMap;
#if DEBUG
struct Debugging {
static void Dump(BlockSet &Blocks, const char *prefix=NULL);
+ static void Dump(Shape *S, const char *prefix=NULL);
};
#endif
diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py
index 96929028..5f6bae3d 100644
--- a/src/relooper/fuzzer.py
+++ b/src/relooper/fuzzer.py
@@ -98,14 +98,14 @@ int main() {
open('fuzz.slow.js', 'w').write(slow)
open('fuzz.cpp', 'w').write(fast)
print '_'
- slow_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
+ slow_out = subprocess.Popen(['mozjs', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
print '.'
subprocess.call(['g++', 'fuzz.cpp', 'Relooper.o', '-o', 'fuzz', '-g'])
print '*'
subprocess.call(['./fuzz'], stdout=open('fuzz.fast.js', 'w'))
print '-'
- fast_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
+ fast_out = subprocess.Popen(['mozjs', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
print
if slow_out != fast_out:
diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp
index 4275941b..7da990b5 100644
--- a/src/relooper/test.cpp
+++ b/src/relooper/test.cpp
@@ -190,5 +190,46 @@ int main() {
puts(buffer);
}
+
+ if (1) {
+ Relooper::SetOutputBuffer(buffer, sizeof(buffer));
+
+ printf("\n\n-- if (expensive || expensive2) X else Y; Z --\n\n");
+
+ Block *b_a = new Block("// block A\n");
+ Block *b_b = new Block("// block B\n");
+ Block *b_c = new Block("// block C;\n");
+ Block *b_d = new Block("// block D\n");
+ Block *b_e = new Block("// block E\n");
+ Block *b_f = new Block("// block F\n");
+
+ b_a->AddBranchTo(b_c, "expensive()");
+ b_a->AddBranchTo(b_b, NULL);
+
+ b_b->AddBranchTo(b_c, "expensive2()");
+ b_b->AddBranchTo(b_d, NULL);
+
+ b_c->AddBranchTo(b_e, NULL);
+
+ b_d->AddBranchTo(b_e, NULL);
+
+ b_e->AddBranchTo(b_f, NULL);
+
+ b_f->AddBranchTo(b_e, NULL);
+
+ Relooper r;
+ r.AddBlock(b_a);
+ r.AddBlock(b_b);
+ r.AddBlock(b_c);
+ r.AddBlock(b_d);
+ r.AddBlock(b_e);
+ r.AddBlock(b_f);
+
+ r.Calculate(b_a);
+ printf("\n\n");
+ r.Render();
+
+ puts(buffer);
+ }
}
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index 12d0ef39..d657c6af 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -109,3 +109,30 @@ while(1) {
// block D
}
+
+
+-- if (expensive || expensive2) X else Y; Z --
+
+
+
+// block A
+do {
+ if (expensive()) {
+ label = 33;
+ } else {
+ // block B
+ if (expensive2()) {
+ label = 33;
+ break;
+ }
+ // block D
+ }
+} while(0);
+if (label == 33) {
+ // block C;
+}
+while(1) {
+ // block E
+ // block F
+}
+
diff --git a/src/relooper/test4.txt b/src/relooper/test4.txt
index f0bfb972..3427ff18 100644
--- a/src/relooper/test4.txt
+++ b/src/relooper/test4.txt
@@ -7,7 +7,6 @@ do {
break;
}
//21
- break;
} else {
label = 4;
}
diff --git a/src/relooper/test_debug.txt b/src/relooper/test_debug.txt
index 1c7d0508..d18ed875 100644
--- a/src/relooper/test_debug.txt
+++ b/src/relooper/test_debug.txt
@@ -28,56 +28,88 @@ int main() {
return 0;
}
// Adding block 1 (ep)
-// with branch out to 2
-// with branch out to 4
// Adding block 2 (LBB1)
-// with branch out to 3
-// with branch out to 4
// Adding block 3 (LBB2)
-// with branch out to 4
// Adding block 4 (LBB3)
// Process() called
// Process() running
- blocks : 1 2 3 4
- entries: 1
+ blocks : 1:
+ -> 2
+ -> 4
+2:
+ -> 3
+ -> 4
+3:
+ -> 4
+4:
+ entries: 1:
+ -> 2
+ -> 4
// creating simple block with block #1
// Solipsizing branches into 2
- relevant to solipsize: 1
+ relevant to solipsize: 1:
+ -> 2
+ -> 4
// eliminated branch from 1
// Solipsizing branches into 4
- relevant to solipsize: 1
+ relevant to solipsize: 1:
+ -> 4
// eliminated branch from 1
// Process() running
- blocks : 2 3 4
- entries: 2 4
+ blocks : 2:
+ -> 3
+ -> 4
+3:
+ -> 4
+4:
+ entries: 2:
+ -> 3
+ -> 4
+4:
// Investigated independent groups:
- group: 2 3
+ group: 2:
+ -> 3
+ -> 4
+3:
+ -> 4
// Independent groups: 1
// Handleable independent groups: 1
// creating multiple block with 1 inner groups
// multiple group with entry 2:
- 2 3
+ 2:
+ -> 3
+ -> 4
+3:
+ -> 4
// Solipsizing branches into 4
- relevant to solipsize: 2 3
+ relevant to solipsize: 2:
+ -> 3
+ -> 4
+3:
+ -> 4
// eliminated branch from 2
// eliminated branch from 3
// Process() called
// Process() running
- blocks : 2 3
- entries: 2
+ blocks : 2:
+ -> 3
+3:
+ entries: 2:
+ -> 3
// creating simple block with block #2
// Solipsizing branches into 3
- relevant to solipsize: 2
+ relevant to solipsize: 2:
+ -> 3
// eliminated branch from 2
// Process() running
- blocks : 3
- entries: 3
+ blocks : 3:
+ entries: 3:
// creating simple block with block #3
// Process() returning
- remaining blocks after multiple: 4
+ remaining blocks after multiple: 4:
// Process() running
- blocks : 4
- entries: 4
+ blocks : 4:
+ entries: 4:
// creating simple block with block #4
// Process() returning
// === Optimizing shapes ===
diff --git a/src/relooper/test_fuzz1.txt b/src/relooper/test_fuzz1.txt
index 5122257e..b278e240 100644
--- a/src/relooper/test_fuzz1.txt
+++ b/src/relooper/test_fuzz1.txt
@@ -3,13 +3,10 @@
print('entry'); var label; var state; var decisions = [4, 1, 7, 2, 6, 6, 8]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
print(5); state = check();
print(6); state = check();
-do {
- if (state == 7) {
- print(7); state = check();
- label = 3;
- break;
- }
-} while(0);
+if (state == 7) {
+ print(7); state = check();
+ label = 3;
+}
L5: while(1) {
if (label == 3) {
label = 0;
diff --git a/src/relooper/test_fuzz5.txt b/src/relooper/test_fuzz5.txt
index 9548205c..29b2dba4 100644
--- a/src/relooper/test_fuzz5.txt
+++ b/src/relooper/test_fuzz5.txt
@@ -3,22 +3,18 @@
print('entry'); var label; var state; var decisions = [133, 98, 134, 143, 162, 187, 130, 87, 91, 49, 102, 47, 9, 132, 179, 176, 157, 25, 64, 161, 57, 107, 16, 167, 185, 45, 191, 180, 23, 131]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
L1: while(1) {
print(7); state = check();
- do {
- if (state % 3 == 1) {
- label = 3;
- } else if (state % 3 == 0) {
- print(8); state = check();
- if (state % 2 == 0) {
- label = 5;
- break;
- } else {
- label = 7;
- break;
- }
+ if (state % 3 == 1) {
+ label = 3;
+ } else if (state % 3 == 0) {
+ print(8); state = check();
+ if (state % 2 == 0) {
+ label = 5;
} else {
- break L1;
+ label = 7;
}
- } while(0);
+ } else {
+ break;
+ }
while(1) {
if (label == 3) {
label = 0;
diff --git a/src/relooper/test_fuzz6.txt b/src/relooper/test_fuzz6.txt
index bd45e8fd..d5a5ab7b 100644
--- a/src/relooper/test_fuzz6.txt
+++ b/src/relooper/test_fuzz6.txt
@@ -82,7 +82,6 @@ while(1) {
print(56); state = check();// ....................................................................................................................................................................................................................
print(34); state = check();// ..........................................................................................................................................
label = 74;
- continue;
}
print(62); state = check();// .......................................................................................
}
diff --git a/src/relooper/testit.sh b/src/relooper/testit.sh
index 61e1a2fb..88db35fb 100755
--- a/src/relooper/testit.sh
+++ b/src/relooper/testit.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
echo "test"
./test &> test.out
diff --git a/src/relooper/updateit.sh b/src/relooper/updateit.sh
index 8c434753..da9fa9aa 100755
--- a/src/relooper/updateit.sh
+++ b/src/relooper/updateit.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
./test &> test.txt
./test2 &> test2.txt
./test3 &> test3.txt
diff --git a/tests/cases/fp80.ll b/tests/cases/fp80_ta2.ll
index 7fc0db4a..7fc0db4a 100644
--- a/tests/cases/fp80.ll
+++ b/tests/cases/fp80_ta2.ll
diff --git a/tests/cases/muli33.ll b/tests/cases/muli33_ta2.ll
index b33b04f7..b33b04f7 100644
--- a/tests/cases/muli33.ll
+++ b/tests/cases/muli33_ta2.ll
diff --git a/tests/cases/muli33.txt b/tests/cases/muli33_ta2.txt
index 21e0231f..21e0231f 100644
--- a/tests/cases/muli33.txt
+++ b/tests/cases/muli33_ta2.txt
diff --git a/tests/cases/philoop.ll b/tests/cases/philoop_ta2.ll
index 5036c7ba..5036c7ba 100644
--- a/tests/cases/philoop.ll
+++ b/tests/cases/philoop_ta2.ll
diff --git a/tests/cases/philoop.txt b/tests/cases/philoop_ta2.txt
index d5117fe8..d5117fe8 100644
--- a/tests/cases/philoop.txt
+++ b/tests/cases/philoop_ta2.txt
diff --git a/tests/files.cpp b/tests/files.cpp
index 04baa151..176cdb62 100644
--- a/tests/files.cpp
+++ b/tests/files.cpp
@@ -56,6 +56,9 @@ int main()
fwrite(data, 1, 5, outf);
fclose(outf);
+ FILE *devNull = fopen("/dev/null", "rb");
+ assert(devNull);
+
char data2[10];
FILE *inf = fopen("go.out", "rb");
int num = fread(data2, 1, 10, inf);
diff --git a/tests/full_es2_sdlproc.c b/tests/full_es2_sdlproc.c
new file mode 100644
index 00000000..d9ac072b
--- /dev/null
+++ b/tests/full_es2_sdlproc.c
@@ -0,0 +1,727 @@
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Ported to GLES2.
+ * Kristian Høgsberg <krh@bitplanet.net>
+ * May 3, 2010
+ *
+ * Improve GLES2 port:
+ * * Refactor gear drawing.
+ * * Use correct normals for surfaces.
+ * * Improve shader.
+ * * Use perspective projection transformation.
+ * * Add FPS count.
+ * * Add comments.
+ * Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ * Jul 13, 2010
+ */
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+
+#define _GNU_SOURCE
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <GL/gl.h>
+#include <GL/glut.h>
+
+#ifndef HAVE_BUILTIN_SINCOS
+#include "sincos.h"
+#endif
+
+#define STRIPS_PER_TOOTH 7
+#define VERTICES_PER_TOOTH 34
+#define GEAR_VERTEX_STRIDE 6
+
+/**
+ * Struct describing the vertices in triangle strip
+ */
+struct vertex_strip {
+ /** The first vertex in the strip */
+ GLint first;
+ /** The number of consecutive vertices in the strip after the first */
+ GLint count;
+};
+
+/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */
+typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE];
+
+/**
+ * Struct representing a gear.
+ */
+struct gear {
+ /** The array of vertices comprising the gear */
+ GearVertex *vertices;
+ /** The number of vertices comprising the gear */
+ int nvertices;
+ /** The array of triangle strips comprising the gear */
+ struct vertex_strip *strips;
+ /** The number of triangle strips comprising the gear */
+ int nstrips;
+ /** The Vertex Buffer Object holding the vertices in the graphics card */
+ GLuint vbo;
+};
+
+/** The view rotation [x, y, z] */
+static GLfloat view_rot[3] = { 20.0, 30.0, 0.0 };
+/** The gears */
+static struct gear *gear1, *gear2, *gear3;
+/** The current gear rotation angle */
+static GLfloat angle = 0.0;
+/** The location of the shader uniforms */
+static GLuint ModelViewProjectionMatrix_location,
+ NormalMatrix_location,
+ LightSourcePosition_location,
+ MaterialColor_location;
+/** The projection matrix */
+static GLfloat ProjectionMatrix[16];
+/** The direction of the directional light for the scene */
+static const GLfloat LightSourcePosition[4] = { 5.0, 5.0, 10.0, 1.0};
+
+/**
+ * Fills a gear vertex.
+ *
+ * @param v the vertex to fill
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coortinate
+ * @param n pointer to the normal table
+ *
+ * @return the operation error code
+ */
+static GearVertex *
+vert(GearVertex *v, GLfloat x, GLfloat y, GLfloat z, GLfloat n[3])
+{
+ v[0][0] = x;
+ v[0][1] = y;
+ v[0][2] = z;
+ v[0][3] = n[0];
+ v[0][4] = n[1];
+ v[0][5] = n[2];
+
+ return v + 1;
+}
+
+/**
+ * Create a gear wheel.
+ *
+ * @param inner_radius radius of hole at center
+ * @param outer_radius radius at center of teeth
+ * @param width width of gear
+ * @param teeth number of teeth
+ * @param tooth_depth depth of tooth
+ *
+ * @return pointer to the constructed struct gear
+ */
+static struct gear *
+create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth)
+{
+ GLfloat r0, r1, r2;
+ GLfloat da;
+ GearVertex *v;
+ struct gear *gear;
+ double s[5], c[5];
+ GLfloat normal[3];
+ int cur_strip = 0;
+ int i;
+
+ /* Allocate memory for the gear */
+ gear = malloc(sizeof *gear);
+ if (gear == NULL)
+ return NULL;
+
+ /* Calculate the radii used in the gear */
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0;
+ r2 = outer_radius + tooth_depth / 2.0;
+
+ da = 2.0 * M_PI / teeth / 4.0;
+
+ /* Allocate memory for the triangle strip information */
+ gear->nstrips = STRIPS_PER_TOOTH * teeth;
+ gear->strips = calloc(gear->nstrips, sizeof (*gear->strips));
+
+ /* Allocate memory for the vertices */
+ gear->vertices = calloc(VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices));
+ v = gear->vertices;
+
+ for (i = 0; i < teeth; i++) {
+ /* Calculate needed sin/cos for varius angles */
+ sincos(i * 2.0 * M_PI / teeth, &s[0], &c[0]);
+ sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]);
+ sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
+ sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
+ sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);
+
+ /* A set of macros for making the creation of the gears easier */
+#define GEAR_POINT(r, da) { (r) * c[(da)], (r) * s[(da)] }
+#define SET_NORMAL(x, y, z) do { \
+ normal[0] = (x); normal[1] = (y); normal[2] = (z); \
+} while(0)
+
+#define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal)
+
+#define START_STRIP do { \
+ gear->strips[cur_strip].first = v - gear->vertices; \
+} while(0);
+
+#define END_STRIP do { \
+ int _tmp = (v - gear->vertices); \
+ gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \
+ cur_strip++; \
+} while (0)
+
+#define QUAD_WITH_NORMAL(p1, p2) do { \
+ SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0); \
+ v = GEAR_VERT(v, (p1), -1); \
+ v = GEAR_VERT(v, (p1), 1); \
+ v = GEAR_VERT(v, (p2), -1); \
+ v = GEAR_VERT(v, (p2), 1); \
+} while(0)
+
+ struct point {
+ GLfloat x;
+ GLfloat y;
+ };
+
+ /* Create the 7 points (only x,y coords) used to draw a tooth */
+ struct point p[7] = {
+ GEAR_POINT(r2, 1), // 0
+ GEAR_POINT(r2, 2), // 1
+ GEAR_POINT(r1, 0), // 2
+ GEAR_POINT(r1, 3), // 3
+ GEAR_POINT(r0, 0), // 4
+ GEAR_POINT(r1, 4), // 5
+ GEAR_POINT(r0, 4), // 6
+ };
+
+ /* Front face */
+ START_STRIP;
+ SET_NORMAL(0, 0, 1.0);
+ v = GEAR_VERT(v, 0, +1);
+ v = GEAR_VERT(v, 1, +1);
+ v = GEAR_VERT(v, 2, +1);
+ v = GEAR_VERT(v, 3, +1);
+ v = GEAR_VERT(v, 4, +1);
+ v = GEAR_VERT(v, 5, +1);
+ v = GEAR_VERT(v, 6, +1);
+ END_STRIP;
+
+ /* Inner face */
+ START_STRIP;
+ QUAD_WITH_NORMAL(4, 6);
+ END_STRIP;
+
+ /* Back face */
+ START_STRIP;
+ SET_NORMAL(0, 0, -1.0);
+ v = GEAR_VERT(v, 6, -1);
+ v = GEAR_VERT(v, 5, -1);
+ v = GEAR_VERT(v, 4, -1);
+ v = GEAR_VERT(v, 3, -1);
+ v = GEAR_VERT(v, 2, -1);
+ v = GEAR_VERT(v, 1, -1);
+ v = GEAR_VERT(v, 0, -1);
+ END_STRIP;
+
+ /* Outer face */
+ START_STRIP;
+ QUAD_WITH_NORMAL(0, 2);
+ END_STRIP;
+
+ START_STRIP;
+ QUAD_WITH_NORMAL(1, 0);
+ END_STRIP;
+
+ START_STRIP;
+ QUAD_WITH_NORMAL(3, 1);
+ END_STRIP;
+
+ START_STRIP;
+ QUAD_WITH_NORMAL(5, 3);
+ END_STRIP;
+ }
+
+ gear->nvertices = (v - gear->vertices);
+
+ /* Store the vertices in a vertex buffer object (VBO) */
+ glGenBuffers(1, &gear->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
+ glBufferData(GL_ARRAY_BUFFER, gear->nvertices * sizeof(GearVertex),
+ gear->vertices, GL_STATIC_DRAW);
+
+ return gear;
+}
+
+/**
+ * Multiplies two 4x4 matrices.
+ *
+ * The result is stored in matrix m.
+ *
+ * @param m the first matrix to multiply
+ * @param n the second matrix to multiply
+ */
+static void
+multiply(GLfloat *m, const GLfloat *n)
+{
+ GLfloat tmp[16];
+ const GLfloat *row, *column;
+ div_t d;
+ int i, j;
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = 0;
+ d = div(i, 4);
+ row = n + d.quot * 4;
+ column = m + d.rem;
+ for (j = 0; j < 4; j++)
+ tmp[i] += row[j] * column[j * 4];
+ }
+ memcpy(m, &tmp, sizeof tmp);
+}
+
+/**
+ * Rotates a 4x4 matrix.
+ *
+ * @param[in,out] m the matrix to rotate
+ * @param angle the angle to rotate
+ * @param x the x component of the direction to rotate to
+ * @param y the y component of the direction to rotate to
+ * @param z the z component of the direction to rotate to
+ */
+static void
+rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+{
+ double s, c;
+
+ sincos(angle, &s, &c);
+ GLfloat r[16] = {
+ x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
+ x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
+ x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0,
+ 0, 0, 0, 1
+ };
+
+ multiply(m, r);
+}
+
+
+/**
+ * Translates a 4x4 matrix.
+ *
+ * @param[in,out] m the matrix to translate
+ * @param x the x component of the direction to translate to
+ * @param y the y component of the direction to translate to
+ * @param z the z component of the direction to translate to
+ */
+static void
+translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 };
+
+ multiply(m, t);
+}
+
+/**
+ * Creates an identity 4x4 matrix.
+ *
+ * @param m the matrix make an identity matrix
+ */
+static void
+identity(GLfloat *m)
+{
+ GLfloat t[16] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+
+ memcpy(m, t, sizeof(t));
+}
+
+/**
+ * Transposes a 4x4 matrix.
+ *
+ * @param m the matrix to transpose
+ */
+static void
+transpose(GLfloat *m)
+{
+ GLfloat t[16] = {
+ m[0], m[4], m[8], m[12],
+ m[1], m[5], m[9], m[13],
+ m[2], m[6], m[10], m[14],
+ m[3], m[7], m[11], m[15]};
+
+ memcpy(m, t, sizeof(t));
+}
+
+/**
+ * Inverts a 4x4 matrix.
+ *
+ * This function can currently handle only pure translation-rotation matrices.
+ * Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118
+ * for an explanation.
+ */
+static void
+invert(GLfloat *m)
+{
+ GLfloat t[16];
+ identity(t);
+
+ // Extract and invert the translation part 't'. The inverse of a
+ // translation matrix can be calculated by negating the translation
+ // coordinates.
+ t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14];
+
+ // Invert the rotation part 'r'. The inverse of a rotation matrix is
+ // equal to its transpose.
+ m[12] = m[13] = m[14] = 0;
+ transpose(m);
+
+ // inv(m) = inv(r) * inv(t)
+ multiply(m, t);
+}
+
+/**
+ * Calculate a perspective projection transformation.
+ *
+ * @param m the matrix to save the transformation in
+ * @param fovy the field of view in the y direction
+ * @param aspect the view aspect ratio
+ * @param zNear the near clipping plane
+ * @param zFar the far clipping plane
+ */
+void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
+{
+ GLfloat tmp[16];
+ identity(tmp);
+
+ double sine, cosine, cotangent, deltaZ;
+ GLfloat radians = fovy / 2 * M_PI / 180;
+
+ deltaZ = zFar - zNear;
+ sincos(radians, &sine, &cosine);
+
+ if ((deltaZ == 0) || (sine == 0) || (aspect == 0))
+ return;
+
+ cotangent = cosine / sine;
+
+ tmp[0] = cotangent / aspect;
+ tmp[5] = cotangent;
+ tmp[10] = -(zFar + zNear) / deltaZ;
+ tmp[11] = -1;
+ tmp[14] = -2 * zNear * zFar / deltaZ;
+ tmp[15] = 0;
+
+ memcpy(m, tmp, sizeof(tmp));
+}
+
+/**
+ * Draws a gear.
+ *
+ * @param gear the gear to draw
+ * @param transform the current transformation matrix
+ * @param x the x position to draw the gear at
+ * @param y the y position to draw the gear at
+ * @param angle the rotation angle of the gear
+ * @param color the color of the gear
+ */
+static void
+draw_gear(struct gear *gear, GLfloat *transform,
+ GLfloat x, GLfloat y, GLfloat angle, const GLfloat color[4])
+{
+ GLfloat model_view[16];
+ GLfloat normal_matrix[16];
+ GLfloat model_view_projection[16];
+
+ /* Translate and rotate the gear */
+ memcpy(model_view, transform, sizeof (model_view));
+ translate(model_view, x, y, 0);
+ rotate(model_view, 2 * M_PI * angle / 360.0, 0, 0, 1);
+
+ /* Create and set the ModelViewProjectionMatrix */
+ memcpy(model_view_projection, ProjectionMatrix, sizeof(model_view_projection));
+ multiply(model_view_projection, model_view);
+
+ glUniformMatrix4fv(ModelViewProjectionMatrix_location, 1, GL_FALSE,
+ model_view_projection);
+
+ /*
+ * Create and set the NormalMatrix. It's the inverse transpose of the
+ * ModelView matrix.
+ */
+ memcpy(normal_matrix, model_view, sizeof (normal_matrix));
+ invert(normal_matrix);
+ transpose(normal_matrix);
+ glUniformMatrix4fv(NormalMatrix_location, 1, GL_FALSE, normal_matrix);
+
+ /* Set the gear color */
+ glUniform4fv(MaterialColor_location, 1, color);
+
+ /* Set the vertex buffer object to use */
+ glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
+
+ /* Set up the position of the attributes in the vertex buffer object */
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
+ 6 * sizeof(GLfloat), NULL);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
+ 6 * sizeof(GLfloat), (GLfloat *) 0 + 3);
+
+ /* Enable the attributes */
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+
+ /* Draw the triangle strips that comprise the gear */
+ int n;
+ for (n = 0; n < gear->nstrips; n++)
+ glDrawElements(GL_TRIANGLE_STRIP, gear->strips[n].count, GL_FLOAT, gear->strips[n].first);
+
+ /* Disable the attributes */
+ glDisableVertexAttribArray(1);
+ glDisableVertexAttribArray(0);
+}
+
+/**
+ * Draws the gears.
+ */
+static void
+gears_draw(void)
+{
+ const static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+ const static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+ const static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+ GLfloat transform[16];
+ identity(transform);
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* Translate and rotate the view */
+ translate(transform, 0, 0, -20);
+ rotate(transform, 2 * M_PI * view_rot[0] / 360.0, 1, 0, 0);
+ rotate(transform, 2 * M_PI * view_rot[1] / 360.0, 0, 1, 0);
+ rotate(transform, 2 * M_PI * view_rot[2] / 360.0, 0, 0, 1);
+
+ /* Draw the gears */
+ draw_gear(gear1, transform, -3.0, -2.0, angle, red);
+ draw_gear(gear2, transform, 3.1, -2.0, -2 * angle - 9.0, green);
+ draw_gear(gear3, transform, -3.1, 4.2, -2 * angle - 25.0, blue);
+
+ glutSwapBuffers();
+}
+
+/**
+ * Handles a new window size or exposure.
+ *
+ * @param width the window width
+ * @param height the window height
+ */
+static void
+gears_reshape(int width, int height)
+{
+ /* Update the projection matrix */
+ perspective(ProjectionMatrix, 60.0, width / (float)height, 1.0, 1024.0);
+
+ /* Set the viewport */
+ glViewport(0, 0, (GLint) width, (GLint) height);
+}
+
+/**
+ * Handles special glut events.
+ *
+ * @param special the event to handle.
+ */
+static void
+gears_special(int special, int crap, int morecrap)
+{
+ switch (special) {
+ case GLUT_KEY_LEFT:
+ view_rot[1] += 5.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ view_rot[1] -= 5.0;
+ break;
+ case GLUT_KEY_UP:
+ view_rot[0] += 5.0;
+ break;
+ case GLUT_KEY_DOWN:
+ view_rot[0] -= 5.0;
+ break;
+ }
+}
+
+static void
+gears_idle(void)
+{
+ static int frames = 0;
+ static double tRot0 = -1.0, tRate0 = -1.0;
+ double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+
+ if (tRot0 < 0.0)
+ tRot0 = t;
+ dt = t - tRot0;
+ tRot0 = t;
+
+ /* advance rotation for next frame */
+ angle += 70.0 * dt; /* 70 degrees per second */
+ if (angle > 3600.0)
+ angle -= 3600.0;
+
+ glutPostRedisplay();
+ frames++;
+
+ if (tRate0 < 0.0)
+ tRate0 = t;
+ if (t - tRate0 >= 5.0) {
+ GLfloat seconds = t - tRate0;
+ GLfloat fps = frames / seconds;
+ printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
+ fps);
+ tRate0 = t;
+ frames = 0;
+ }
+}
+
+static const char vertex_shader[] =
+"attribute vec3 position;\n"
+"attribute vec3 normal;\n"
+"\n"
+"uniform mat4 ModelViewProjectionMatrix;\n"
+"uniform mat4 NormalMatrix;\n"
+"uniform vec4 LightSourcePosition;\n"
+"uniform vec4 MaterialColor;\n"
+"\n"
+"varying vec4 Color;\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" // Transform the normal to eye coordinates\n"
+" vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n"
+"\n"
+" // The LightSourcePosition is actually its direction for directional light\n"
+" vec3 L = normalize(LightSourcePosition.xyz);\n"
+"\n"
+" // Multiply the diffuse value by the vertex color (which is fixed in this case)\n"
+" // to get the actual color that we will use to draw this vertex with\n"
+" float diffuse = max(dot(N, L), 0.0);\n"
+" Color = diffuse * MaterialColor;\n"
+"\n"
+" // Transform the position to clip coordinates\n"
+" gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n"
+"}";
+
+static const char fragment_shader[] =
+"#ifdef GL_ES\n"
+"precision mediump float;\n"
+"#endif\n"
+"varying vec4 Color;\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" gl_FragColor = Color;\n"
+"}";
+
+static void
+gears_init(void)
+{
+ GLuint v, f, program;
+ const char *p;
+ char msg[512];
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ /* Compile the vertex shader */
+ p = vertex_shader;
+ v = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(v, 1, &p, NULL);
+ glCompileShader(v);
+ glGetShaderInfoLog(v, sizeof msg, NULL, msg);
+ printf("vertex shader info: %s\n", msg);
+
+ /* Compile the fragment shader */
+ p = fragment_shader;
+ f = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(f, 1, &p, NULL);
+ glCompileShader(f);
+ glGetShaderInfoLog(f, sizeof msg, NULL, msg);
+ printf("fragment shader info: %s\n", msg);
+
+ /* Create and link the shader program */
+ program = glCreateProgram();
+ glAttachShader(program, v);
+ glAttachShader(program, f);
+ glBindAttribLocation(program, 0, "position");
+ glBindAttribLocation(program, 1, "normal");
+
+ glLinkProgram(program);
+ glGetProgramInfoLog(program, sizeof msg, NULL, msg);
+ printf("info: %s\n", msg);
+
+ /* Enable the shaders */
+ glUseProgram(program);
+
+ /* Get the locations of the uniforms so we can access them */
+ ModelViewProjectionMatrix_location = glGetUniformLocation(program, "ModelViewProjectionMatrix");
+ NormalMatrix_location = glGetUniformLocation(program, "NormalMatrix");
+ LightSourcePosition_location = glGetUniformLocation(program, "LightSourcePosition");
+ MaterialColor_location = glGetUniformLocation(program, "MaterialColor");
+
+ /* Set the LightSourcePosition uniform which is constant throught the program */
+ glUniform4fv(LightSourcePosition_location, 1, LightSourcePosition);
+
+ /* make the gears */
+ gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7);
+ gear2 = create_gear(0.5, 2.0, 2.0, 10, 0.7);
+ gear3 = create_gear(1.3, 2.0, 0.5, 10, 0.7);
+}
+
+int
+main(int argc, char *argv[])
+{
+ if (argc == 12) SDL_GL_GetProcAddress("glWhatevah");
+
+ /* Initialize the window */
+ glutInit(&argc, argv);
+ glutInitWindowSize(300, 300);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+
+ glutCreateWindow("es2gears");
+
+ gears_idle();
+ gears_init();
+ gears_draw();
+
+ int result = 1;
+ REPORT_RESULT();
+
+ return 0;
+}
diff --git a/tests/runner.py b/tests/runner.py
index 6e259f45..47c1f1be 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -3613,36 +3613,36 @@ Exiting setjmp function, level: 0, prev_jmp: -1
src = open(path_from_root('tests', 'life.c'), 'r').read()
self.do_run(src, '''--------------------------------
[] [] [][][]
- [] [] [] [][] [] [] []
-[] [][] [][] [][][] []
+ [] [] [] [][] [] [] []
+[] [][] [][] [][][] []
[] [] [] [] [][] [] []
[] [][] [] [] [] [] [][][][]
- [][] [][] [] [][][] [] []
- [] [][] [][] [][] [][][]
+ [][] [][] [] [][][] [] []
+ [] [][] [][] [][] [][][]
[][] [][][] [] []
[][] [][] []
[][][]
- []
-
-
-
-
- [][][]
- [] [][] [][]
- [][] [] [][] [][]
- [][] [][]
- []
- [][]
+ []
+
+
+
+
+ [][][]
+ [] [][] [][]
+ [][] [] [][] [][]
+ [][] [][]
+ []
+ [][]
[][] []
[] [][] []
[][][] []
- [] [][]
+ [] [][]
[] [] []
- []
+ []
[] [] []
- [][][]
-
- []
+ [][][]
+
+ []
[][][] []
--------------------------------
''', ['2'], force_c=True)
@@ -4533,6 +4533,8 @@ The current type of b is: 9
self.do_run(src, '*1*', force_c=True)
def test_strtoll_hex(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
# tests strtoll for hex strings (0x...)
src = r'''
#include <stdio.h>
@@ -4559,6 +4561,8 @@ The current type of b is: 9
self.do_run(src, '111111')
def test_strtoll_dec(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
# tests strtoll for decimal strings (0x...)
src = r'''
#include <stdio.h>
@@ -4585,6 +4589,8 @@ The current type of b is: 9
self.do_run(src, '111111')
def test_strtoll_bin(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
# tests strtoll for binary strings (0x...)
src = r'''
#include <stdio.h>
@@ -4606,6 +4612,8 @@ The current type of b is: 9
self.do_run(src, '111')
def test_strtoll_oct(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
# tests strtoll for decimal strings (0x...)
src = r'''
#include <stdio.h>
@@ -6210,13 +6218,13 @@ at function.:blag
printf("|%s|\n", buffy);
int numverts = -1;
- printf("%d\n", sscanf(" numverts 1499\n", " numverts %d", &numverts)); // white space is the same, even if tab vs space
+ printf("%d\n", sscanf(" numverts 1499\n", " numverts %d", &numverts)); // white space is the same, even if tab vs space
printf("%d\n", numverts);
int index;
float u, v;
short start, count;
- printf("%d\n", sscanf(" vert 87 ( 0.481565 0.059481 ) 0 1\n", " vert %d ( %f %f ) %hu %hu", &index, &u, &v, &start, &count));
+ printf("%d\n", sscanf(" vert 87 ( 0.481565 0.059481 ) 0 1\n", " vert %d ( %f %f ) %hu %hu", &index, &u, &v, &start, &count));
printf("%d,%.6f,%.6f,%hu,%hu\n", index, u, v, start, count);
int neg, neg2, neg3 = 0;
@@ -6824,7 +6832,7 @@ def process(filename):
printf("f_blocks: %lu\n", s.f_blocks);
printf("f_bfree: %lu\n", s.f_bfree);
printf("f_bavail: %lu\n", s.f_bavail);
- printf("f_files: %lu\n", s.f_files);
+ printf("f_files: %d\n", s.f_files > 5);
printf("f_ffree: %lu\n", s.f_ffree);
printf("f_favail: %lu\n", s.f_favail);
printf("f_fsid: %lu\n", s.f_fsid);
@@ -6842,7 +6850,7 @@ def process(filename):
f_blocks: 1000000
f_bfree: 500000
f_bavail: 500000
- f_files: 10
+ f_files: 1
f_ffree: 1000000
f_favail: 1000000
f_fsid: 42
@@ -10307,6 +10315,8 @@ f.close()
assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs'
def test_symlink(self):
+ if os.name == 'nt':
+ return self.skip('Windows FS does not need to be tested for symlinks support, since it does not have them.')
open(os.path.join(self.get_dir(), 'foobar.xxx'), 'w').write('int main(){ return 0; }')
os.symlink(os.path.join(self.get_dir(), 'foobar.xxx'), os.path.join(self.get_dir(), 'foobar.c'))
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'foobar.c'), '-o', os.path.join(self.get_dir(), 'foobar')], stdout=PIPE, stderr=PIPE).communicate()
@@ -11132,7 +11142,7 @@ f.close()
output = Popen([os.path.join(self.get_dir(), 'files.o.run')], stdin=open(os.path.join(self.get_dir(), 'stdin')), stdout=PIPE, stderr=PIPE).communicate()
self.assertContained('''size: 37
data: 119,97,107,97,32,119,97,107,97,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35
-loop: 119 97 107 97 32 119 97 107 97 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35
+loop: 119 97 107 97 32 119 97 107 97 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35
input:inter-active
texto
$
@@ -12436,6 +12446,9 @@ elif 'browser' in str(sys.argv):
self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true')
assert ('var GLEmulation' in open(self.in_dir('something.html')).read()) == emulation, "emulation code should be added when asked for"
+ def test_fulles2_sdlproc(self):
+ self.btest('full_es2_sdlproc.c', '1', args=['-s', 'GL_TESTING=1', '-DHAVE_BUILTIN_SINCOS', '-s', 'FULL_ES2=1'])
+
def test_glgears_deriv(self):
self.reftest(path_from_root('tests', 'gears.png'))
Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles_deriv.c'), '-o', 'something.html', '-s', 'GL_TESTING=1',
diff --git a/tools/shared.py b/tools/shared.py
index 7d956293..799a5bbe 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -295,7 +295,7 @@ def check_node_version():
# we re-check sanity when the settings are changed)
# We also re-check sanity and clear the cache when the version changes
-EMSCRIPTEN_VERSION = '1.4.3'
+EMSCRIPTEN_VERSION = '1.4.7'
def generate_sanity():
return EMSCRIPTEN_VERSION + '|' + get_llvm_target()