How to access a structured array of unsized type - llvm

First, I customize a data structure:
typedef struct{
char name[10];
void* fp;
} test;
I created this data structure during the IR phase.
static StructType* Test_Type = llvm::StructType::create(C,"test");
Also, I create a structured array:
test my_test[10];
test* my_test_pointer = my_test;
Finally, I tried to access its elements through getelementptr and got the following error:
GEP into unsized type!
%1 = getelementptr %test, %test* %0, i32 0
What is the cause of this unsized Type? How do I resolve this error?
Any answer would be of great help to me. Thanks

Functions, labels, metadata, token and void types do not have sizes, nor do array/struct/vector aggregates formed out of them.
I suggest you call Test_Type->dump() and take a look at what your type really is.

Related

C++: Type of multidimensional array with `variable` size

I can run this
int a = 5;
auto foo = new int [a][4][4];
But when I try this:
int a = 5;
int * foo[4][4];
foo = new int [a][4][4];
I get the error
error: incompatible types in assignment of ‘int (*)[4][4]’ to ‘int* [4][4]’
Question
What type do I have to specify for foo?
Edit:
The goal is to have one single chunk of memory, not an array of pointers.
The error message is a little confusing because it does not state the variable name.
This works:
int a = 5;
int (*foo)[4][4];
foo = new int [a][4][4];
As #john correctly identified:
You're confused between a 2D array of pointers (that's what you wrote) and a pointer to a 2D array (that's what you want).
So what's the difference between pointer to an array and array of pointers. The correct syntax to define a pointer to an array (what you tried to do):
data_type (*var_name)[array_size];
But this defines an array of pointers (what you actually did):
data_type *var_name[array_size];
#OP in your own answer you already found out what the correct type should be – a pointer to an array int (*foo)[4][4], but I thought a little more explanation is also helpful.

LLVM ArrayType with varying array size

Hi, I'm currently working on LLVM IR and have a question.
I'm creating function using following code.
Function::Create(Ty, Linkage, "tile_load", mod);
In doing so, my function type Ty is represented as:
FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), params, false);
One of my params is an array, which is currently pointed with int32*.
params.push_back(Type::getInt32PtrTy(mod->getContext()));
I want to change this part with ArrayType like [10 * i32*] but with varying array size.
I know that array type is defined like:
Type* I = IntegerType::getInt32Ty(mod->getContext());
auto num = 6;
ArrayType* arrayType = ArrayType::get(I, num);
But have no idea how to make an array type with size varying.
Does any body know how can it be done?
Thank you in advance.
jwlee
Arrays are having fixed size. Array with "varying array size" is essentially a piece of memory. So, you'd need to use pointers for this. If at some point the size become compile-time constant you could bitcast to array type.

Convert complex struct / opaquepointer / function from C++ header to Delphi

