How to generate metadata for LLVM IR? - c++

I am trying to generate a metadata for the LLVM IR i have generated. I want to generate a metadata of the form :
!nvvm.annotations = !{!0}
!0 = metadata !{void ()* #foo, metadata !"kernel", i32 1}
Where foo is a function in my LLVM IR. Right now I am only able to generate a metadata of the form:
!nvvm.annotations = !{!0}
!0 = !{!"kernel"}
I used the following code for the above metadata generation.
char metaDataArgument[512];
sprintf(metaDataArgument, "%s", pipelineKernelName);
llvm::NamedMDNode *nvvmMetadataNode = LLVMModule->getOrInsertNamedMetadata("nvvm.annotations");
llvm::MDNode *MDNOdeNVVM = llvm::MDNode::get(*context, llvm::MDString::get(*context, "kernel"));
nvvmMetadataNode->addOperand(MDNOdeNVVM);
Could someone tell me how to modify the above code to generate metadata of the required form

Your metadata will be a tuple with 3 elements.
The first one is a global value, which is wrapped when insert in the metadata hierarchy as "ValueAsMetadata" (we can use the Constant subclass since GlobalValues are constant).
The second is a MDString, you got this one.
The last one is wrapped as a ConstantAsMetadata.
This should look approximately like the follow:
SmallVector<Metadata *, 32> Ops; // Tuple operands
GlobalValue *Foo = Mod.getNamedValue("foo");
if (!Foo) report_fatal_error("Expected foo..");
Ops.push_back(llvm::ValueAsMetadata::getConstant(Foo));
Ops.push_back(llvm::MDString::get(*context, "kernel"));
// get constant i32 1
Type *I32Ty = Type::getInt32Ty(*context);
Contant *One = ConstantInt::get(I32Ty, 1);
Ops.push_back(llvm::ValueAsMetadata::getConstant(One));
auto *Node = MDTuple::get(Context, Ops);

Related

Storing datatype u64 in QuestDB

Apparently, the Rust Postgres library doesn't allow the datatype u64 to be stored in QuestDB. So I am trying to sneak it in bypassing it as a String to the prepared statement:
INSERT INTO table_x VALUES ($1,cast($2 as LONG))
However, this is resulting in an error for me too, when I pass a String for $2:
Error { kind: ToSql(1), cause: Some(WrongType { postgres: Numeric, rust: "&alloc::string::String" }) }
Does anyone have an idea how to solve this?
The following works okay with as:
use postgres::{Client, NoTls, Error};
fn main() -> Result<(), Error> {
let mut client = Client::connect("postgresql://admin:quest#localhost:8812/qdb", NoTls)?;
// Basic query
client.batch_execute(
"CREATE TABLE IF NOT EXISTS rust (name STRING, value long);",
)?;
// Parameterized query
let name = "abc";
let uval: u64 = 9223372036854773000;
let val = uval as i64;
client.execute(
"INSERT INTO rust (name, value) VALUES ($1,$2)",
&[&name, &val],
)?;
println!("import finished");
Ok(())
}
Note the difference with i64 and u64 is the following:
i64 is +/- 9223372036854775808
u64 unsigned int is 0-18446744073709551615
The data type in QuestDB for long is 64 bit signed int (i64) so
if you have values over 9223372036854775808, you will need different handling.
edit for more information, see the following resources:
Data types in QuestDB
Rust postgres types
Rust i64 primitive type
Rust u64 primitive type

zeep objects stored in list keep getting overwritten

I am trying to append many variables that are zeep objects to a list. However, when I print out the list at the end, each variable in the list has the same data.
I have tried isolating when the variable gets overwritten, and it's happening when I put a new value into the variable with the same name, but I do this after I append the variable to the list. So I am confused as to why this is happening. I've tried to use different variable names, but it results in the same problem.
def create_json_list(json_template):
newVar = json_template
newVar['name'] = unique_name
list.append(newVar)
newVar = json_template
newVar['name'] = unique_name2
list.append(newVar)
print(list[0]['name'])
print(list[1]['name'])
# At this point, the same name gets printed twice
You are appending the same object to the list multiple times. If you notice, the template is getting modified:
import json
template = {
"field1": 1,
"field2": "two"
}
json_list = list()
def create_json_list(json_template):
newVar = json_template
newVar['name'] = "unique_name"
json_list.append(newVar)
newVar = json_template
newVar['name'] = 'another_unique_name'
json_list.append(newVar)
print(json.dumps(json_template, indent=4))
create_json_list(template)
Output
{
"field2": "two",
"field1": 1,
"name": "another_unique_name"
}
You need to create a new template for each entry:
newVar = dict(json_template)
From the documenation:
Assignment statements in Python do not copy objects, they create
bindings between a target and an object.
If you want to copy an object, you need to let Python know. In the case of a dict, you can just use the constructor as shown above.
For a zeep object, you should be able to use a factory:
factory = client.type_factory('ns0')
newVar = factory.JsonTemplate({"field1": 1, "field2": "two"})

Converting protobuf.js Types to custom formats

In my protobuf schema, I have a type that contains binary data (already defined in an existing schema, I can't change this):
// message BinaryKey { bytes data = 1; }
let BinaryKey = new Type('BinaryKey')
BinaryKey.add(new Field('data', 1, 'bytes'))
In my application JSON, I have a human readable string format of this field/type and would like to use this string for my field that is passed to encode(). What is the correct way to have encode() and decode() use custom conversion functions between string and binary format?
A full example of my code (using protobuf.js reflection):
let BinaryKey = new Type('BinaryKey')
BinaryKey.add(new Field('data', 1, 'bytes'))
let Message = new Type('CustomMessage')
Message.add(new Field('balance', 1, 'uint32'))
Message.add(BinaryKey)
Message.add(new Field('bin_key', 2, 'BinaryKey'))
let object = { balance: 100, bin_key: '<String representation>' }; // <-- *** pass in the data as a string to be converted
Message.encode(object).finish();
I would need to specify conversion functions between my string format and the binary field of the schema, but don't know how to add these to my Type (BinaryKey)

How can I traverse every character of GlobalVariable name in LLVM?

I have written a demo of getting every character of GlobalVariable name and doing XOR operation. Here is my part of my demo code(Function entry block has been created privously, gvar is the GlobalVariable and len is the GlobalVariable length):
BasicBlock *preHeaderBB=builder.GetInsertBlock();
ConstantInt* string_length = ConstantInt::get(mod->getContext(), APInt(32, len));
BasicBlock* for_body = BasicBlock::Create(mod->getContext(), "for-body", fdecode);
builder.CreateBr(for_body);
builder.SetInsertPoint(for_body);
PHINode *variable = builder.CreatePHI(Type::getInt32Ty(mod->getContext()), 2, "i");
Value *startValue = builder.getInt32(0);
Value *endValue = builder.getInt32(len);
variable->addIncoming(startValue, preHeaderBB);
LoadInst *Load=builder.CreateLoad(gvar);
Load->setAlignment(8);
Value* indexList[2] = {ConstantInt::get(startValue->getType(), 0), startValue};
ConstantInt* const_key = ConstantInt::get(mod->getContext(), APInt(8, key));
Value *GEP=builder.CreateGEP(gvar,ArrayRef<Value*>(indexList, 2),"arrayIdx");
LoadInst *loadElement=builder.CreateLoad(GEP);
loadElement->setAlignment(1);
Value *Xor = builder.CreateXor(loadElement,const_key,"xor");
StoreInst *Store = builder.CreateStore(Xor, loadElement);
Value *stepValue = builder.getInt32(1);
Value *nextValue = builder.CreateAdd(startValue, stepValue, "next-value");
Value *endCondition = builder.CreateICmpULT(startValue, endValue, "end-condition");
endCondition = builder.CreateICmpNE(endCondition, builder.getInt32(0), "loop-condion");
BasicBlock *loopEndBB = builder.GetInsertBlock();
builder.CreateCondBr(endCondition, loopEndBB, entry);
variable->addIncoming(nextValue, loopEndBB);
builder.SetInsertPoint(entry);
I used the LoadInst to get every character of GloablVariable name, but it came with error. I wander where can I improve this code. Thank you.
In LLVM's SSA form IR, the GV's name is merely an "alias" for the variable, and possibly appears in the SymbolTable, depending on the LinkageType. There is nothing as "Loading the variable's name", since the name is the variable itself. The GEP Instruction you are creating is actually an index into whatever value being represented by the GV, not the name. So that's something fundamentally wrong here. You will need to writing some code to parse the binary format and runtime and retrieve the name from the SymbolTable, providing the GV's LinkageType is not PrivateLinkage or InternalLinkage and the binary is not stripped

Converting NSEnum from Userinfo in NSNotification fails in Objective c

I want to convert userInfo data from a NSNotification to an enum to use in a switch statement. The notification is coming from a pre-compiled c++ framework with some headerfiles defining te enum.
-(void)updateOTAStatus:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo;
otaUpgradeStatus status = (otaUpgradeStatus)userInfo[#"status"];
//...
}
Enum definition:
typedef NS_ENUM(NSUInteger, otaUpgradeStatus) {
none = 0,
started = 1,
inProgress = 2,
completed = 3,
failed = 4,
failedLowBattery = 5,
cancelled = 6,
timedout = 7,
forced = 8
};
When debugging I get
Printing description of status:
(otaUpgradeStatus) status = 6178538944
And switch statement fails, when I do the same in Swift:
let status = notification.userInfo?["status"] as? otaUpgradeStatus
I get the right status back, and switch statement works as expected.
What goes wrong here?
An NSDictionary can only hold objects, i.e. instances of (a subclass of) NSObject. Swift has a mechanism to wrap/unwrap values in an
opaque _SwiftValue instance transparently.
But for interoperability with Objective-C you have to put the number
as NSNumber instances into the user info dictionary on the Swift side, e.g.
let notification = Notification(name: ..., object: ...,
userInfo: ["status": NSNumber(value: otaUpgradeStatus.failed.rawValue)])
and extract the integer value on the Objective-C side, e.g.
NSDictionary *userInfo = notification.userInfo;
NSNumber *num = userInfo[#"status"];
otaUpgradeStatus status = num.unsignedIntegerValue;