Add an llvm instruction - c++11

I'm new to LLVM and I was wondering if you could help me building a pass to duplicate instructions in LLVM IR, the problem I'm facing is that the cloned instructions couldn't be returned using (user class), is this the correct way to do it ? are there any other ways (excluding this http://llvm.org/docs/ExtendingLLVM.html)
My pass:
BasicBlock *B = I->getParent();
if (auto *op = dyn_cast<BinaryOperator>(&*I))
{
auto temp = op->clone();
B->getInstList().insert(op, temp);
temp->setName(op->getName());
if (temp->getOpcode() == Instruction::Add)
{
IRBuilder<> builder(temp); //building the cloned instruction
Value *lhs = temp->getOperand(0);
Value *rhs = temp->getOperand(1);
Value *add1 = builder.CreateAdd(lhs, rhs);
for (auto &v : temp->uses()) {
User *user = v.getUser(); // A User is anything with operands.
user->setOperand(v.getOperandNo(), add1);
}
}
}

BasicBlock *B = I->getParent();
if (auto *op = dyn_cast<BinaryOperator>(&*I))
{
auto temp = op->clone();
B->getInstList().insert(op, temp);
temp->setName(op->getName());
At this point you have successfully cloned your instruction and inserted it in the BasicBlock where the original instruction lives.
if (temp->getOpcode() == Instruction::Add)
{
IRBuilder<> builder(temp); //building the cloned instruction
Value *lhs = temp->getOperand(0);
Value *rhs = temp->getOperand(1);
Value *add1 = builder.CreateAdd(lhs, rhs);
Now you are building an IRBuilder. An IRBuilder as a helper class that allows you easy insertion of instructions in your code. But it does not build your temp instruction. The temp instruction is already there from calling clone an inserting it in the BasicBlock.
You create another copy of your original instruction (add1).
for (auto &v : temp->uses()) {
User *user = v.getUser(); // A User is anything with operands.
user->setOperand(v.getOperandNo(), add1);
}
Here you are updating all users of temp. But at this point temp has no users. temp is just a clone of your original instruction. You have created two copies of your original instruction that are not used and will be removed by dead code elimination.
What you want to do is to replace all uses of op by one of your copies.
An easier way to achieve this is to use RAUW ReplaceAllUsesWith.
BasicBlock *B = I->getParent();
if (auto *op = dyn_cast<BinaryOperator>(&*I))
{
auto temp = op->clone();
B->getInstList().insert(op, temp);
temp->setName(op->getName());
op->replaceAllUsesWith(temp);
}
With RAUW now op is dead (i.e., has no users) and your cloned instruction is alive.

Related

std::vector erase issue with MSVC 2010

ALL,
I have a class defined that just holds the data (different types of data). I also have std::vector that holds a pointers to objects of this class.
Something like this:
class Foo
{
};
class Bar
{
private:
std::vector<Foo *> m_fooVector;
};
At one point of time in my program I want to remove an element from this vector. And so I write following:
for (std::vector<Foo *>::iterator it = m_fooVector.begin(); it <= m_fooVector.end(); )
{
if( checking it condition is true )
{
delete (*it);
(*it) = NULL;
m_fooVector.erase( it );
}
}
The problem is that the erase operation fails. When I open the debugger I still see this element inside the vector and when the program finishes it crashes because the element is half way here.
In another function I am trying to remove the simple std::wstring from the vector and everything works fine - string is removed and the size of the vector decreased.
What could be the problem for such behavior? I could of course try to check the erase function in MSVC standard library, but I don't even know where to start.
TIA!!!
Your loop is incorrect:
for (std::vector<Foo *>::iterator it = m_fooVector.begin(); it != m_fooVector.end(); )
{
if (/*checking it condition is true*/)
{
delete *it;
// *it = NULL; // Not needed
it = m_fooVector.erase(it);
} else {
++it;
}
}
Traditional way is erase-remove idiom, but as you have to call delete first (smart pointer would avoid this issue), you might use std::partition instead of std::remove:
auto it = std::partition(m_fooVector.begin(), m_fooVector.end(), ShouldBeKeptFunc);
for (std::vector<Foo *>::iterator it = m_fooVector.begin(); it != m_fooVector.end(); ++it) {
delete *it;
}
m_fooVector.erase(it, m_fooVector.end());

What is the Cocoa method for doing the Carbon FSExchangeObjectsCompat call?

There was this great function in the old MoreFilesX, FSExchangeObjectsCompat, that "exchanges the data between two files". It was typically used as part of a safe-save approach, where a temp file was written out, then FSExchangeObjectsCompat was called to exchange the newly-saved temp file with the old "original" file. It preserved all the metadata, privileges, etc.
I'm seeing a failure with this function on High Sierra, on APFS volumes, which never failed on HFS+ volumes. Not a big surprise -- many of those calls are deprecated.
But what is the Cocoa NSFileManager method of doing the same thing?
You want -[NSFileManager replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:].
You can do something similar using lower-level functions. Here's code I wrote to be used with a pre-10.12 SDK. You can make it somewhat simpler if you compile against the 10.12 SDK or later, and even simpler if you have a deployment target that is 10.12 or later.
#ifndef RENAME_SWAP
#define RENAME_SWAP 0x00000002
#endif
/*!
#function ExchangeFiles
#abstract Given full paths to two files on the same volume,
swap their contents.
#discussion This is often part of a safe-save strategy.
#param inOldFile Full path to a file.
#param inNewFile Full path to a file.
#result 0 if all went well, -1 otherwise.
*/
int ExchangeFiles( const char* inOldFile, const char* inNewFile )
{
int result = -1;
static dispatch_once_t sOnce = 0;
static renameFuncType sRenameFunc = NULL;
// Try to get a function pointer to renamex_np, which is available in OS 10.12 and later.
dispatch_once( &sOnce,
^{
sRenameFunc = (renameFuncType) dlsym( RTLD_DEFAULT, "renamex_np" );
});
// renamex_np is only available on OS 10.12 and later, and does not work on HFS+ volumes
// but does work on APFS volumes. Being the latest and greatest, we try it first.
if (sRenameFunc != NULL)
{
result = (*sRenameFunc)( inOldFile, inNewFile, RENAME_SWAP );
}
if (result != 0)
{
// exchangedata is an older function that works on HFS+ but not APFS.
result = exchangedata( inOldFile, inNewFile, 0 );
}
if (result != 0)
{
// Neither function worked, we must go old school.
std::string nameTemplate( inOldFile );
nameTemplate += "-swapXXXX";
// Make a mutable copy of the template
std::vector<char> workPath( nameTemplate.size() + 1 );
memcpy( &workPath[0], nameTemplate.c_str(), nameTemplate.size() + 1 );
mktemp( &workPath[0] );
std::string tempPath( &workPath[0] );
// Make the old file have a temporary name
result = rename( inOldFile, tempPath.c_str() );
// Put the new file data under the old name.
if (result == 0)
{
result = rename( inNewFile, inOldFile );
}
// Put the old data under the new name.
if (result == 0)
{
result = rename( tempPath.c_str(), inNewFile );
}
}
return result;
}

node.js c++ addon - afraid of memory leak

first of all I admit I'm a newbie in C++ addons for node.js.
I'm writing my first addon and I reached a good result: the addon does what I want. I copied from various examples I found in internet to exchange complex data between the two languages, but I understood almost nothing of what I wrote.
The first thing scaring me is that I wrote nothing that seems to free some memory; another thing which is seriously worrying me is that I don't know if what I wrote may helps or creating confusion for the V8 garbage collector; by the way I don't know if there are better ways to do what I did (iterating over js Object keys in C++, creating js Objects in C++, creating Strings in C++ to be used as properties of js Objects and what else wrong you can find in my code).
So, before going on with my job writing the real math of my addon, I would like to share with the community the nan and V8 part of it to ask if you see something wrong or that can be done in a better way.
Thank you everybody for your help,
iCC
#include <map>
#include <nan.h>
using v8::Array;
using v8::Function;
using v8::FunctionTemplate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Value;
using v8::String;
using Nan::AsyncQueueWorker;
using Nan::AsyncWorker;
using Nan::Callback;
using Nan::GetFunction;
using Nan::HandleScope;
using Nan::New;
using Nan::Null;
using Nan::Set;
using Nan::To;
using namespace std;
class Data {
public:
int dt1;
int dt2;
int dt3;
int dt4;
};
class Result {
public:
int x1;
int x2;
};
class Stats {
public:
int stat1;
int stat2;
};
typedef map<int, Data> DataSet;
typedef map<int, DataSet> DataMap;
typedef map<float, Result> ResultSet;
typedef map<int, ResultSet> ResultMap;
class MyAddOn: public AsyncWorker {
private:
DataMap *datas;
ResultMap results;
Stats stats;
public:
MyAddOn(Callback *callback, DataMap *set): AsyncWorker(callback), datas(set) {}
~MyAddOn() { delete datas; }
void Execute () {
for(DataMap::iterator i = datas->begin(); i != datas->end(); ++i) {
int res = i->first;
DataSet *datas = &i->second;
for(DataSet::iterator l = datas->begin(); l != datas->end(); ++l) {
int dt4 = l->first;
Data *data = &l->second;
// TODO: real population of stats and result
}
// test result population
results[res][res].x1 = res;
results[res][res].x2 = res;
}
// test stats population
stats.stat1 = 23;
stats.stat2 = 42;
}
void HandleOKCallback () {
Local<Object> obj;
Local<Object> res = New<Object>();
Local<Array> rslt = New<Array>();
Local<Object> sts = New<Object>();
Local<String> x1K = New<String>("x1").ToLocalChecked();
Local<String> x2K = New<String>("x2").ToLocalChecked();
uint32_t idx = 0;
for(ResultMap::iterator i = results.begin(); i != results.end(); ++i) {
ResultSet *set = &i->second;
for(ResultSet::iterator l = set->begin(); l != set->end(); ++l) {
Result *result = &l->second;
// is it ok to declare obj just once outside the cycles?
obj = New<Object>();
// is it ok to use same x1K and x2K instances for all objects?
Set(obj, x1K, New<Number>(result->x1));
Set(obj, x2K, New<Number>(result->x2));
Set(rslt, idx++, obj);
}
}
Set(sts, New<String>("stat1").ToLocalChecked(), New<Number>(stats.stat1));
Set(sts, New<String>("stat2").ToLocalChecked(), New<Number>(stats.stat2));
Set(res, New<String>("result").ToLocalChecked(), rslt);
Set(res, New<String>("stats" ).ToLocalChecked(), sts);
Local<Value> argv[] = { Null(), res };
callback->Call(2, argv);
}
};
NAN_METHOD(AddOn) {
Local<Object> datas = info[0].As<Object>();
Callback *callback = new Callback(info[1].As<Function>());
Local<Array> props = datas->GetOwnPropertyNames();
Local<String> dt1K = Nan::New("dt1").ToLocalChecked();
Local<String> dt2K = Nan::New("dt2").ToLocalChecked();
Local<String> dt3K = Nan::New("dt3").ToLocalChecked();
Local<Array> props2;
Local<Value> key;
Local<Object> value;
Local<Object> data;
DataMap *set = new DataMap();
int res;
int dt4;
DataSet *dts;
Data *dt;
for(uint32_t i = 0; i < props->Length(); i++) {
// is it ok to declare key, value, props2 and res just once outside the cycle?
key = props->Get(i);
value = datas->Get(key)->ToObject();
props2 = value->GetOwnPropertyNames();
res = To<int>(key).FromJust();
dts = &((*set)[res]);
for(uint32_t l = 0; l < props2->Length(); l++) {
// is it ok to declare key, data and dt4 just once outside the cycles?
key = props2->Get(l);
data = value->Get(key)->ToObject();
dt4 = To<int>(key).FromJust();
dt = &((*dts)[dt4]);
int dt1 = To<int>(data->Get(dt1K)).FromJust();
int dt2 = To<int>(data->Get(dt2K)).FromJust();
int dt3 = To<int>(data->Get(dt3K)).FromJust();
dt->dt1 = dt1;
dt->dt2 = dt2;
dt->dt3 = dt3;
dt->dt4 = dt4;
}
}
AsyncQueueWorker(new MyAddOn(callback, set));
}
NAN_MODULE_INIT(Init) {
Set(target, New<String>("myaddon").ToLocalChecked(), GetFunction(New<FunctionTemplate>(AddOn)).ToLocalChecked());
}
NODE_MODULE(myaddon, Init)
One year and half later...
If somebody is interested, my server is up and running since my question and the amount of memory it requires is stable.
I can't say if the code I wrote really does not has some memory leak or if lost memory is freed at each thread execution end, but if you are afraid as I was, I can say that using same structure and calls does not cause any real problem.
You do actually free up some of the memory you use, with the line of code:
~MyAddOn() { delete datas; }
In essence, C++ memory management boils down to always calling delete for every object created by new. There are also many additional architecture-specific and legacy 'C' memory management functions, but it is not strictly necessary to use these when you do not require the performance benefits.
As an example of what could potentially be a memory leak: You're passing the object held in the *callback pointer to the function AsyncQueueWorker. Yet nowhere in your code is this pointer freed, so unless the Queue worker frees it for you, there is a memory leak here.
You can use a memory tool such as valgrind to test your program further. It will spot most memory problems for you and comes highly recommended.
One thing I've observed is that you often ask (paraphrased):
Is it okay to declare X outside my loop?
To which the answer actually is that declaring variables inside of your loops is better, whenever you can do it. Declare variables as deep inside as you can, unless you have to re-use them. Variables are restricted in scope to the outermost set of {} brackets. You can read more about this in this question.
is it ok to use same x1K and x2K instances for all objects?
In essence, when you do this, if one of these objects modifies its 'x1K' string, then it will change for all of them. The advantage is that you free up memory. If the string is the same for all these objects anyway, instead of having to store say 1,000,000 copies of it, your computer will only keep a single one in memory and have 1,000,000 pointers to it instead. If the string is 9 ASCII characters long or longer under amd64, then that amounts to significant memory savings.
By the way, if you don't intend to modify a variable after its declaration, you can declare it as const, a keyword short for constant which forces the compiler to check that your variable is not modified after declaration. You may have to deal with quite a few compiler errors about functions accepting only non-const versions of things they don't modify, some of which may not be your own code, in which case you're out of luck. Being as conservative as possible with non-const variables can help spot problems.

llvm Branch instruction using SplitBlockAndInsertIfThenElse

I'm trying to build an LLVM pass that splits the BasicBlock and make a decision using "SplitBlockAndInsertIfThenElse" every time a binary operation is encountered, however this only allows me to split once (split at the 1st binop). could you please help me make it iterate through all the binop instructions?
Knowing that changing the position of "break;" gives me errors when running the pass. same thing happens when I put the "SplitBlockAndInsertIfThenElse" in a nested loop.
Here is my code:
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
{
if (auto *op = dyn_cast<BinaryOperator>(&*I))
{
IRBuilder<> Builder(op);
Value *lhs = op->getOperand(0);
Value *rhs = op->getOperand(1);
Value *xpv = Builder.CreateAlloca(llvm::Type::getInt32Ty(llvm::getGlobalContext()), nullptr, "x");
Value *xpv2 = Builder.CreateAlloca(llvm::Type::getInt32Ty(llvm::getGlobalContext()), nullptr, "x2");
Value *add1 = Builder.CreateAdd(lhs, rhs);
Value *add2 = Builder.CreateAdd(lhs, rhs);
Value *icmp1 = Builder.CreateICmpEQ(add1, add2);
TerminatorInst *ThenTerm , *ElseTerm ;
SplitBlockAndInsertIfThenElse(icmp1, op, &ThenTerm, &ElseTerm,nullptr);
Builder.SetInsertPoint(ThenTerm);
Value *xp1 = Builder.CreateStore(add1, xpv);
Builder.SetInsertPoint(ElseTerm);
break ;
}
}
Don't perform concurrent iteration and modification of the instruction list. Iterate until you find the first instruction you care about, then break out of the loop, perform the modification, and restart the loop, starting from the next instruction after the split-before one (so the next instruction after op, in your case).

Creating N number of instances of MFC application

Can someone please tell me how to go about creating a maximum of N instances of an application in MFC?
Also, if N instances are running, and one instance gets closed, then one new instance can be created (but no more than N instances can run at any one time).
Thank you in advance.
a.
You can create a global semaphore that up to n process instances can enter. The n+1 th instance of your process will fail to enter the semaphore. Of course you should select a short timeout for the locking operation so you can present a meaningful feedback to the user.
For the semaphore stuff you can take a look at MSDN.
I'd use lock files. In your CMyApp::InitInstance() add:
CString Path;
// better get the path to the global app data or local user app data folder,
// depending on if you want to allow the three instances machine-wide or per user.
// Windows' file system virtualization will make GetModuleFileName() per user:
DWORD dw = GetModuleFileName(m_hInstance,
Path.GetBuffer(MAX_PATH), MAX_PATH);
Path.ReleaseBuffer();
// strip "exe" from filename and replace it with "lock"
Path = Path.Left(Path.GetLength()-3) + T("lock");
int i;
// better have the locking file in your class and do a clean Close on ExitInstance()!
CFile *pLockingFile = NULL;
for (i = 0; i < 3; i++) // restrict to three instances
{
CString Counter;
Counter.Format(T("%d"), i);
TRY
{
pLockingFile = new CFile(Path + Counter,
CFile::modeCreate|CFile::modeWrite|CFile::shareExclusive);
pLockingFile.Close();
break; // got an instance slot
}
CATCH( CFileException, e )
{
// maybe do something else here, if file open fails
}
END_CATCH
if (i >= 3)
return TRUE; // close instance, no slot available
}
Edit: To lock the software machine-wide, retrieve the common app folder using the following function instead of calling GetModuleFileName().
#pragma warning(disable: 4996) // no risk, no fun
BOOL GetCommonAppDataPath(char *path)
{
*path = '\0';
if (SHGetSpecialFolderPath(NULL, path, CSIDL_COMMON_APPDATA, TRUE))
{
strcat(path, T("\\MyApplication")); // usually found under C:\ProgramData\MyApplication
DWORD dwFileStat = GetFileAttributes(path);
if (dwFileStat == 0xffffffff) // no MyApplication directory yet?
CreateDirectory(path, NULL); // create it
dwFileStat = GetFileAttributes(path); // 2nd try, just to be sure
if (dwFileStat == 0xffffffff || !(dwFileStat & FILE_ATTRIBUTE_DIRECTORY))
return FALSE;
return TRUE;
}
return FALSE;
}
Note: This will only work from Vista on. If you have XP, writing to a global directory is an easy task, e.g. C:\Windows\Temp. I have put the function in a helper dll I only load if the OS is Vista or higher. Otherwise your software won't start because of unresolved references in system dlls.

Resources