I'm converting from C/C++ header to Delphi.
I've carefully read the great Rudy's Delphi Corner article about this kind of conversion. Anyway, I'm facing something I'm hard to understand.
There's an opaque pointer, then a function prototype that has that pointer as parameter, followed by the struct declaration og the function type.
Maybe the code will make things clearer.
source .h code:
struct my_ManagedPtr_t_;
typedef struct my_ManagedPtr_t_ my_ManagedPtr_t;
typedef int (*my_ManagedPtr_ManagerFunction_t)(
my_ManagedPtr_t *managedPtr,
const my_ManagedPtr_t *srcPtr,
int operation);
typedef union {
int intValue;
void *ptr;
} my_ManagedPtr_t_data_;
struct my_ManagedPtr_t_ {
void *pointer;
my_ManagedPtr_t_data_ userData[4];
my_ManagedPtr_ManagerFunction_t manager;
};
typedef struct my_CorrelationId_t_ {
unsigned int size:8; // fill in the size of this struct
unsigned int valueType:4; // type of value held by this correlation id
unsigned int classId:16; // user defined classification id
unsigned int reserved:4; // for internal use must be 0
union {
my_UInt64_t intValue;
my_ManagedPtr_t ptrValue;
} value;
} my_CorrelationId_t;
... i'm lost. :-( I can't figure out where to start.
The structure? The function?
Thank you.
As you clarified in the comments, the immediate area of confusion for you is the circular reference. The function pointer parameters refer to the struct, but the struct contains the function pointer. In the C code this is dealt with by the opaque struct type declaration which is simply a forward declaration. A forward declaration simply promises that the type will be fully declared at some later point.
In Delphi you can deal with this in a directly analogous manner. You need to use a forward type declaration. I don't want to translate all the types in your question because that would require dealing with unions and bitfields which I deem to be separate topics. Instead I will present a simple Delphi example that shows how to deal with such circular type declarations. You can take the concept and apply it to your specific types.
type
PMyRecord = ^TMyRecord; // forward declaration
TMyFunc = function(rec: PMyRecord): Integer; cdecl;
TMyRecord = record
Func: TMyFunc;
end;
It is a little hard to find out where to start, but #DavidHeffernan's explanation of forward declaring a pointer type should give you a start.
I would translate this to following (untested) code:
type
_my_ManagedPtr_p = ^my_ManagedPtr_t;
my_ManagedPtr_ManagerFunction_t = function(
managedPtr: my_ManagedPtr_p;
scrPtr: my_ManagedPtr_p;
operation: Integer): Integer cdecl;
my_ManagedPtr_t_data = record
case Boolean of
False: (intValue: Integer);
True: (ptr: Pointer);
end;
my_ManagedPtr_t = record
ptr: Pointer;
userData: array[0..3] of my_ManagedPr_t_data;
manager: my_ManagedPtr_ManagerFunction_t;
end;
my_CorrelationId_t = record
typeData: UInt32; // size, valueType, classId and reserved combined in one integer.
case Byte of
0: (intValue: my_UInt64_t);
1: (ptrValue: my_ManagedPtr_t;
end;
I am not going to do the bitfields, but please read the Bitfields section of my article Pitfalls of converting again (I see you mentioned it already) to find a few solutions. If you want to make it really nice, use the methods and indexed access, otherwise just use shifts and masks to access the bitfields contained in the member I called typeData. How this can be done is explained in the article and is far too much to repeat here.
If you have problems with them anyway, ask a new question.

Getting a pointer of a primitive type in a function

I have a union (ValueDefinition) with pointers of different datatypes in it and functions to create it. With String it works fine:
ValueDefinition CreateValDefString(String value){
ValueDefinition valDef = {.ValueString = new String(value)};
return valDef;
}
But when I do the same with e.g. uint8_t it compiles, but at runtime I get this error:
[E][WString.cpp:185] changeBuffer(): realloc failed! Buffer unchanged
That's the code for the uint8_t:
ValueDefinition CreateValDefUint8(uint8_t value){
ValueDefinition valDef = {.ValueUInt8 = new uint8_t(value)};
return valDef;
}
What am I doing wrong? I tried it without "new" and with malloc, but I still get the same error.
Edit: As requested, the definition of ValueDefinition:
union ValueDefinition{
bool* ValueBool;
int8_t* ValueInt8;
int16_t* ValueInt16;
int32_t* ValueInt32;
uint8_t* ValueUInt8;
uint16_t* ValueUInt16;
uint32_t* ValueUInt32;
float* ValueFloat;
ulong* ValueULong;
String* ValueString;
};
In your code, it looks like C++ is throwing an error to a function to create a WString instead of uint8_t, hence the stacktrace in a completely separate header. Searching the source code in the repository for arduino shows that there is an error in WString.cpp here, which is what your compiler's detecting.
The github users suggest using a different string library, and since the bug hasn't been fixed you'll have to change, probably to the standard string library defined by C++ and not arduino. As the users have stated on github, arduino strings are notoriously unreliable.
In other words, this error has nothing to do with your code, but a question that I'd like to ask is "Why use unions in C++?" If you want to define a generic type just use templates, ex:
template<class T>
class ValueDefinition<T> {
private:
T typeDat;
public:
Valuedefinition(T t);
/* etc. */
}
Unions were made so that C could have a way to use generic typing by having several types share the data in the union. Another common use is taking advantage of the data types using the same memory to find the underlying binary of more complex types, such as using individual uint8_t values underlying a long long to find the value of its bits or using an int to get the binary value of a float, ex:
union foo {
uint8_t bits[4]; /* Represent the bits of 'data' */
long long int data;
}
union foo myLong = {.data = 12378591249169278l};
printf("%d\n", myLong.bits[0]); // Returns the value of the high bit of myLong
However note that this is undefined behavior because unions are usually padded and architectures use a different form of endianess. Whatever you're doing, if you're using C++ there's a better way to implement your solution than using unions, since this was a feature meant for a language that had no generic typing in order to save memory.
Edit:
Initialize ValueDefinition using C's malloc like so:
union ValueDefinition *value = malloc(sizeof(union ValueDefinition));
value->ValueUInt8 = malloc(sizeof(uint8_t));
/* more code */
Or with C++'s new:
union ValueDefinition *value = new ValueDefinition();
value->ValueUInt8 = new uint8_t(/* Some number */);
/* more code */

Failed to push a custom struct allocated with "new" in queue

I have an issue about pushing structs allocated with new operator.
Here follows my queue declaration, my struct and the code where I allocate a new struct and try to push it in my queue:
std::queue<data_pkt> my_queue;
typedef struct data_pkt {
int sockfd;
std::string payload;
int payload_size;
} data_packet;
data_packet *data = new data_packet;
if (!data) {
printf("Failed to allocate data_packet to enqueue pkt\n");
exit(EXIT_FAILURE);
}
/* filling struct's fields... */
my_queue.push(data);
When compiling with flags -Wall -std=c++11, it gives:
error: no matching function for call to ‘std::queue<data_pkt>::push(data_packet*&)’
queue_to_internet_1.push(data);
no known conversion for argument 1 from ‘data_packet*
{aka data_pkt*}’ to ‘const value_type& {aka const data_pkt&}’
So I tried changing my queue declaration including &, so that it could accept pointers to struct, but it says:
error: template argument 1 is invalid
std::queue<&data_pkt> q;
^
QOSManager.h:57:23: error: template argument 2 is invalid
I saw that new returns a void *, so my queue should be capable of storing pointers to data_packet structs, but I don't know what I'm doing wrong.
In your code compiler produce syntax error about push of value of wrong type,
that can be fixed by:
my_queue.push(*data);
side note in C++ you not need typedef struct data_pkt{} data_packet;
you can write struct data_packet {}; and then write data_packet data;,
without struct keyword, because of C++ not C.
But your memory allocation is waste of CPU cycles,
so you can write:
data_pkt data;
my_queue.push(data);
Or to remove useless copy:
my_queue.push(data_pkt());
data_pkt &data = my_queue.back();
//fill data here
Two options to fix compilation error:
Do not use dynamic allocation as already mentioned.
Store pointers in the queue instead of structs and this is correct declaration for this std::queue<data_pkt*> my_queue;
Well, templates and std:: library is a big topic, but to quickly understand where the compiler error comes from - consider the my_queue as plain array. You either declare array of structures and set structure in each element or you declare array of pointers and set pointers.