Hi I've been doing gcc plugins for gcc 4.8 and 4.9 but I'm having a problem in gcc 5.1.0. The problem is that I can't register a GIMPLE pass in this new gcc version.
Here is an example plugin code:
int plugin_is_GPL_compatible;
static bool gateCheck(void)
{
printf("BBBBB\n");
return true;
}
static unsigned int executeCheck(void)
{
printf("CCCCC\n");
return 0;
}
const pass_data gimplePass =
{
GIMPLE_PASS, // opt type name
"exampleChecker", // name
OPTGROUP_NONE, // optinfo_flags
TV_NONE, // tv_id
PROP_ssa, // properties_required
0, // properties_provided
0, // properties_destroyed
0, // todo_flags_start
0, // todo_flags_finish
};
class passAttrChecker : public gimple_opt_pass
{
public:
passAttrChecker(gcc::context* ctxt)
: gimple_opt_pass(gimplePass, ctxt)
{}
bool gate (){return gateCheck();}
unsigned int execute(){return executeCheck();}
};
extern int plugin_init(struct plugin_name_args* plugin_info,
struct plugin_gcc_version* version)
{
const char * name = "exampleChecker";
struct register_pass_info pass_info;
pass_info.pass = new passAttrChecker(g);
pass_info.reference_pass_name = "ssa";
pass_info.ref_pass_instance_number = 1;
pass_info.pos_op = PASS_POS_INSERT_AFTER;
register_callback(name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
return 0;
}
When compiling some file with this plugin should be printed some B's and C's, but nothing is being printed.
The difference with gcc 4.9 is that the type "pass_data" has two less fields than before(has_gate and has_execute). Everything else seems to be like before.
If someone knows what I'm doing wrong or what I'm missing, I'll appreciate the help.
I've already solved it. It was a pretty silly mistake.
Now in gcc 5.1.0 the execute and gate methods from otp_pass recive one argument, instead of void.
This way the example works:
class passAttrChecker : public gimple_opt_pass
{
public:
passAttrChecker(gcc::context* ctxt)
: gimple_opt_pass(gimplePass, ctxt)
{}
bool gate (function *)
{
std::cout << "GATE\n";
return true;
}
unsigned int execute(function *)
{
std::cout << "EXECUTE\n";
return 1;
}
};
Related
I am creating a c++ PBNI non-visual extension, calling it from powerbuilder like this :
textbox1.text = string (cpp_add.f_add(integer(textbox2.text), integer(textbox3.text)))
PBX_GetDescription() has one class and two functions described this way:
"class pbadd from nonvisualobject \n" \
"function int f_add(int a, int b)\n" \
"function int f_add2(int a, int b)\n" \
"end class \n"
Header:
#include "pbext.h"
class pbadd : public IPBX_NonVisualObject
{
public:
pbadd();
virtual ~pbadd();
PBXRESULT Invoke(
IPB_Session *session,
pbobject obj,
pbmethodID mid,
PBCallInfo *ci);
int f_add(IPB_Session*, pbint, pbint);
int f_add2(IPB_Session*, pbint, pbint);
enum MethodIDs
{
mAdd = 1,
mAdd2 = 2
};
private:
virtual void Destroy();
};
And the required Invoke method:
PBXRESULT pbadd::Invoke(IPB_Session *Session,
pbobject obj, pbmethodID mid, PBCallInfo *ci)
{
if (mid == mAdd)
{
int sum = f_add(Session, ci->pArgs->GetAt(0)->
GetInt(), ci->pArgs->GetAt(1)->GetInt());
ci->returnValue->SetInt(sum);
}
if (mid == mAdd2)
{
int sum = f_add2(Session, ci->pArgs->GetAt(0)->
GetInt(), ci->pArgs->GetAt(1)->GetInt());
ci->returnValue->SetInt(sum+1);
}
return PBX_OK;
}
Now the problem is: I have no clue how to call second of the two methods. I am assuming I can somehow change the pbmethod mid, but I do not know how to do so from powerbuilder.
Did you in PowerBuilder right click the library and choose 'Import PB Extension'? Doing that creates a 'shell' object that you use in your PB script and it automatically calls the Invoke method passing the method id.
Apparently the problem was here:
enum MethodIDs
{
mAdd = 1,
mAdd2 = 2
};
The IDs are counted from 0. Correct:
enum MethodIDs
{
mAdd = 0,
mAdd2 = 1
};
Got into an interesting problem while tried to call the overloaded function using conditional operator (just to avoid multiple if else condition)
class VirtualGpio
{
typedef enum
{
OUTPUT = 0xC7,
INPUT ,
DIRINVALID
}GpioDirection;
struct pinconfig
{
struct pinmap pin;
GpioPolarity plrty;
bool IsPullupCfgValid;
bool IsTriStCfgValid;
bool IsInputFilterValid;
GpioDirection dic;
gpiolistner fptr; // Callback function pointer on event change
};
};
class factory
{
public:
VirtualGpio *GetGpiofactory(VirtualGpio::pinconfig *cfg,VirtualGpio::GpioAccessTyp acc=VirtualGpio::Pin);
private:
int setCfgSetting(VirtualGpio::pinmap * const getpin, VirtualGpio::GpioDirection const data);
int setCfgSetting(VirtualGpio::pinmap * const getpin, bool const data);
};
int factory::setCfgSetting(VirtualGpio::pinmap * const getpin, VirtualGpio::GpioDirection const data)
{
cout << "It is a Direction overloaded" << endl;
}
int factory::setCfgSetting(VirtualGpio::pinmap * const getpin, bool const data)
{
cout << "It is a bool overloaded" << endl;
}
VirtualGpio* factory::GetGpiofactory(VirtualGpio::pinconfig *cfg,VirtualGpio::GpioAccessTyp acc)
{
VirtualGpio * io = new VirtualGpio();
printf("acc : 0x%X, pin : 0x%x, port : 0x%x\n",acc, cfg->pin.pinno, cfg->pin.portno);
printf("value of expression : 0x%x\n",((acc == VirtualGpio::Pin)? cfg->dic : ((cfg->dic == VirtualGpio::INPUT)?true :false))); <= this prints the right value
if(acc == VirtualGpio::Pin)
setCfgSetting(&cfg->pin,cfg->dic);
else if(cfg->dic == VirtualGpio::INPUT)
setCfgSetting(&cfg->pin,true);
else
setCfgSetting(&cfg->pin,false);
#if 0
if(setCfgSetting(&cfg->pin, ((acc == VirtualGpio::Pin)? cfg->dic : ((cfg->dic == VirtualGpio::INPUT)?true :false))) == ERROR)
{
printf("Error Setting the IO configuration for XRA\n");
}
else
printf("Set IO config successfully\n");
#endif
return io;
}
The commented part #if 0 in GetGpiofactory() is same as the above
multiple if-else-if-else block, but if I uncomment the #if0 part to #if
1, for all the possible inputs only bool version of the overloaded
function i.e setCfgSetting(VirtualGpio::pinmap * const getpin, bool
const data) is invoked.
below is my main code.
main()
{
static struct VirtualGpio::pinconfig cfg = {
.pin = {
.location = VirtualGpio::GPIO_ON_GPIOEXP1_TCI,
.pinno = 0,
.portno = -1
},
.plrty = VirtualGpio::active_high,
.IsPullupCfgValid = true,
.IsTriStCfgValid = true,
.IsInputFilterValid = true,
.dic = VirtualGpio::OUTPUT,
.fptr = NULL
};
factory fac;
fac.GetGpiofactory(&cfg);
}
Surprised, the overloaded function works well if I don't use the ternary operator instead use multiple if-else if-else blocks. curious to understand the reason.
That is because the ternary operator always evaluates to a single type. You can't "return" different types with this operator.
When the compiler encounters such an expression he tries to figure out whether he can reduce the whole thing to one type. If that's not possible you get a compile error.
In your case there is a valid option using bool as a type. Because cfg->dic is an enum type which is implicitly convertible to bool. If you would use and enum class your code would not compile anymore showing you what your actual problem is (example).
Also I don't really see what the advantage of this kind of code is. In my opinion it makes the code much harder to read. You could reduce your ifs to just one, if you're concerned about too many of them:
if(acc == VirtualGpio::Pin)
setCfgSetting(&cfg->pin,cfg->dic);
else
setCfgSetting(&cfg->pin, cfg->dic == VirtualGpio::INPUT);
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);
I have a few classes set up for a game, with XMapObject as the base, and XEntity, XEnviron, and XItem inheriting it.
MapObjects have a number of flags, one of them being MAPOBJECT_SOLID. My problem is that XEntity is the only class that correctly detects MAPOBJECT_SOLID. Both Items are Environs are always considered solid by the game, regardless of the flag's state. What is important is that Environs and Item should almost never be solid.
Each class has a very basic preliminary constructor, just initializing all varibles to zero or NULL. During the CreateX() phase, Objects are linked into the map, set into a linked linked list.
Both XItem and XEnviron are a tad sloppy. They are both new, and in the middle or my debugging attempts.
Here are the relevent code samples:
XMapObject:
#define MAPOBJECT_ACTIVE 1
#define MAPOBJECT_RENDER 2
#define MAPOBJECT_SOLID 4
class XMapObject : public XObject
{
public:
Uint8 MapObjectType,Location[2],MapObjectFlags;
XMapObject *NextMapObject,*PrevMapObject;
XMapObject();
void CreateMapObject(Uint8 MapObjectType);
void SpawnMapObject(Uint8 MapObjectLocation[2]);
void RemoveMapObject();
void DeleteMapObject();
void MapObjectSetLocation(Uint8 Y,Uint8 X);
void MapObjectMapLink();
void MapObjectMapUnlink();
};
XMapObject::XMapObject()
{
MapObjectType = 0;
Location[0] = 0;
Location[1] = 1;
NextMapObject = NULL;
PrevMapObject = NULL;
}
void XMapObject::CreateMapObject(Uint8 Type)
{
MapObjectType = Type;
}
void XMapObject::SpawnMapObject(Uint8 MapObjectLocation[2])
{
if(!(MapObjectFlags & MAPOBJECT_ACTIVE)) { MapObjectFlags += MAPOBJECT_ACTIVE; }
Location[0] = MapObjectLocation[0];
Location[1] = MapObjectLocation[1];
MapObjectMapLink();
}
XEntity:
XEntity *StartEntity = NULL,*EndEntity = NULL;
class XEntity : public XMapObject
{
public:
Uint8 Health,EntityFlags;
float Speed,Time;
XEntity *NextEntity,*PrevEntity;
XItem *IventoryList;
XEntity();
void CreateEntity(Uint8 EntityType,Uint8 EntityLocation[2]);
void DeleteEntity();
void EntityLink();
void EntityUnlink();
Uint8 MoveEntity(Uint8 YOffset,Uint8 XOffset);
};
XEntity::XEntity()
{
Health = 0;
Speed = 0;
Time = 1.0;
EntityFlags = 0;
NextEntity = NULL;
PrevEntity = NULL;
IventoryList = NULL;
}
void XEntity::CreateEntity(Uint8 EntityType,Uint8 EntityLocation[2])
{
CreateMapObject(EntityType);
SpawnMapObject(EntityLocation);
if(!(MapObjectFlags & MAPOBJECT_SOLID) { MapObjectFlags += MAPOBJECT_SOLID; }
EntityFlags = ENTITY_CLIPPING;
Time = 1.0;
Speed = 1.0;
EntityLink();
}
void XEntity::EntityLink()
{
if(StartEntity == NULL)
{
StartEntity = this;
PrevEntity = NULL;
NextEntity = NULL;
}
else
{
EndEntity->NextEntity = this;
}
EndEntity = this;
}
XEnviron:
class XEnviron : public XMapObject
{
public:
Uint8 Effect,TimeOut;
void CreateEnviron(Uint8 Type,Uint8 Y,Uint8 X,Uint8 TimeOut);
};
void XEnviron::CreateEnviron(Uint8 EnvironType,Uint8 Y,Uint8 X,Uint8 TimeOut)
{
CreateMapObject(EnvironType);
Location[0] = Y;
Location[1] = X;
SpawnMapObject(Location);
XTile *Tile = GetTile(Y,X);
Tile->Environ = this;
MapObjectFlags = MAPOBJECT_ACTIVE + MAPOBJECT_SOLID;
printf("%i\n",MapObjectFlags);
}
XItem:
class XItem : public XMapObject
{
public:
void CreateItem(Uint8 Type,Uint8 Y,Uint8 X);
};
void XItem::CreateItem(Uint8 Type,Uint8 Y,Uint8 X)
{
CreateMapObject(Type);
Location[0] = Y;
Location[1] = X;
SpawnMapObject(Location);
}
And lastly, the entity move code. Only entities are capable of moving themselves.
Uint8 XEntity::MoveEntity(Uint8 YOffset,Uint8 XOffset)
{
Uint8
NewY = Location[0] + YOffset,
NewX = Location[1] + XOffset;
if((NewY >= 0 && NewY < MAPY) && (NewX >= 0 && NewX < MAPX))
{
XTile *Tile = GetTile(NewY,NewX);
if(Tile->MapList != NULL)
{
XMapObject *MapObject = Tile->MapList;
while(MapObject != NULL)
{
if(MapObject->MapObjectFlags & MAPOBJECT_SOLID)
{
printf("solid\n");
return 0;
}
MapObject = MapObject->NextMapObject;
}
}
if(Tile->Flags & TILE_SOLID && EntityFlags & ENTITY_CLIPPING)
{
return 0;
}
this->MapObjectSetLocation(NewY,NewX);
return 1;
}
return 0;
}
What is wierd, is that the bitwise operator always returns true when the MapObject is an Environ or an Item, but it works correctly for Entities. For debug I am using the printf "Solid", and also a printf containing the value of the flag for both Environs and Items.
Any help is greatly appreciated, as this is a major bug for the small game I am working on. I am also very new at Object Oriented programming, anything tips, suggestions and/or criticism are also welcome.
Your problem appears to be that you never initialize MapObjectFlags in any classes other than XEnviron so, as a basic type, it will have an unspecified value in XItem, XEntity and other XMapObject derived objects. I suggest that, as a member of XMapObject you explicitly initialize it to a known value.
As a rule, it is generally a good idea to ensure that all members of basic type are explicitly initialized in the initializer list of every constructor that you define.
e.g.
XMapObject()
: MapObjectFlags(0)
, // ... other initializers
{
// Other initializations
}
You can't (legally) be calling XEntity::MoveEntity on a MapObject or Environ because they don't have such a method. If you're using static_cast to change your object pointer into an XEntity so you can call MoveEntity on it, then you really have no guarantees about how the bit operation will work. In some implementations, things may appear to work in MoveEntity, but what's actually happening is it's interpreting the other object's memory as an XEntity. When it tries to access the offset where it believes MapObjectFlags exists, it's not actually there and always has that bit set to 1.
I figured out the problem earlier today - It didn't have any relation to OO programming, inheritance, or bitwise; it was a simple scope error.
The problem was in the fact that during my quick test to get an Environ in game, I declared the new variable inside of the control switch sequence, so the next time any control was used, the Environ would act in unpredictable ways.
switch(Event.key.keysym.sym)
{
...
case SDLK_c: { XEnviron Environ; Environ.InitEnviron(...); }
...
}
I am trying to compile a custom class in Xcode 3 and I keep getting a no matching function call error although the same custom class compiles fine under Windows. Obviously something is not right regarding the use of curly brackets and the XCode compiler. The compiler is choking at the first curly bracket { below:
: ADataBrowser(inOwnerWindow,inID,inOwner), mEncoding(kTextEncodingMacRoman)
{
std::memset( mCustomLabels, 0, sizeof(CFStringRef) * kMaxLevelCount);
}
Any ideas much appreciated!
//Full source below
#pragma once
#include <ADataBrowser.h>
#include <AControls.h>
enum
{
kMaxLevelCount = 16
};
class CArray;
class ACustomLabelList :
public ADataBrowser
{
public:
ACustomLabelList(
ControlRef inControl,
bool inOwner = false)
: ADataBrowser(inControl, inOwner), mEncoding(kTextEncodingMacRoman)
{
std::memset( mCustomLabels, 0, sizeof(CFStringRef) * kMaxLevelCount);
}
ACustomLabelList(
WindowRef inOwnerWindow,
const ControlID &inID,
bool inOwner = false)
: ADataBrowser(inOwnerWindow,inID,inOwner), mEncoding(kTextEncodingMacRoman)
{
std::memset( mCustomLabels, 0, sizeof(CFStringRef) * kMaxLevelCount);
}
ACustomLabelList(
WindowRef inOwnerWindow,
const Rect &inBounds,
DataBrowserViewStyle inStyle)
: ADataBrowser(inOwnerWindow, inBounds, inStyle), mEncoding(kTextEncodingMacRoman)
{
std::memset( mCustomLabels, 0, sizeof(CFStringRef) * kMaxLevelCount);
}
virtual ~ACustomLabelList();
void Initialize(CArray *inArray, const TextStyle &inStyle);
CFStringRef GetCurrentSelectionLabelString();
void SetCurrentSelectionLabelString(CFStringRef inString);
void SetLabelStringAt(CFStringRef inString, DataBrowserItemID inRowID);
void ShiftCurrentSelectionUp();
void ShiftCurrentSelectionDown();
void SendSelectionChangedEvent();
CFStringRef * GetLabelList() { return mCustomLabels; }
void GetLabelAt(Str15 outString, UInt32 inIndex);
protected:
virtual void ItemNotification(
Item &inItem,
DataBrowserItemNotification inMessage,
ItemData &inItemData);
virtual OSStatus GetItemData(
Item &inItem,
DataBrowserPropertyID inProperty,
ItemData &inItemData);
virtual OSStatus SetItemData(
Item &inItem,
DataBrowserPropertyID inProperty,
ItemData &inItemData);
CFStringRef mCustomLabels[kMaxLevelCount];
TextEncoding mEncoding;
private:
ACustomLabelList(const ACustomLabelList&);
ACustomLabelList& operator=(const ACustomLabelList&);
};
It looks like you're not including the file that declares std::memset.