Saving changes to LLVM BasicBlock Pass - llvm

I successfully added some Metadata to a Basic Block in LLVM. Then I used Mod->dump() to display it on the screen.
The data is added successfully to my byte code, i.e. metadata is displayed on the screen.
My problem is that these changes are not updated in my original file.
How can I solve this problem?
class BasicBlock1 : public BasicBlockPass {
public:
BasicBlock1()
: BasicBlockPass(ID)
{}
virtual bool runOnBasicBlock(BasicBlock &BB) {
Value *A[] = {MDString::get(getGlobalContext(), "mymetadata")};
MDNode *Node = MDNode::get(getGlobalContext(), A);
for (BasicBlock::iterator ii = BB.begin(), ii_e = BB.end();
ii != ii_e; ++ii) {
ii->setMetadata("XXX", Node);
}
return true;
}
static char ID;
};
char FunctionPrint::ID = 0;
char BasicBlock1::ID =0;
int main(int argc, char **argv) {
Module *Mod = ParseIRFile(argv[1], Err, getGlobalContext());
PM.add(new BasicBlock1());
PM.run(*Mod);
Mod->dump();
return 0;
}

You write:
The data is added successfully to my byte code, i.e. metadata is displayed on the screen.
My problem is that these changes are not updated in my original file.
In your code snippet, you do not write your modified module anywhere, you just print it to the output. You can write it using:
std::string ErrorInfo;
raw_fd_ostream OS(argv[1], ErrorInfo, sys::fs::F_Binary);
if (ErrorInfo.empty()) WriteBitcodeToFile(*Mod, OS);

Related

Passing a member(which is a class) of an array(of class') to a function

I am trying to pass 5th element of an array(Products[]) of class product to another function. The goal is to update the information of the element Product[5]. Everything seems to work fine except information of Product[5] variable is not updating.
Update: Problem solved by removing while(!EOF), thanks to Remy Lebeau.
The relevant part of Class:
class product
{
private:
float Wholesale_Price = 0;
float Retail_Price = 0;
string Supplier = "N/A";
string Note = "N/A";
int Stock_Amount = 0;
public:
string Name="N/A";
void UpdateRetailPrice(float New_Retail_Price)
{
Retail_Price = New_Retail_Price;
}
void UpdateProductAmount(int New_Stock_Amount)
{
Stock_Amount = New_Stock_Amount;
}
void UpdateWholesale_price(float New_Wholesale_Price)
{
Wholesale_Price = New_Wholesale_Price;
}
};
The relevant part of function:
void ReadProductFromFile(product* Products)
{
string Name, Supplier, Note, Wholesale_Price, Retail_Price, Stock_Amount;//wholesale price, stock amount,price are in string so that
//it becomes easy to use getline(). Use stoi() later for turning string to int.
ifstream ReadProductFromFile;
ReadProductFromFile.open("product.txt");
if (!ReadProductFromFile)
{
perror("Product File failed to open");
return;
}
while(!EOF)
{
/*read product info txt file------>*/
getline(ReadProductFromFile, Name);
getline(ReadProductFromFile, Wholesale_Price);
getline(ReadProductFromFile, Retail_Price);
getline(ReadProductFromFile, Stock_Amount);
/*update product info---------->*/
Products->Name = Name;
Products->UpdateWholesale_price(stoi(Wholesale_Price));
Products->UpdateProductAmount(stoi(Stock_Amount));
Products->UpdateRetailPrice(stoi(Retail_Price));
}
}
Relevant part of Main function:
int main(int argc, char const *argv[])
{
product Products[10];
ReadProductFromFile(Products+5);//is this the right way to send Products[5]? tried &(product[5]) but error
return 0;
}
Input:
Bananas
210
270
310

Pointer to pointer comparision breaks when while(1) removed - why?

Trying to build a menu system but running into some issues with pointers - which I don't have much experience with.
I don't understand why removing the while(1) makes the comparison fail between mainmenu_table[1][i] == &option6 but for some reason it does.
What am I doing wrong? Using visual studio and an atmega328p. Thanks
Serial output with original code:
Serial begins
MeNu6
MeNu6
Starting compare loop
it worked
Serial output with while(1) removed.
Serial begins
MeNu6
MeNu6
Starting compare loop
the end
Original code (with while(1) included)
const char option1[] PROGMEM = "Menu1";
const char option2[] PROGMEM = "MEnu2";
const char option3[] PROGMEM = "MeNu3";
const char option4[] PROGMEM = "Menu4";
const char option5[] PROGMEM = "MEnu5";
const char option6[] PROGMEM = "MeNu6";
const char option7[] PROGMEM = "menu7";
const char* const submenu1_table[] PROGMEM = { option1, option2, option3 }; // array of pointers to chars stored in flash
const char* const submenu2_table[] PROGMEM = { option4, option5, option6, option7 };
const char** const mainmenu_table[] PROGMEM = { submenu1_table, submenu2_table }; //array of pointers to pointers to chars in flash
// The setup() function runs once each time the micro-controller starts
void setup()
{
Serial.begin(9600);
delay(100);
Serial.println("Serial begins");
Serial.println((const __FlashStringHelper*)(mainmenu_table[1][2])); // prints "Menu6" as expected
Serial.println((const __FlashStringHelper*)option6); // also prints "Menu6"
Serial.println("Starting compare loop");
for (int i = 0; i < 4; i++) {
if ( mainmenu_table[1][i] == &option6 ) { //
Serial.println("it worked");
while (1); // COMMENTING THIS OUT MEANS DOESN'T COMPARE SUCCESSFULLY.
}
}
Serial.println("the end");
}
// Add the main program code into the continuous loop() function
void loop()
{
}
According to Arduino description of PROGMEM, you cannot access the data through pointers to it directly as with plain pointers. You need to use the proper macros/functions to access the data.
In your code, the pointer tables themselves are located in the PROGMEM, so, to extract the individual pointers, you are supposed to do something like:
const char** submenu = (const char**)pgm_read_word(&(mainmenu_table[1]));
const char* option = (const char*)pgm_read_word(&(submenu[i]));
if (option == option6) {
//...
This code is based on the string table example from the first link.

VS2017: cannot add strings/wstrings

I have trouble understanding why the following code does not do what it should, VS2017 does not show an error and the solution is created, but the string is never what it should be:
void COrion::AddJournalMessage(CTextData *msg, const string &name)
{
WISPFUN_DEBUG("c194_f101");
CTextData *jmsg = new CTextData(msg);
jmsg->Text = name + jmsg->Text;
}
jmsg->Text is std::string.
now at runtime let's say 'name' is "Player:" and 'jmsg->Text' is "Hello World", I would expect the text after the code to be "Player:Hello World", but it is not. It's only "Player:" and I don't understand why.
I found a workaround in a way:
jmsg->Text = name.c_str() + jmsg->Text;
with this change it is "Player:Hello World".
Problem is, I still don't understand why the first one does not work.
Can someone explain where the problem is?
Is it specific to VS or something?
to make it clear: this is from an open source project I want to use, not code I wrote myself, but the problem has been the source of many bugs, since it is used in this way alot.
edit
CTextData class:
class CTextData : public CRenderTextObject
{
public:
bool Unicode = false;
TEXT_TYPE Type = TT_CLIENT;
uchar Font = 0;
uint Timer = 0;
uint MoveTimer = 0;
string Text = "";
wstring UnicodeText = L"";
uchar Alpha = 0xFF;
CRenderWorldObject *Owner = NULL;
CTextData();
CTextData(CTextData *obj);
virtual ~CTextData();
virtual bool IsText() { return true; }
bool CanBeDrawedInJournalGump();
CGLTextTexture m_Texture;
void GenerateTexture(
int maxWidth,
ushort flags = 0,
TEXT_ALIGN_TYPE align = TS_LEFT,
uchar cell = 30,
int font = -1);
};

How do I enumerate volumes on MacOSX in C++?

I'm brand new to Mac development/xcode. I'm trying to do what I feel should be extremely simple, but over a week of research has yielded no results.
I want to list the external usb drive available as a vector of strings.
I don't want their cryptic information like address serial or anything. I just want their paths IE: "D:/" or "Sandisk USB".
I accomplished this in Windows quite easily using the code found below, but finding out how to do this on Mac has me pulling my hair out.
The only thing I've found seems to be done for Objective C, - How to enumerate volumes on Mac OS X?
but my project uses c++.
Can someone please provide a simple example or point me in the right direction.
struct ESDriveDescription
{
std::string path;
std::string label;
ESDriveDescription() = default;
ESDriveDescription(const std::string &path, const std::string &label)
: path(path), label(label)
{}
};
int ESFileUtils::getExternalStorageDevicePaths(vector<ESDriveDescription> &paths){
// Letters in alphabet * 3 characters per drive path, + nul term + final nul
// NOTE: constexpr not supported in vs2013
static const DWORD DRIVE_BUFFER_SIZE = 26 * 4 + 1;
static const DWORD VOLUME_LABEL_MAX = 32;
const char* removableDriveNames[26] = { 0 };
char allDrives[DRIVE_BUFFER_SIZE] = { 0 };
int numRemovableDrives = 0;
DWORD n = GetLogicalDriveStringsA(DRIVE_BUFFER_SIZE, allDrives);
for (DWORD i = 0; i < n; i += 4) {
const char* driveName = &allDrives[i];
UINT type = GetDriveTypeA(driveName);
if (type == DRIVE_REMOVABLE)
removableDriveNames[numRemovableDrives++] = driveName;
}
char label[VOLUME_LABEL_MAX] = { 0 };
for (int i = 0; i < numRemovableDrives; i++) {
const char* driveName = removableDriveNames[i];
GetVolumeInformationA(driveName, label, VOLUME_LABEL_MAX, 0, 0, 0, 0, 0);
paths.emplace_back(driveName, label);
}
return numRemovableDrives;
}

EXC_BAD_ACCESS issue after refactoring

The following code works in a the Marmalade simulator (I'm on OSX using x-code)
bool PictureDictionary::OnTableSelect(CTable* table, int tab){
//if something is selected, look up the item, and display it
//also change the search to the selected item
if(-1 < tab){
// if a term is selected, set the search text field to the term
CString term = m_SearchResults.GetString(tab);
if(m_currentWord != (char*)term.Get()){
m_currentWord = (char *)term.Get();
m_searchTextField->SetAttribute("text", term);
char* normalizedTerm = (char *)term.Get();
char* imagePath;
sprintf(imagePath,"images/%s.jpg", normalizedTerm);
if(m_ImageAttached){
m_Image->SetAttribute("image", (const char*)imagePath);
} else {
m_Image = CreateImage(CAttributes()
.Set("name", "picture")
.Set("x1", "0")
.Set("x2", "0")
.Set("y1", "50%")
.Set("image", (const char*)imagePath)
);
m_SearchView->AddChild(m_Image);
m_ImageAttached = true;
}
}
}
return true;
}
When I run the simulator, and select an item from the table, the image appears, and changes when I select a different item. When I go to refactor, I get a EXC_BAD_ACCESS (code=1…..) Error
bool PictureDictionary::OnTableSelect(CTable* table, int tab){
//if something is selected, look up the item, and display it
//also change the search to the selected item
if(-1 < tab){
// if a term is selected, set the search text field to the term
CString term = m_SearchResults.GetString(tab);
if(m_currentWord != (char*)term.Get()){
m_currentWord = (char *)term.Get();
m_searchTextField->SetAttribute("text", term);
char* normalizedTerm = (char *)term.Get();
char* imagePath;
sprintf(imagePath,"images/%s.jpg", normalizedTerm);
UpdatePictureView(imagePath);
}
}
return true;
}
void PictureDictionary::UpdatePictureView(char* imagePath){
if(m_ImageAttached){
m_Image->SetAttribute("image", (const char*)imagePath);
} else {
m_Image = CreateImage(CAttributes()
.Set("name", "picture")
.Set("x1", "0")
.Set("x2", "0")
.Set("y1", "50%")
.Set("image", (const char*)imagePath)
);
m_SearchView->AddChild(m_Image);
m_ImageAttached = true;
}
}
Any suggestions on how to clean up the code without getting these issues?
Edit RE Comments about uninitialized variables:
m_ImageAttached was initialized to false in the constructor, unless I'm doing something wrong. Also, changing the condition to check if m_Image!=NULL also throws the same error.
main.cpp:
PictureDictionary pictDict(myApp, &dictionary);
Constructor for PictureDictionary:
PictureDictionary::PictureDictionary(CAppPtr app,Dictionary::Dictionary* dictionary){
m_App = app;
m_Dictionary = dictionary;
m_currentWord = "";
m_ImageAttached = false;
}
imagePath is an unitialized pointer, in both snippets. Any attempt to dereference is undefined behaviour. It just appeared to work in the first snippet. Use an array or populate a std::string instead:
std::string imagePath(std::string("images/") + normalizedTerm + ".jpg");
And use std::string::c_str() if access to the underlying const char* is required.