Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
2f2357f6
"plugins/drude/vscode:/vscode.git/clone" did not exist on "1d93120a697299d8fcbfeb10088d38eaee7d1c3f"
Commit
2f2357f6
authored
Sep 18, 2014
by
peastman
Browse files
Fixed an illegal memory access
parent
96b61389
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
370 additions
and
368 deletions
+370
-368
libraries/lepton/src/CompiledExpression.cpp
libraries/lepton/src/CompiledExpression.cpp
+370
-368
No files found.
libraries/lepton/src/CompiledExpression.cpp
View file @
2f2357f6
/* -------------------------------------------------------------------------- *
/* -------------------------------------------------------------------------- *
* Lepton *
* Lepton *
* -------------------------------------------------------------------------- *
* -------------------------------------------------------------------------- *
* This is part of the Lepton expression parser originating from *
* This is part of the Lepton expression parser originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* 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: *
* Software is furnished to do so, subject to the following conditions: *
* *
* *
* The above copyright notice and this permission notice shall be included in *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* all copies or substantial portions of the Software. *
* *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* 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 *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
#include "lepton/CompiledExpression.h"
#include "lepton/CompiledExpression.h"
#include "lepton/Operation.h"
#include "lepton/Operation.h"
#include "lepton/ParsedExpression.h"
#include "lepton/ParsedExpression.h"
#include <utility>
#include <utility>
using
namespace
Lepton
;
using
namespace
Lepton
;
using
namespace
std
;
using
namespace
std
;
#ifdef LEPTON_USE_JIT
#ifdef LEPTON_USE_JIT
using
namespace
asmjit
;
using
namespace
asmjit
;
#endif
#endif
CompiledExpression
::
CompiledExpression
()
:
jitCode
(
NULL
)
{
CompiledExpression
::
CompiledExpression
()
:
jitCode
(
NULL
)
{
}
}
CompiledExpression
::
CompiledExpression
(
const
ParsedExpression
&
expression
)
:
jitCode
(
NULL
)
{
CompiledExpression
::
CompiledExpression
(
const
ParsedExpression
&
expression
)
:
jitCode
(
NULL
)
{
ParsedExpression
expr
=
expression
.
optimize
();
// Just in case it wasn't already optimized.
ParsedExpression
expr
=
expression
.
optimize
();
// Just in case it wasn't already optimized.
vector
<
pair
<
ExpressionTreeNode
,
int
>
>
temps
;
vector
<
pair
<
ExpressionTreeNode
,
int
>
>
temps
;
compileExpression
(
expr
.
getRootNode
(),
temps
);
compileExpression
(
expr
.
getRootNode
(),
temps
);
int
maxArguments
=
1
;
int
maxArguments
=
1
;
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
if
(
operation
[
i
]
->
getNumArguments
()
>
maxArguments
)
if
(
operation
[
i
]
->
getNumArguments
()
>
maxArguments
)
maxArguments
=
operation
[
i
]
->
getNumArguments
();
maxArguments
=
operation
[
i
]
->
getNumArguments
();
argValues
.
resize
(
maxArguments
);
argValues
.
resize
(
maxArguments
);
#ifdef LEPTON_USE_JIT
#ifdef LEPTON_USE_JIT
generateJitCode
();
generateJitCode
();
#endif
#endif
}
}
CompiledExpression
::~
CompiledExpression
()
{
CompiledExpression
::~
CompiledExpression
()
{
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
if
(
operation
[
i
]
!=
NULL
)
if
(
operation
[
i
]
!=
NULL
)
delete
operation
[
i
];
delete
operation
[
i
];
}
}
CompiledExpression
::
CompiledExpression
(
const
CompiledExpression
&
expression
)
:
jitCode
(
NULL
)
{
CompiledExpression
::
CompiledExpression
(
const
CompiledExpression
&
expression
)
:
jitCode
(
NULL
)
{
*
this
=
expression
;
*
this
=
expression
;
}
}
CompiledExpression
&
CompiledExpression
::
operator
=
(
const
CompiledExpression
&
expression
)
{
CompiledExpression
&
CompiledExpression
::
operator
=
(
const
CompiledExpression
&
expression
)
{
arguments
=
expression
.
arguments
;
arguments
=
expression
.
arguments
;
target
=
expression
.
target
;
target
=
expression
.
target
;
variableIndices
=
expression
.
variableIndices
;
variableIndices
=
expression
.
variableIndices
;
variableNames
=
expression
.
variableNames
;
variableNames
=
expression
.
variableNames
;
workspace
.
resize
(
expression
.
workspace
.
size
());
workspace
.
resize
(
expression
.
workspace
.
size
());
argValues
.
resize
(
expression
.
argValues
.
size
());
argValues
.
resize
(
expression
.
argValues
.
size
());
operation
.
resize
(
expression
.
operation
.
size
());
operation
.
resize
(
expression
.
operation
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
operation
[
i
]
=
expression
.
operation
[
i
]
->
clone
();
operation
[
i
]
=
expression
.
operation
[
i
]
->
clone
();
#ifdef LEPTON_USE_JIT
#ifdef LEPTON_USE_JIT
generateJitCode
();
generateJitCode
();
#endif
#endif
return
*
this
;
return
*
this
;
}
}
void
CompiledExpression
::
compileExpression
(
const
ExpressionTreeNode
&
node
,
vector
<
pair
<
ExpressionTreeNode
,
int
>
>&
temps
)
{
void
CompiledExpression
::
compileExpression
(
const
ExpressionTreeNode
&
node
,
vector
<
pair
<
ExpressionTreeNode
,
int
>
>&
temps
)
{
if
(
findTempIndex
(
node
,
temps
)
!=
-
1
)
if
(
findTempIndex
(
node
,
temps
)
!=
-
1
)
return
;
// We have already processed a node identical to this one.
return
;
// We have already processed a node identical to this one.
// Process the child nodes.
// Process the child nodes.
vector
<
int
>
args
;
vector
<
int
>
args
;
for
(
int
i
=
0
;
i
<
node
.
getChildren
().
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
node
.
getChildren
().
size
();
i
++
)
{
compileExpression
(
node
.
getChildren
()[
i
],
temps
);
compileExpression
(
node
.
getChildren
()[
i
],
temps
);
args
.
push_back
(
findTempIndex
(
node
.
getChildren
()[
i
],
temps
));
args
.
push_back
(
findTempIndex
(
node
.
getChildren
()[
i
],
temps
));
}
}
// Process this node.
// Process this node.
if
(
node
.
getOperation
().
getId
()
==
Operation
::
VARIABLE
)
{
if
(
node
.
getOperation
().
getId
()
==
Operation
::
VARIABLE
)
{
variableIndices
[
node
.
getOperation
().
getName
()]
=
(
int
)
workspace
.
size
();
variableIndices
[
node
.
getOperation
().
getName
()]
=
(
int
)
workspace
.
size
();
variableNames
.
insert
(
node
.
getOperation
().
getName
());
variableNames
.
insert
(
node
.
getOperation
().
getName
());
}
}
else
{
else
{
int
stepIndex
=
(
int
)
arguments
.
size
();
int
stepIndex
=
(
int
)
arguments
.
size
();
arguments
.
push_back
(
vector
<
int
>
());
arguments
.
push_back
(
vector
<
int
>
());
target
.
push_back
((
int
)
workspace
.
size
());
target
.
push_back
((
int
)
workspace
.
size
());
operation
.
push_back
(
node
.
getOperation
().
clone
());
operation
.
push_back
(
node
.
getOperation
().
clone
());
if
(
args
.
size
()
==
0
)
if
(
args
.
size
()
==
0
)
arguments
[
stepIndex
].
push_back
(
0
);
// The value won't actually be used. We just need something there.
arguments
[
stepIndex
].
push_back
(
0
);
// The value won't actually be used. We just need something there.
else
{
else
{
// If the arguments are sequential, we can just pass a pointer to the first one.
// If the arguments are sequential, we can just pass a pointer to the first one.
bool
sequential
=
true
;
bool
sequential
=
true
;
for
(
int
i
=
1
;
i
<
args
.
size
();
i
++
)
for
(
int
i
=
1
;
i
<
args
.
size
();
i
++
)
if
(
args
[
i
]
!=
args
[
i
-
1
]
+
1
)
if
(
args
[
i
]
!=
args
[
i
-
1
]
+
1
)
sequential
=
false
;
sequential
=
false
;
if
(
sequential
)
if
(
sequential
)
arguments
[
stepIndex
].
push_back
(
args
[
0
]);
arguments
[
stepIndex
].
push_back
(
args
[
0
]);
else
else
arguments
[
stepIndex
]
=
args
;
arguments
[
stepIndex
]
=
args
;
}
}
}
}
temps
.
push_back
(
make_pair
(
node
,
workspace
.
size
()));
temps
.
push_back
(
make_pair
(
node
,
workspace
.
size
()));
workspace
.
push_back
(
0.0
);
workspace
.
push_back
(
0.0
);
}
}
int
CompiledExpression
::
findTempIndex
(
const
ExpressionTreeNode
&
node
,
vector
<
pair
<
ExpressionTreeNode
,
int
>
>&
temps
)
{
int
CompiledExpression
::
findTempIndex
(
const
ExpressionTreeNode
&
node
,
vector
<
pair
<
ExpressionTreeNode
,
int
>
>&
temps
)
{
for
(
int
i
=
0
;
i
<
(
int
)
temps
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
temps
.
size
();
i
++
)
if
(
temps
[
i
].
first
==
node
)
if
(
temps
[
i
].
first
==
node
)
return
i
;
return
i
;
return
-
1
;
return
-
1
;
}
}
const
set
<
string
>&
CompiledExpression
::
getVariables
()
const
{
const
set
<
string
>&
CompiledExpression
::
getVariables
()
const
{
return
variableNames
;
return
variableNames
;
}
}
double
&
CompiledExpression
::
getVariableReference
(
const
string
&
name
)
{
double
&
CompiledExpression
::
getVariableReference
(
const
string
&
name
)
{
map
<
string
,
int
>::
iterator
index
=
variableIndices
.
find
(
name
);
map
<
string
,
int
>::
iterator
index
=
variableIndices
.
find
(
name
);
if
(
index
==
variableIndices
.
end
())
if
(
index
==
variableIndices
.
end
())
throw
Exception
(
"getVariableReference: Unknown variable '"
+
name
+
"'"
);
throw
Exception
(
"getVariableReference: Unknown variable '"
+
name
+
"'"
);
return
workspace
[
index
->
second
];
return
workspace
[
index
->
second
];
}
}
double
CompiledExpression
::
evaluate
()
const
{
double
CompiledExpression
::
evaluate
()
const
{
#ifdef LEPTON_USE_JIT
#ifdef LEPTON_USE_JIT
return
((
double
(
*
)())
jitCode
)();
return
((
double
(
*
)())
jitCode
)();
#else
#else
// Loop over the operations and evaluate each one.
// Loop over the operations and evaluate each one.
for
(
int
step
=
0
;
step
<
operation
.
size
();
step
++
)
{
for
(
int
step
=
0
;
step
<
operation
.
size
();
step
++
)
{
const
vector
<
int
>&
args
=
arguments
[
step
];
const
vector
<
int
>&
args
=
arguments
[
step
];
if
(
args
.
size
()
==
1
)
if
(
args
.
size
()
==
1
)
workspace
[
target
[
step
]]
=
operation
[
step
]
->
evaluate
(
&
workspace
[
args
[
0
]],
dummyVariables
);
workspace
[
target
[
step
]]
=
operation
[
step
]
->
evaluate
(
&
workspace
[
args
[
0
]],
dummyVariables
);
else
{
else
{
for
(
int
i
=
0
;
i
<
args
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
args
.
size
();
i
++
)
argValues
[
i
]
=
workspace
[
args
[
i
]];
argValues
[
i
]
=
workspace
[
args
[
i
]];
workspace
[
target
[
step
]]
=
operation
[
step
]
->
evaluate
(
&
argValues
[
0
],
dummyVariables
);
workspace
[
target
[
step
]]
=
operation
[
step
]
->
evaluate
(
&
argValues
[
0
],
dummyVariables
);
}
}
}
}
return
workspace
[
workspace
.
size
()
-
1
];
return
workspace
[
workspace
.
size
()
-
1
];
#endif
#endif
}
}
#ifdef LEPTON_USE_JIT
#ifdef LEPTON_USE_JIT
static
double
evaluateOperation
(
Operation
*
op
,
double
*
args
)
{
static
double
evaluateOperation
(
Operation
*
op
,
double
*
args
)
{
map
<
string
,
double
>*
dummyVariables
=
NULL
;
map
<
string
,
double
>*
dummyVariables
=
NULL
;
return
op
->
evaluate
(
args
,
*
dummyVariables
);
return
op
->
evaluate
(
args
,
*
dummyVariables
);
}
}
void
CompiledExpression
::
generateJitCode
()
{
void
CompiledExpression
::
generateJitCode
()
{
X86Compiler
c
(
&
runtime
);
X86Compiler
c
(
&
runtime
);
c
.
addFunc
(
kFuncConvHost
,
FuncBuilder0
<
double
>
());
c
.
addFunc
(
kFuncConvHost
,
FuncBuilder0
<
double
>
());
vector
<
X86XmmVar
>
workspaceVar
(
workspace
.
size
());
vector
<
X86XmmVar
>
workspaceVar
(
workspace
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)
workspaceVar
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
workspaceVar
.
size
();
i
++
)
workspaceVar
[
i
]
=
c
.
newXmmVar
(
kX86VarTypeXmmSd
);
workspaceVar
[
i
]
=
c
.
newXmmVar
(
kX86VarTypeXmmSd
);
X86GpVar
workspacePointer
(
c
);
X86GpVar
workspacePointer
(
c
);
X86GpVar
argsPointer
(
c
);
X86GpVar
argsPointer
(
c
);
c
.
mov
(
workspacePointer
,
imm_ptr
(
&
workspace
[
0
]));
c
.
mov
(
workspacePointer
,
imm_ptr
(
&
workspace
[
0
]));
c
.
mov
(
argsPointer
,
imm_ptr
(
&
argValues
[
0
]));
c
.
mov
(
argsPointer
,
imm_ptr
(
&
argValues
[
0
]));
// Load the arguments into variables.
// Load the arguments into variables.
for
(
set
<
string
>::
const_iterator
iter
=
variableNames
.
begin
();
iter
!=
variableNames
.
end
();
++
iter
)
{
for
(
set
<
string
>::
const_iterator
iter
=
variableNames
.
begin
();
iter
!=
variableNames
.
end
();
++
iter
)
{
map
<
string
,
int
>::
iterator
index
=
variableIndices
.
find
(
*
iter
);
map
<
string
,
int
>::
iterator
index
=
variableIndices
.
find
(
*
iter
);
c
.
movsd
(
workspaceVar
[
index
->
second
],
x86
::
ptr
(
workspacePointer
,
8
*
index
->
second
,
0
));
c
.
movsd
(
workspaceVar
[
index
->
second
],
x86
::
ptr
(
workspacePointer
,
8
*
index
->
second
,
0
));
}
}
// Make a list of all constants that will be needed for evaluation.
// Make a list of all constants that will be needed for evaluation.
vector
<
int
>
operationConstantIndex
(
operation
.
size
(),
-
1
);
vector
<
int
>
operationConstantIndex
(
operation
.
size
(),
-
1
);
for
(
int
step
=
0
;
step
<
(
int
)
operation
.
size
();
step
++
)
{
for
(
int
step
=
0
;
step
<
(
int
)
operation
.
size
();
step
++
)
{
// Find the constant value (if any) used by this operation.
// Find the constant value (if any) used by this operation.
Operation
&
op
=
*
operation
[
step
];
Operation
&
op
=
*
operation
[
step
];
double
value
;
double
value
;
if
(
op
.
getId
()
==
Operation
::
CONSTANT
)
if
(
op
.
getId
()
==
Operation
::
CONSTANT
)
value
=
dynamic_cast
<
Operation
::
Constant
&>
(
op
).
getValue
();
value
=
dynamic_cast
<
Operation
::
Constant
&>
(
op
).
getValue
();
else
if
(
op
.
getId
()
==
Operation
::
ADD_CONSTANT
)
else
if
(
op
.
getId
()
==
Operation
::
ADD_CONSTANT
)
value
=
dynamic_cast
<
Operation
::
AddConstant
&>
(
op
).
getValue
();
value
=
dynamic_cast
<
Operation
::
AddConstant
&>
(
op
).
getValue
();
else
if
(
op
.
getId
()
==
Operation
::
MULTIPLY_CONSTANT
)
else
if
(
op
.
getId
()
==
Operation
::
MULTIPLY_CONSTANT
)
value
=
dynamic_cast
<
Operation
::
MultiplyConstant
&>
(
op
).
getValue
();
value
=
dynamic_cast
<
Operation
::
MultiplyConstant
&>
(
op
).
getValue
();
else
if
(
op
.
getId
()
==
Operation
::
RECIPROCAL
)
else
if
(
op
.
getId
()
==
Operation
::
RECIPROCAL
)
value
=
1.0
;
value
=
1.0
;
else
if
(
op
.
getId
()
==
Operation
::
STEP
)
else
if
(
op
.
getId
()
==
Operation
::
STEP
)
value
=
1.0
;
value
=
1.0
;
else
if
(
op
.
getId
()
==
Operation
::
DELTA
)
else
if
(
op
.
getId
()
==
Operation
::
DELTA
)
value
=
1.0
;
value
=
1.0
;
else
else
continue
;
continue
;
// See if we already have a variable for this constant.
// See if we already have a variable for this constant.
for
(
int
i
=
0
;
i
<
(
int
)
constants
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
constants
.
size
();
i
++
)
if
(
value
==
constants
[
i
])
{
if
(
value
==
constants
[
i
])
{
operationConstantIndex
[
step
]
=
i
;
operationConstantIndex
[
step
]
=
i
;
break
;
break
;
}
}
if
(
operationConstantIndex
[
step
]
==
-
1
)
{
if
(
operationConstantIndex
[
step
]
==
-
1
)
{
operationConstantIndex
[
step
]
=
constants
.
size
();
operationConstantIndex
[
step
]
=
constants
.
size
();
constants
.
push_back
(
value
);
constants
.
push_back
(
value
);
}
}
}
}
// Load constants into variables.
// Load constants into variables.
vector
<
X86XmmVar
>
constantVar
(
constants
.
size
());
vector
<
X86XmmVar
>
constantVar
(
constants
.
size
());
X86GpVar
constantsPointer
(
c
);
if
(
constants
.
size
()
>
0
)
{
c
.
mov
(
constantsPointer
,
imm_ptr
(
&
constants
[
0
]));
X86GpVar
constantsPointer
(
c
);
for
(
int
i
=
0
;
i
<
(
constants
.
size
());
i
++
)
{
c
.
mov
(
constantsPointer
,
imm_ptr
(
&
constants
[
0
]));
constantVar
[
i
]
=
c
.
newXmmVar
(
kX86VarTypeXmmSd
);
for
(
int
i
=
0
;
i
<
(
int
)
constants
.
size
();
i
++
)
{
c
.
movsd
(
constantVar
[
i
],
x86
::
ptr
(
constantsPointer
,
8
*
i
,
0
));
constantVar
[
i
]
=
c
.
newXmmVar
(
kX86VarTypeXmmSd
);
}
c
.
movsd
(
constantVar
[
i
],
x86
::
ptr
(
constantsPointer
,
8
*
i
,
0
));
}
// Evaluate the operations.
}
for
(
int
step
=
0
;
step
<
(
int
)
operation
.
size
();
step
++
)
{
// Evaluate the operations.
Operation
&
op
=
*
operation
[
step
];
vector
<
int
>
args
=
arguments
[
step
];
for
(
int
step
=
0
;
step
<
(
int
)
operation
.
size
();
step
++
)
{
if
(
args
.
size
()
==
1
)
{
Operation
&
op
=
*
operation
[
step
];
// One or more sequential arguments. Fill out the list.
vector
<
int
>
args
=
arguments
[
step
];
if
(
args
.
size
()
==
1
)
{
for
(
int
i
=
1
;
i
<
op
.
getNumArguments
();
i
++
)
// One or more sequential arguments. Fill out the list.
args
.
push_back
(
args
[
0
]
+
i
);
}
for
(
int
i
=
1
;
i
<
op
.
getNumArguments
();
i
++
)
args
.
push_back
(
args
[
0
]
+
i
);
// Generate instructions to execute this operation.
}
switch
(
op
.
getId
())
{
// Generate instructions to execute this operation.
case
Operation
::
CONSTANT
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
switch
(
op
.
getId
())
{
break
;
case
Operation
::
CONSTANT
:
case
Operation
::
ADD
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
c
.
addsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
case
Operation
::
ADD
:
break
;
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
SUBTRACT
:
c
.
addsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
c
.
subsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
case
Operation
::
SUBTRACT
:
break
;
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
MULTIPLY
:
c
.
subsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
case
Operation
::
MULTIPLY
:
break
;
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
DIVIDE
:
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
c
.
divsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
case
Operation
::
DIVIDE
:
break
;
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
NEGATE
:
c
.
divsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
c
.
xorps
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
target
[
step
]]);
break
;
c
.
subsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
NEGATE
:
break
;
c
.
xorps
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
target
[
step
]]);
case
Operation
::
SQRT
:
c
.
subsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
sqrtsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
break
;
case
Operation
::
SQRT
:
case
Operation
::
EXP
:
c
.
sqrtsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
exp
);
break
;
break
;
case
Operation
::
EXP
:
case
Operation
::
LOG
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
exp
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
log
);
break
;
break
;
case
Operation
::
LOG
:
case
Operation
::
SIN
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
log
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
sin
);
break
;
break
;
case
Operation
::
SIN
:
case
Operation
::
COS
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
sin
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
cos
);
break
;
break
;
case
Operation
::
COS
:
case
Operation
::
TAN
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
cos
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
tan
);
break
;
break
;
case
Operation
::
TAN
:
case
Operation
::
ASIN
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
tan
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
asin
);
break
;
break
;
case
Operation
::
ASIN
:
case
Operation
::
ACOS
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
asin
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
acos
);
break
;
break
;
case
Operation
::
ACOS
:
case
Operation
::
ATAN
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
acos
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
atan
);
break
;
break
;
case
Operation
::
ATAN
:
case
Operation
::
SINH
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
atan
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
sinh
);
break
;
break
;
case
Operation
::
SINH
:
case
Operation
::
COSH
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
sinh
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
cosh
);
break
;
break
;
case
Operation
::
COSH
:
case
Operation
::
TANH
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
cosh
);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
tanh
);
break
;
break
;
case
Operation
::
TANH
:
case
Operation
::
STEP
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
tanh
);
c
.
xorps
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
target
[
step
]]);
break
;
c
.
cmpsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
imm
(
18
));
// Comparison mode is _CMP_LE_OQ = 18
case
Operation
::
STEP
:
c
.
andps
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
c
.
xorps
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
target
[
step
]]);
break
;
c
.
cmpsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
imm
(
18
));
// Comparison mode is _CMP_LE_OQ = 18
case
Operation
::
DELTA
:
c
.
andps
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
c
.
xorps
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
target
[
step
]]);
break
;
c
.
cmpsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
imm
(
16
));
// Comparison mode is _CMP_EQ_OS = 16
case
Operation
::
DELTA
:
c
.
andps
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
c
.
xorps
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
target
[
step
]]);
break
;
c
.
cmpsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
imm
(
16
));
// Comparison mode is _CMP_EQ_OS = 16
case
Operation
::
SQUARE
:
c
.
andps
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
SQUARE
:
break
;
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
CUBE
:
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
CUBE
:
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
RECIPROCAL
:
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
break
;
c
.
divsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
RECIPROCAL
:
break
;
c
.
movsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
case
Operation
::
ADD_CONSTANT
:
c
.
divsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
c
.
addsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
case
Operation
::
ADD_CONSTANT
:
break
;
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
MULTIPLY_CONSTANT
:
c
.
addsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
case
Operation
::
MULTIPLY_CONSTANT
:
break
;
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
case
Operation
::
ABS
:
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
fabs
);
break
;
break
;
case
Operation
::
ABS
:
default:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
fabs
);
// Just invoke evaluateOperation().
break
;
default:
for
(
int
i
=
0
;
i
<
(
int
)
args
.
size
();
i
++
)
// Just invoke evaluateOperation().
c
.
movsd
(
x86
::
ptr
(
argsPointer
,
8
*
i
,
0
),
workspaceVar
[
args
[
i
]]);
X86GpVar
fn
(
c
,
kVarTypeIntPtr
);
for
(
int
i
=
0
;
i
<
(
int
)
args
.
size
();
i
++
)
c
.
mov
(
fn
,
imm_ptr
((
void
*
)
evaluateOperation
));
c
.
movsd
(
x86
::
ptr
(
argsPointer
,
8
*
i
,
0
),
workspaceVar
[
args
[
i
]]);
X86CallNode
*
call
=
c
.
call
(
fn
,
kFuncConvHost
,
FuncBuilder2
<
double
,
Operation
*
,
double
*>
());
X86GpVar
fn
(
c
,
kVarTypeIntPtr
);
call
->
setArg
(
0
,
imm_ptr
(
&
op
));
c
.
mov
(
fn
,
imm_ptr
((
void
*
)
evaluateOperation
));
call
->
setArg
(
1
,
imm_ptr
(
&
argValues
[
0
]));
X86CallNode
*
call
=
c
.
call
(
fn
,
kFuncConvHost
,
FuncBuilder2
<
double
,
Operation
*
,
double
*>
());
call
->
setRet
(
0
,
workspaceVar
[
target
[
step
]]);
call
->
setArg
(
0
,
imm_ptr
(
&
op
));
}
call
->
setArg
(
1
,
imm_ptr
(
&
argValues
[
0
]));
}
call
->
setRet
(
0
,
workspaceVar
[
target
[
step
]]);
c
.
ret
(
workspaceVar
[
workspace
.
size
()
-
1
]);
}
c
.
endFunc
();
}
jitCode
=
c
.
make
();
c
.
ret
(
workspaceVar
[
workspace
.
size
()
-
1
]);
}
c
.
endFunc
();
jitCode
=
c
.
make
();
void
CompiledExpression
::
generateSingleArgCall
(
X86Compiler
&
c
,
X86XmmVar
&
dest
,
X86XmmVar
&
arg
,
double
(
*
function
)(
double
))
{
}
X86GpVar
fn
(
c
,
kVarTypeIntPtr
);
c
.
mov
(
fn
,
imm_ptr
((
void
*
)
function
));
void
CompiledExpression
::
generateSingleArgCall
(
X86Compiler
&
c
,
X86XmmVar
&
dest
,
X86XmmVar
&
arg
,
double
(
*
function
)(
double
))
{
X86CallNode
*
call
=
c
.
call
(
fn
,
kFuncConvHost
,
FuncBuilder1
<
double
,
double
>
());
X86GpVar
fn
(
c
,
kVarTypeIntPtr
);
call
->
setArg
(
0
,
arg
);
c
.
mov
(
fn
,
imm_ptr
((
void
*
)
function
));
call
->
setRet
(
0
,
dest
);
X86CallNode
*
call
=
c
.
call
(
fn
,
kFuncConvHost
,
FuncBuilder1
<
double
,
double
>
());
}
call
->
setArg
(
0
,
arg
);
call
->
setRet
(
0
,
dest
);
}
#endif
#endif
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment