"plugins/drude/vscode:/vscode.git/clone" did not exist on "1d93120a697299d8fcbfeb10088d38eaee7d1c3f"
Commit 2f2357f6 authored by peastman's avatar peastman
Browse files

Fixed an illegal memory access

parent 96b61389
/* -------------------------------------------------------------------------- * /* -------------------------------------------------------------------------- *
* 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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment