I want to insert a counter to record how many times the basic block executed.
The steps I took:
I write an LLVM instrumentation pass named BlockProfiling.cpp
I compile it with:
$ g++ -c BlockProfiling.cpp _i/usr/local/include `llvm-config --cxxflag`
it generates a file named BlockPrpfiling.o
I run:
$ g++ -shared -o BlockProfiling.so BlockProfiling.o -L/usr/local/lib `llvm-config --ldflags -libs`
it generates a shared library named BlockProfiling.so
I use it to instrument my file test.bc and generate test.bb.bc:
$opt -load=./BlockProfiling.so -insert-bb-profling test.bc -o test.bb.bc
I use llvm-diff to confirm it's done.
But when I use lli to execute test.bb.bc, there comes an error said:
LLVM ERROR: Program used external function 'llvm_start_func_profiling' which could not be resolved!
Any solutions?
The llvm version is 3.3 and here is my code:
namespace{
struct BlockProfiler: public ModulePass{
static char ID;
BlockProfiler():ModulePass(ID) {
initializeBlock ProfilerPass(*Registry::getPassRegistry());
}
virtual bool runOnModule(Module &M);
}; //end of function profiling pass
} //end of namespace
char BlockProfiler::ID = 0 ;
INITIALIZE_PASS(BlockProfiler, "insert-block-profiling",
"Insert instrumentation for profiling", false, false )
ModulePass *llvm::createBlockProfilerPass() {return new BlockProfiler() ; }
//static RegisterPass<BlockProfilerPass> Y("insert-block-profiling",
"Insert instrumentation for block profiling");
bool BlockProfiler::runOnModule(Module &M){
Function *Main = M.getFunction("main") ;
if(Main == 0)
{
errs()<<" WARING: cannot insert block profiling into a module"
<<" with no main function. \n" ;
return false ; // no main, no instrumentation, and no modify
}
unsigned NumBlocks = 0;
for(Module::iterator I = M.begin(), E = M.end(); I != E ; ++I)
NumBlocks += I->size();
Type *ATy = ArrayType::get(Type::getInt32Ty(M.getContext()), NumBlocks) ;
GlobalVariable *Counters =
new GlobalVariable(M, ATy, false, GlobalValue::InternalLinkage,
Constant::getNullValue(ATy), "BlockProCounters") ;
//Instrument all of the blocks
unsigned i = 0;
for(Module::iterator I = M.begin(), E = M.end(); I != E; ++I){
for(Function::iterator BB = I->begin(), E = I->end() ; BB != E; ++BB )
//Insert counter at the start of the block
IncrementCounterInBlock(BB, i++, Counters);
}
//add the initialization call to main
InsertProfilingInitCall(Main, "llvm_start_block_profiling", Counters);
return true;
}
Related
I am writing a LLVM pass that would insert some codes into programs. Here is a minimal example, which inserts a function call to foo at the beginning of each basic block.
bool MyPass::runOnModule(Module &M) {
std::string foo = "_Z3foov";
LLVMContext &C = M.getContext();
Function *callee = M.getFunction(foo);
if (!callee) {
fprintf(stderr, "Unknown function %s", foo.c_str());
return false;
}
for (auto &F : M) {
if (F.getName().str() == foo) continue;
for (auto &BB : F) {
BasicBlock::iterator IP = BB.getFirstInsertionPt();
IRBuilder<> builder(&(*IP));
builder.CreateCall(callee, std::vector<Value *>(0), "call to foo"); // insert a new instruction.
}
verifyFunction(F);
}
return true;
}
I am seeking the way to locate all the inserted instructions(the call instruction in this example) in the binary after linking (e.g., the ELF format). I think one way to do that is to manipulate the debug information, and store the information in the DWARF sections.
But I can only find the debug information tutorial about how to map the source code to the binary. Is there a way to maintain the information of the manually-added codes?
I have tried a tricky idea: create a virtual source file. The code is just like this:
bool MyPass::runOnModule(Module &M) {
std::string foo = "_Z3foov";
DIBuilder *DBuilder = new DIBuilder(M);
DICompileUnit *CU = DBuilder->createCompileUnit(
dwarf::DW_LANG_C,
DBuilder->createFile("extra_debug_information.db", "."),
"MyPass", 1, "", 1);
DIFile *DFile = DBuilder->createFile(CU->getFilename(), CU->getDirectory());
LLVMContext &C = M.getContext();
Function *callee = M.getFunction(foo);
if (!callee) {
printf("Unknown function %s", foo.c_str());
return false;
}
size_t counter = 0;
for (auto &F : M) {
if (F.getName().str() == foo) continue;
DIScope *FContext = DFile;
DISubprogram *SP = DBuilder->createFunction(
FContext, "extra_debug_subprogram", "", DFile, 1,
DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(None)),
DINode::FlagZero);
F.setSubprogram(SP);
for (auto &BB : F) {
BasicBlock::iterator IP = BB.getFirstInsertionPt();
IRBuilder<> builder(&(*IP));
counter++;
builder.SetCurrentDebugLocation(
DILocation::get(SP->getContext(), counter, counter, SP));
builder.CreateCall(callee, std::vector<Value *>(0), "call to foo");
}
verifyFunction(F);
}
M.addModuleFlag(llvm::Module::Warning, "Dwarf Version", 5);
M.addModuleFlag(llvm::Module::Error, "Debug Info Version",
llvm::DEBUG_METADATA_VERSION);
DBuilder->finalize();
return true;
}
But I got a warning like
clang++ -Xclang -load -Xclang ./libmypass.so test.cpp -emit-llvm -S
clang++ test.ll -o test
test.ll:74:6: error: Expected '!' here
!9 = <temporary!> !{}
^
1 error generated.
make: *** [Makefile:7: test] Error 1
I would be grateful if you could give some suggestions. Thank you very much.
I created a modified version of HowToUseJIT.cpp (llvm version 11.x) that uses IRBuilder class to build a function that calls an external defined in an shared object file.
This example works fine (on my system) when the external has an int argument and return value, but it fails when the argument and return value are double.
The Source for the int case is included below. In addition, the source has instructions, at the top, for transforming it to the double case.
What is wrong with the double version of this example ?
/*
This file is a modified version of the llvm 11.x example HowToUseJIT.cpp:
The file callee.c contains the following text:
int callee(int arg)
{ return arg + 1; }
The shared library callee.so is created from callee.c as follows:
clang -shared callee.c -o callee.so
This example calls the funciton callee from a function that is generated using
the IRBuilder class. It links callee by loading callee.so into its LLJIT.
This works on my sytesm where the progam output is
add1(42) = 43
which is correct.
If I change the type of the function callee from "int (*)(int)" to
"double (*)(double)", the program output is
add1(42) = 4.200000e+01
which is incorrect.
I use following command to change callee.c so that it uses double:
sed -i callee.c \
-e 's|int callee(int arg)|double callee(double arg)|' \
-e 's|return arg + 1;|return arg + 1.0;|'
I use the following command to change this file so that it should porperly
link to the double version of callee:
sed -i add_obj2jit.cpp \
-e '30,$s|"int"|"double"|' \
-e '30,$s|getInt32Ty|getDoubleTy|g' \
-e '/getAddress/s|int|double|g' \
-e 's|int Result = Add1(42);|double Result = Add1(42.0);|
What is wrong with the double version of this example ?
*/
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::orc;
ExitOnError ExitOnErr;
// --------------------------------------------------------------------------
void add_obj2jit(LLJIT* jit, const std::string filename)
{ // load object file into memory_buffer
ErrorOr< std::unique_ptr<MemoryBuffer> > error_or_buffer =
MemoryBuffer::getFile(filename);
std::error_code std_error_code = error_or_buffer.getError();
if( std_error_code )
{ std::string msg = "add_obj2jit: " + filename + "\n";
msg += std_error_code.message();
std::fprintf(stderr, "%s\n", msg.c_str() );
std::exit( std_error_code.value() );
}
std::unique_ptr<MemoryBuffer> memory_buffer(
std::move( error_or_buffer.get() )
);
// move object file into jit
Error error = jit->addObjectFile( std::move(memory_buffer) );
if( error )
{ std::fprintf(stderr, "Can't load object file %s", filename.c_str());
std::exit(1);
}
}
// --------------------------------------------------------------------------
ThreadSafeModule createDemoModule() {
auto Context = std::make_unique<LLVMContext>();
auto M = std::make_unique<Module>("test", *Context);
// functiont_t
// function has a return type of "int" and take an argument of "int".
FunctionType* function_t = FunctionType::get(
Type::getInt32Ty(*Context), {Type::getInt32Ty(*Context)}, false
);
// declare the callee function
AttributeList empty_attributes;
FunctionCallee callee = M->getOrInsertFunction(
"callee", function_t, empty_attributes
);
// Create the add1 function entry and insert this entry into module M.
Function *Add1F = Function::Create(
function_t, Function::ExternalLinkage, "add1", M.get()
);
// Add a basic block to the function. As before, it automatically inserts
// because of the last argument.
BasicBlock *BB = BasicBlock::Create(*Context, "EntryBlock", Add1F);
// Create a basic block builder with default parameters. The builder will
// automatically append instructions to the basic block `BB'.
IRBuilder<> builder(BB);
// Get pointers to the integer argument of the add1 function...
assert(Add1F->arg_begin() +1 == Add1F->arg_end()); // Make sure there's an arg
Argument *ArgX = &*Add1F->arg_begin(); // Get the arg
ArgX->setName("AnArg"); // Give it a nice symbolic name for fun.
// Create the call instruction, inserting it into the end of BB.
Value *Add = builder.CreateCall( callee, {ArgX}, "Add=callee(ArgX)" );
// Create the return instruction and add it to the basic block
builder.CreateRet(Add);
return ThreadSafeModule(std::move(M), std::move(Context));
}
// --------------------------------------------------------------------------
int main(int argc, char *argv[]) {
// Initialize LLVM.
InitLLVM X(argc, argv);
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
cl::ParseCommandLineOptions(argc, argv, "add_obj2jit");
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
// Create an LLJIT instance.
auto J = ExitOnErr(LLJITBuilder().create());
auto M = createDemoModule();
ExitOnErr(J->addIRModule(std::move(M)));
add_obj2jit(J.get(), "callee.so");
// Look up the JIT'd function, cast it to a function pointer, then call it.
auto Add1Sym = ExitOnErr(J->lookup("add1"));
int (*Add1)(int) = (int (*)(int))Add1Sym.getAddress();
int Result = Add1(42);
outs() << "add1(42) = " << Result << "\n";
// return error number
if( Result != 43 )
return 1;
return 0;
}
Andrea:
Thanks for asking to see the IR outupt. Changing the example code line
// llvm::outs() << *M;
to the line
lvm::outs() << *M;
generates this output.
Looking at the output is was clear to me that second sed command had failed.
This was because it was missing a single quote at the end.
When I fixed this, the double case worked. Here is the outptut, including the IR, for the the int case:
; ModuleID = 'test'
source_filename = "test"
declare i32 #callee(i32)
define i32 #add1(i32 %AnArg) {
EntryBlock:
%0 = call i32 #callee(i32 %AnArg)
ret i32 %0
}
add1(42) = 43
Here is the output for the double case:
; ModuleID = 'test'
source_filename = "test"
declare double #callee(double)
define double #add1(double %AnArg) {
EntryBlock:
%0 = call double #callee(double %AnArg)
ret double %0
}
add1(42) = 4.300000e+01
I am trying to code my math model in CPLEX language using C++ (Concert Technology). when I run my code in the compiler window read my inputs and freezes. when trying to debug my code, the visual studio shows the following line as a breakpoint.
//constraint 2
for (cc = 0; cc < NumberOfCourses; cc++) {
IloExpr Constraint2(env);
for (rr = 0; rr < AvailableRooms; rr++) {
Constraint2 += RoomCapacity[rr] * Y[cc][rr];
mod.add(Constraint2 >= Students[cc]); // this line
Constraint2.end();
}
}
i have set up the parameters and variables as follow:
double RoomCapacity[AvailableRooms];
double Students[NumberOfCourses];
//Ycr
IloBoolVarArray2 Y(env, NumberOfCourses);
for (cc = 0; cc < NumberOfCourses; cc++)
Y[cc] = IloBoolVarArray(env, AvailableRooms);
I do not understand what is wrong with my constraint!
Your code is wrong: In the very first inner iteration you add Constraint2 to your model and then you end() that variable. So in the second inner iteration, you are doing Constraint2 += ... while the Constraint2 object was already deleted. This will lead to undefined behavior (hang, crash, ...).
I guess what you wanted to write is this (pull add() and end() out of the inner loop):
for (cc = 0; cc < NumberOfCourses; cc++) {
IloExpr Constraint2(env);
for (rr = 0; rr < AvailableRooms; rr++) {
Constraint2 += RoomCapacity[rr] * Y[cc][rr];
}
mod.add(Constraint2 >= Students[cc]);
Constraint2.end();
}
I'm currently debugging a C/C++ program I wrote that uses Bullet Physics. I'm working on Ubuntu 14.04.3, using g++ 4.8.4, valgrind 3.10.1, and Bullet Physics 2.82.
My compiling command (for debugging) is:
g++ -fno-inline -O0 -g -Wall -Wl,-rpath=./more_libs/lib,--enable-new-dtags -std=gnu++11 -I../bullet-2.82-r2704/Demos/OpenGL/ -I./more_libs/include/ -I../bullet-2.82-r2704/src/ ./main.cpp -L../bullet-2.82-r2704/Glut/ -L./more_libs/lib/ -L./more_libs/mesa -L../bullet-build/Demos/OpenGL/ -L../more_libs/lib/x86_64-linux-gnu -L../bullet-build/src/BulletDynamics/ -L../bullet-build/src/BulletCollision/ -L../bullet-build/src/LinearMath/ -lOpenGLSupport -lGL -lGLU -lglut -lBulletDynamics -lBulletCollision -lLinearMath -lXi -lXxf86vm -lX11 -o ./app
(The difference between debugging and normal is the -O0 and -fno-inline options. I'm adding library paths because I need this program to be portable to a cluster I don't have super-user privileges on.)
Using Valgrind, I have found a ton of similar Uninitialized Value errors that look like this:
Conditional jump or move depends on uninitialised value(s)
at 0x4608C1: btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject**, int, btPersistentManifold**, int, btTypedConstraint**, int, btContactSolverInfo const&, btIDebugDraw*) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
by 0x4591FC: btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject**, int, btPersistentManifold**, int, btTypedConstraint**, int, btContactSolverInfo const&, btIDebugDraw*, btDispatcher*) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
by 0x46A3FF: btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo&) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
by 0x467584: btDiscreteDynamicsWorld::internalSingleStepSimulation(float) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
by 0x465459: btDiscreteDynamicsWorld::stepSimulation(float, int, float) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
by 0x4088F4: NoiseWorld::clientMoveAndDisplay() (NoiseWorld.cpp:288)
by 0x409A28: main (main.cpp:46)
Uninitialised value was created by a heap allocation
at 0x4C2ABBD: malloc (vg_replace_malloc.c:296)
by 0x4EE043: btAlignedAllocDefault(unsigned long, int) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
by 0x40BC09: btHingeConstraint::operator new(unsigned long) (btHingeConstraint.h:103)
by 0x40CF73: NoiseWorld::CreateHinge(int, int, int, float, float, float, float, float, float, float, float, bool) (NoiseWorld.h:332)
by 0x40807C: NoiseWorld::initPhysics() (NoiseWorld.cpp:193)
by 0x4099F4: main (main.cpp:41)
I've tried to look what's going on at solveGroupCacheFriendlySetup(), but when I set a breakpoint there and run GDB, the program doesn't stop---it just runs to completion. I've set the breakpoint by function and by memory (which is constant across valgrind checks), but none of them are getting found/used.
So, here's the question: How can I look at what's going on in solveGroupCacheFriendlySetup() during the run of program? From there, I think I'll be able to figure out what was left uninitialized.
Sorry in advance if this is a simple question, but I haven't been able to find the answer for the past two days. I'm a novice programmer and I've taken on a big project, so I'm guessing there's something simple I'm doing wrong, but I don't know exactly to what ask at this point.
EDIT:
Here is the function I need to look at while running, as per πάντα ῥεῖ's suggestion. The online documentation for this function can be found here: http://bulletphysics.org/Bullet/BulletFull/classbtSequentialImpulseConstraintSolver.html
Note: This portion of the code was not written by me, and I'm not 100% what it does. I'm pretty sure the error lies elsewhere; that I'm not setting up the physics-simulator environment well enough.
Also, I do not know what the valgrind message "(in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)" means in terms of trying to add a breakpoint that GDB can find when running the program.
btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
{
m_fixedBodyId = -1;
BT_PROFILE("solveGroupCacheFriendlySetup");
(void)debugDrawer;
m_maxOverrideNumSolverIterations = 0;
#ifdef BT_ADDITIONAL_DEBUG
//make sure that dynamic bodies exist for all (enabled) constraints
for (int i=0;i<numConstraints;i++)
{
btTypedConstraint* constraint = constraints[i];
if (constraint->isEnabled())
{
if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
{
bool found=false;
for (int b=0;b<numBodies;b++)
{
if (&constraint->getRigidBodyA()==bodies[b])
{
found = true;
break;
}
}
btAssert(found);
}
if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
{
bool found=false;
for (int b=0;b<numBodies;b++)
{
if (&constraint->getRigidBodyB()==bodies[b])
{
found = true;
break;
}
}
btAssert(found);
}
}
}
//make sure that dynamic bodies exist for all contact manifolds
for (int i=0;i<numManifolds;i++)
{
if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
{
bool found=false;
for (int b=0;b<numBodies;b++)
{
if (manifoldPtr[i]->getBody0()==bodies[b])
{
found = true;
break;
}
}
btAssert(found);
}
if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
{
bool found=false;
for (int b=0;b<numBodies;b++)
{
if (manifoldPtr[i]->getBody1()==bodies[b])
{
found = true;
break;
}
}
btAssert(found);
}
}
#endif //BT_ADDITIONAL_DEBUG
for (int i = 0; i < numBodies; i++)
{
bodies[i]->setCompanionId(-1);
}
m_tmpSolverBodyPool.reserve(numBodies+1);
m_tmpSolverBodyPool.resize(0);
//btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
//initSolverBody(&fixedBody,0);
//convert all bodies
for (int i=0;i<numBodies;i++)
{
int bodyId = getOrInitSolverBody(*bodies[i],infoGlobal.m_timeStep);
btRigidBody* body = btRigidBody::upcast(bodies[i]);
if (body && body->getInvMass())
{
btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
btVector3 gyroForce (0,0,0);
if (body->getFlags()&BT_ENABLE_GYROPSCOPIC_FORCE)
{
gyroForce = body->computeGyroscopicForce(infoGlobal.m_maxGyroscopicForce);
solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
}
}
}
if (1)
{
int j;
for (j=0;j<numConstraints;j++)
{
btTypedConstraint* constraint = constraints[j];
constraint->buildJacobian();
constraint->internalSetAppliedImpulse(0.0f);
}
}
//btRigidBody* rb0=0,*rb1=0;
//if (1)
{
{
int totalNumRows = 0;
int i;
m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
//calculate the total number of contraint rows
for (i=0;i<numConstraints;i++)
{
btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
btJointFeedback* fb = constraints[i]->getJointFeedback();
if (fb)
{
fb->m_appliedForceBodyA.setZero();
fb->m_appliedTorqueBodyA.setZero();
fb->m_appliedForceBodyB.setZero();
fb->m_appliedTorqueBodyB.setZero();
}
if (constraints[i]->isEnabled())
{
}
if (constraints[i]->isEnabled())
{
constraints[i]->getInfo1(&info1);
} else
{
info1.m_numConstraintRows = 0;
info1.nub = 0;
}
totalNumRows += info1.m_numConstraintRows;
}
m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
///setup the btSolverConstraints
int currentRow = 0;
for (i=0;i<numConstraints;i++)
{
const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
if (info1.m_numConstraintRows)
{
btAssert(currentRow<totalNumRows);
btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
btTypedConstraint* constraint = constraints[i];
btRigidBody& rbA = constraint->getRigidBodyA();
btRigidBody& rbB = constraint->getRigidBodyB();
int solverBodyIdA = getOrInitSolverBody(rbA,infoGlobal.m_timeStep);
int solverBodyIdB = getOrInitSolverBody(rbB,infoGlobal.m_timeStep);
btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
int j;
for ( j=0;j<info1.m_numConstraintRows;j++)
{
memset(¤tConstraintRow[j],0,sizeof(btSolverConstraint));
currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
currentConstraintRow[j].m_appliedImpulse = 0.f;
currentConstraintRow[j].m_appliedPushImpulse = 0.f;
currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
}
bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
btTypedConstraint::btConstraintInfo2 info2;
info2.fps = 1.f/infoGlobal.m_timeStep;
info2.erp = infoGlobal.m_erp;
info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1;
info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2;
info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
///the size of btSolverConstraint needs be a multiple of btScalar
btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
info2.m_constraintError = ¤tConstraintRow->m_rhs;
currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
info2.m_damping = infoGlobal.m_damping;
info2.cfm = ¤tConstraintRow->m_cfm;
info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit;
info2.m_upperLimit = ¤tConstraintRow->m_upperLimit;
info2.m_numIterations = infoGlobal.m_numIterations;
constraints[i]->getInfo2(&info2);
///finalize the constraint setup
for ( j=0;j<info1.m_numConstraintRows;j++)
{
btSolverConstraint& solverConstraint = currentConstraintRow[j];
if (solverConstraint.m_upperLimit>=constraints[i]->getBreakingImpulseThreshold())
{
solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
}
if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold())
{
solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
}
solverConstraint.m_originalContactPoint = constraint;
{
const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor();
}
{
const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor();
}
{
btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass();
btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal?
btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;
btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1);
sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
sum += iMJlB.dot(solverConstraint.m_contactNormal2);
sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
btScalar fsum = btFabs(sum);
btAssert(fsum > SIMD_EPSILON);
solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?btScalar(1.)/sum : 0.f;
}
{
btScalar rel_vel;
btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0,0,0);
btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0,0,0);
btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0,0,0);
btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ?bodyBPtr->m_externalTorqueImpulse : btVector3(0,0,0);
btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()+externalForceImpulseA)
+ solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()+externalTorqueImpulseA);
btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()+externalForceImpulseB)
+ solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()+externalTorqueImpulseB);
rel_vel = vel1Dotn+vel2Dotn;
btScalar restitution = 0.f;
btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
btScalar velocityError = restitution - rel_vel * info2.m_damping;
btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
solverConstraint.m_appliedImpulse = 0.f;
}
}
}
currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
}
}
convertContacts(manifoldPtr,numManifolds,infoGlobal);
}
// btContactSolverInfo info = infoGlobal;
int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
int numConstraintPool = m_tmpSolverContactConstraintPool.size();
int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
///#todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2);
else
m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
{
int i;
for (i=0;i<numNonContactPool;i++)
{
m_orderNonContactConstraintPool[i] = i;
}
for (i=0;i<numConstraintPool;i++)
{
m_orderTmpConstraintPool[i] = i;
}
for (i=0;i<numFrictionPool;i++)
{
m_orderFrictionConstraintPool[i] = i;
}
}
return 0.f;
}
If you want to debug your program when running it under valgrind,
then you can do the following:
valgrind --vgdb-error=1 .... rest of the args as usual
Then on first error, valgrind will stop, and will wait for gdb to connect.
You can then use gdb commands and/or valgrind specific features to
investigate the problem. You can continue execution using the gdb continue
command, to stop on the next error.
See http://www.valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver for more information.
I'm writing a module level pass and inside the runOnModule function I have the following bit of code:
for (Module::iterator F = M.begin(), FEND = M.end(); F != FEND; ++F){
if (!(*F).isDeclaration()){
LoopInfo* LI = new LoopInfo();
LI->runOnFunction(*F);
lis.push_back(LI);
for(LoopInfo::iterator L = LI->begin(), LEND = LI->end(); L != LEND; ++L){
// add all functions
loops.push_back(*L);
}
}
}
This all compiles but when I run it I get the following error:
opt: /include/llvm/PassAnalysisSupport.h:200: AnalysisType
&llvm::Pass::getAnalysis() const [AnalysisType = llvm::DominatorTreeWrapperPass]:
Assertion `Resolver && "Pass has not been inserted into a PassManager object!"' failed.
I tried putting the below code in ``lib/Transforms/IPO/PassManagerBuilder.cppin thepopulateModulePassManager` method but nothing happened.
if (EnableMergeFunctions) {
MPM.add(createMergeFunctionsPass());
MPM.add(createJumpThreadingPass()); // Merge consecutive conditionals
MPM.add(createInstructionCombiningPass());
MPM.add(createCFGSimplificationPass());
}
Any help would be great thanks.