Recently, I've been trying to create a toy language based on an old tutorial. I had this idea almost half a year ago, but I don't have the time to do it until now. Anyway, when I'm following the tutorial, I modified the source code to get rid of a handful of compile errors (I believe that most of the errors are related to backward compatibility), but I'm stuck with feeding the "custom-defined code" to the parser.
The error:
eric#pop-os:~/Desktop/my_toy_compiler-master$ echo 'int do_math(int a){ int x = a * 5 + 3 } do_math(10)' | ./parser
0x55a3e10a7580
Generating code...
Generating code for 20NFunctionDeclaration
Creating variable declaration int a
Generating code for 20NVariableDeclaration
Creating variable declaration int x
Creating assignment for x
Creating binary operation 274
Creating integer: 3
Creating binary operation 276
Creating integer: 5
Creating identifier reference: a
parser: /home/eric/llvm-project/llvm/lib/IR/DataLayout.cpp:740: llvm::Align llvm::DataLayout::getAlignment(llvm::Type*, bool) const: Assertion `Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"' failed.
Aborted (core dumped)
The problem starts after 'Creating identifier reference: a'. Therefore, it is intuitive to take a look at the relevant code. There are two functions in the codegen.cpp that are considered significant to this bug.
excerpt of codegen.cpp:
...
static Type *typeOf(const NIdentifier& type)
{
if (type.name.compare("int") == 0) {
return Type::getInt64Ty(MyContext);
}
else if (type.name.compare("double") == 0) {
return Type::getDoubleTy(MyContext);
}
return Type::getVoidTy(MyContext);
}
...
Value* NIdentifier::codeGen(CodeGenContext& context)
{
std::cout << "Creating identifier reference: " << name << endl;
if (context.locals().find(name) == context.locals().end()) {
std::cerr << "undeclared variable " << name << endl;
return NULL;
}
return new LoadInst(typeOf(name), context.locals()[name], "", false, context.currentBlock());
}
...
The full version of codegen.cpp:
#include "node.h"
#include "codegen.h"
#include "parser.hpp"
using namespace std;
/* Compile the AST into a module */
void CodeGenContext::generateCode(NBlock& root)
{
std::cout << "Generating code...\n";
/* Create the top level interpreter function to call as entry */
vector<Type*> argTypes;
FunctionType *ftype = FunctionType::get(Type::getVoidTy(MyContext), makeArrayRef(argTypes), false);
mainFunction = Function::Create(ftype, GlobalValue::InternalLinkage, "main", module);
BasicBlock *bblock = BasicBlock::Create(MyContext, "entry", mainFunction, 0);
/* Push a new variable/block context */
pushBlock(bblock);
root.codeGen(*this); /* emit bytecode for the toplevel block */
ReturnInst::Create(MyContext, bblock);
popBlock();
/* Print the bytecode in a human-readable format
to see if our program compiled properly
*/
std::cout << "Code is generated.\n";
// module->dump();
legacy::PassManager pm;
pm.add(createPrintModulePass(outs()));
pm.run(*module);
}
/* Executes the AST by running the main function */
GenericValue CodeGenContext::runCode() {
std::cout << "Running code...\n";
ExecutionEngine *ee = EngineBuilder( unique_ptr<Module>(module) ).create();
ee->finalizeObject();
vector<GenericValue> noargs;
GenericValue v = ee->runFunction(mainFunction, noargs);
std::cout << "Code was run.\n";
return v;
}
/* Returns an LLVM type based on the identifier */
static Type *typeOf(const NIdentifier& type)
{
if (type.name.compare("int") == 0) {
return Type::getInt64Ty(MyContext);
}
else if (type.name.compare("double") == 0) {
return Type::getDoubleTy(MyContext);
}
return Type::getVoidTy(MyContext);
}
/* -- Code Generation -- */
Value* NInteger::codeGen(CodeGenContext& context)
{
std::cout << "Creating integer: " << value << endl;
return ConstantInt::get(Type::getInt64Ty(MyContext), value, true);
}
Value* NDouble::codeGen(CodeGenContext& context)
{
std::cout << "Creating double: " << value << endl;
return ConstantFP::get(Type::getDoubleTy(MyContext), value);
}
Value* NIdentifier::codeGen(CodeGenContext& context)
{
std::cout << "Creating identifier reference: " << name << endl;
if (context.locals().find(name) == context.locals().end()) {
std::cerr << "undeclared variable " << name << endl;
return NULL;
}
return new LoadInst(Type::getInt64Ty(MyContext), context.locals()[name], "", false, context.currentBlock());
}
Value* NMethodCall::codeGen(CodeGenContext& context)
{
Function *function = context.module->getFunction(id.name.c_str());
if (function == NULL) {
std::cerr << "no such function " << id.name << endl;
}
std::vector<Value*> args;
ExpressionList::const_iterator it;
for (it = arguments.begin(); it != arguments.end(); it++) {
args.push_back((**it).codeGen(context));
}
CallInst *call = CallInst::Create(function, makeArrayRef(args), "", context.currentBlock());
std::cout << "Creating method call: " << id.name << endl;
return call;
}
Value* NBinaryOperator::codeGen(CodeGenContext& context)
{
std::cout << "Creating binary operation " << op << endl;
Instruction::BinaryOps instr;
switch (op) {
case TPLUS: instr = Instruction::Add; goto math;
case TMINUS: instr = Instruction::Sub; goto math;
case TMUL: instr = Instruction::Mul; goto math;
case TDIV: instr = Instruction::SDiv; goto math;
/* TODO comparison */
}
return NULL;
math:
return BinaryOperator::Create(instr, lhs.codeGen(context),
rhs.codeGen(context), "", context.currentBlock());
}
Value* NAssignment::codeGen(CodeGenContext& context)
{
std::cout << "Creating assignment for " << lhs.name << endl;
if (context.locals().find(lhs.name) == context.locals().end()) {
std::cerr << "undeclared variable " << lhs.name << endl;
return NULL;
}
return new StoreInst(rhs.codeGen(context), context.locals()[lhs.name], false, context.currentBlock());
}
Value* NBlock::codeGen(CodeGenContext& context)
{
StatementList::const_iterator it;
Value *last = NULL;
for (it = statements.begin(); it != statements.end(); it++) {
std::cout << "Generating code for " << typeid(**it).name() << endl;
last = (**it).codeGen(context);
}
std::cout << "Creating block" << endl;
return last;
}
Value* NExpressionStatement::codeGen(CodeGenContext& context)
{
std::cout << "Generating code for " << typeid(expression).name() << endl;
return expression.codeGen(context);
}
Value* NReturnStatement::codeGen(CodeGenContext& context)
{
std::cout << "Generating return code for " << typeid(expression).name() << endl;
Value *returnValue = expression.codeGen(context);
context.setCurrentReturnValue(returnValue);
return returnValue;
}
Value* NVariableDeclaration::codeGen(CodeGenContext& context)
{
std::cout << "Creating variable declaration " << type.name << " " << id.name << endl;
AllocaInst *alloc = new AllocaInst(typeOf(type), NULL, id.name.c_str(), context.currentBlock());
context.locals()[id.name] = alloc;
if (assignmentExpr != NULL) {
NAssignment assn(id, *assignmentExpr);
assn.codeGen(context);
}
return alloc;
}
Value* NExternDeclaration::codeGen(CodeGenContext& context)
{
vector<Type*> argTypes;
VariableList::const_iterator it;
for (it = arguments.begin(); it != arguments.end(); it++) {
argTypes.push_back(typeOf((**it).type));
}
FunctionType *ftype = FunctionType::get(typeOf(type), makeArrayRef(argTypes), false);
Function *function = Function::Create(ftype, GlobalValue::ExternalLinkage, id.name.c_str(), context.module);
return function;
}
Value* NFunctionDeclaration::codeGen(CodeGenContext& context)
{
vector<Type*> argTypes;
VariableList::const_iterator it;
for (it = arguments.begin(); it != arguments.end(); it++) {
argTypes.push_back(typeOf((**it).type));
}
FunctionType *ftype = FunctionType::get(typeOf(type), makeArrayRef(argTypes), false);
Function *function = Function::Create(ftype, GlobalValue::InternalLinkage, id.name.c_str(), context.module);
BasicBlock *bblock = BasicBlock::Create(MyContext, "entry", function, 0);
context.pushBlock(bblock);
Function::arg_iterator argsValues = function->arg_begin();
Value* argumentValue;
for (it = arguments.begin(); it != arguments.end(); it++) {
(**it).codeGen(context);
argumentValue = &*argsValues++;
argumentValue->setName((*it)->id.name.c_str());
StoreInst *inst = new StoreInst(argumentValue, context.locals()[(*it)->id.name], false, bblock);
}
block.codeGen(context);
ReturnInst::Create(MyContext, context.getCurrentReturnValue(), bblock);
context.popBlock();
std::cout << "Creating function: " << id.name << endl;
return function;
}
Note that there are originally only 3 parameters for the LoadInst function. I checked the llvm::LoadInst Class Reference only to see that the LoadInst function now requires at least 4 parameters. I figured out that I (and the author) missed the Type *Ty parameter. Obviously, typeOf(name) in return new LoadInst(typeOf(name), context.locals()[name], "", false, context.currentBlock()); is not a solution since name, which is 'a' according to the error, will always make typeOf(name) void. I suspect that this causes Cannot getTypeInfo() on a type that is unsized!, as stated by the error.
To be short, I believe that I should look for something like this:
Value* NIdentifier::codeGen(CodeGenContext& context)
{
std::cout << "Creating identifier reference: " << name << endl;
if (context.locals().find(name) == context.locals().end()) {
std::cerr << "undeclared variable " << name << endl;
return NULL;
}
return new LoadInst(*some magic that return the llvm::type of name identifier*, context.locals()[name], "", false, context.currentBlock());
}
I'm still a noob in llvm, so excuse me if my guess isn't correct. Big thanks for any tips or ideas.
P.S. I tried return new LoadInst(Type::getInt64Ty(MyContext), context.locals()[name], "", false, context.currentBlock());. The terminal broke my heart again by saying the follow:
eric#pop-os:~/Desktop/my_toy_compiler-master$ echo 'int do_math(int a){ int x = a * 5 + 3 } do_math(10)' | ./parser
0x562120785580
Generating code...
Generating code for 20NFunctionDeclaration
Creating variable declaration int a
Generating code for 20NVariableDeclaration
Creating variable declaration int x
Creating assignment for x
Creating binary operation 274
Creating integer: 3
Creating binary operation 276
Creating integer: 5
Creating identifier reference: a
Creating block
Creating function: do_math
Generating code for 20NExpressionStatement
Generating code for 11NMethodCall
Creating integer: 10
Creating method call: do_math
Creating block
Code is generated.
; ModuleID = 'main'
source_filename = "main"
#.str = private constant [4 x i8] c"%d\0A\00"
declare i32 #printf(i8*, ...)
define internal void #echo(i64 %toPrint) {
entry:
%0 = call i32 (i8*, ...) #printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* #.str, i32 0, i32 0), i64 %toPrint)
ret void
}
define internal void #main() {
entry:
%0 = call i64 #do_math(i64 10)
ret void
}
define internal i64 #do_math(i64 %a1) {
entry:
%a = alloca i64, align 8
store i64 %a1, i64* %a, align 4
%x = alloca i64, align 8
%0 = load i64, i64* %a, align 4
%1 = mul i64 %0, 5
%2 = add i64 %1, 3
store i64 %2, i64* %x, align 4
ret void
}
Running code...
Function context does not match Module context!
void (i64)* #echo
in function echo
LLVM ERROR: Broken function found, compilation aborted!
Aborted (core dumped)
It's sad that my core is dumped anyway.
Related
I have this C++ code that needs to call a Lua function. When I get the function return values, all is well and good ("Even printing the result") but when it comes to storing the variable, the value will disappear.
LS = luaL_newstate();
luaL_openlibs(LS);
lua_register(LS, "lua_HostFunction", Link::lua_HostFunction);
if (luaL_dofile(LS, "./src/solutions/16t20.lua") != LUA_OK) {
cout << "Error: File not found or invalid" << endl;
}
string pholder = "prob"+to_string(pi);
lua_getglobal(LS, cv.stringToChar(pholder));
if (!lua_isfunction(LS, -1)) {
cout << pholder << endl;
}
int argNum = 1;
switch(pi) {
case 18: {
char *ptr = strtok(ca, ":");
lua_pushstring(LS, ptr);
ptr = strtok(NULL, ":");
lua_pushstring(LS, ptr);
argNum = 2;
break;
}
default: {
lua_pushstring(LS, ca);
argNum = 1;
break;
}
}
if (lua_pcall(LS, argNum, 1, 0) != LUA_OK) {
cout << "Couldn't call function | " + pholder << endl;
}
if (!lua_isstring(LS, -1)) {
cout << "Not a string";
}
const char* answer = lua_tostring(LS, -1);
// Will print output, but never store
cout << answer << endl;
answers += answer;
lua_pop(LS, 1);
const char* answer = lua_tostring(LS, -1);
lua_tostring returns a pointer to a string in Lua VM.
Lua is a language with GC, so this string will disappear after you pop it from Lua API stack:
lua_pop(LS, 1);
You end up with a dangling pointer.
How to fix:
Copy string's content somewhere before popping Lua string from Lua API stack.
alright, this is a bit complicated for me to understand but ill explain it simply. Right now I in the middle of making a parser. part of making that parser is to make a parse tree. the first code snip below is the class for the parse tree where the label is like the node itself. nonTerms is just an enum of non-terminal names. the children here can either be terminals(tokens in the tk[]) or another non-terminal(nodeTK in children[]).
node.h
enum nonTerms{
PARSER,
PROG,
BLOCK,
VARS,
STATS,
STAT,
MSTAT,
IN,
OUT,
IF_,
LOOP,
ASSIGN,
GOTO_,
LABEL,
R0_,
EXPR,
N_,
A_,
M_,
R_,
none = -1
};
class nodeTK{
public:
nonTerms label;
std::vector<int> printOrder;
int tkIndex = 0;
Token* tk[5] = {nullptr, nullptr, nullptr, nullptr, nullptr};
int ntIndex = 0;
nodeTK* children[4] = {nullptr, nullptr, nullptr, nullptr};
nodeTK(); // creates a null node
nodeTK(nonTerms); //creates a node with specified nonterminal name
void pushTk(Token); //adds a token to the tk[]
void pushChild(nodeTK*); // adds a child to the children[]
nonTerms getLabel(); // returns the label of the current node
std::string printLabel(); // prints the string equivalent of the label
Token* getTk(int); // retrieves a specific tk in current node
nodeTK* getChild(int); // retrieves a child from current node
};
node.cpp
std::string myLabels[21] = {
"PARSER",
"PROG",
"BLOCK",
"VARS",
"STATS",
"STAT",
"MSTAT",
"IN",
"OUT",
"IF",
"LOOP",
"ASSIGN",
"GOTO",
"LABEL",
"R0",
"EXPR",
"N",
"A",
"M",
"R",
"none"
};
nodeTK::nodeTK(){
label = none;
}
nodeTK::nodeTK(nonTerms non_terminal){
std::cout << non_terminal << std::endl;
label = non_terminal;
}
void nodeTK::pushTk(Token token){
if(tkIndex < 5){
printOrder.push_back(1);
tk[tkIndex] = &token;
tkIndex++;
}else{
std::cout << "your pushing too many tokens in this node with tk " << token.getInstance() << std::endl;
}
}
void nodeTK::pushChild(nodeTK* nodeChild){
if(ntIndex < 4){
printOrder.push_back(0);
children[ntIndex] = nodeChild;
std::cout << children[ntIndex]->getLabel() << std::endl;
ntIndex++;
}
else{
std::cout << "your pushing too many non-terminals in this node" << std::endl;
}
}
nonTerms nodeTK::getLabel(){
std::cout << "hello" << std::endl;
return label;
}
std::string nodeTK::printLabel(){
std::string str = myLabels[label];
return str;
}
Token* nodeTK::getTk(int index){
return tk[index];
}
nodeTK* nodeTK::getChild(int index){
return children[index];
}
void nodeTK::preOrder(){
std::cout << printLabel() << std::endl;
int tkIndex = 0;
int childIndex = 0;
for(int i = 0; i < printOrder.size(); i++){
if(printOrder.at(i) == 1){
std::cout << getTk(tkIndex)->getInstance() << std::endl;
tkIndex++;
}else if(printOrder.at(i) == 0){
nodeTK * temp;
std::cout << getChild(childIndex)->getLabel() << std::endl;
childIndex++;
}else{
std::cout << "something went wrong" << std::endl;
}
}
}
this is where the issue is. As you can see this function receives a node pointer which I then assign to one of the still null children in the children[]. all I want to do is print the label of the child node after it has received the pointer to check that it was retrieved correctly. getLabel() should return an enumerated value and the cout should just output some number. Every time I attempt to run getLabel() in the program ends with a segmentation fault at exactly that function call. I know it partly runs because I put some dummy cout statements to see if the function runs and the couts to appear in the terminal. I'm not sure exactly what I'm doing wrong though. Sorry if my question is not super clear, I feel like I'm still a noob to pointers.
void nodeTK::pushChild(nodeTK* nodeChild){
if(ntIndex < 4){
printOrder.push_back(0);
children[ntIndex] = nodeChild;
std::cout << children[ntIndex]->getLabel() << std::endl;
ntIndex++;
}
else{
std::cout << "your pushing too many non-terminals in this node" << std::endl;
}
}
here's the getLabel function:
nonTerms nodeTK::getLabel(){
std::cout << "hello" << std::endl;
return label;
}
here's the output of the code.
hello
Segmentation fault
thank you again
I am creating an LLVM pass and I don't understand something : when I look into the .ll file the argument of a function has a name :
call void #_ZNK2xi9spawnable9SpawnableIFvbdEEclEbd( %"class.xi::spawnable::Spawnable.0"* nonnull #_ZN2xi9spawnable2f2E, i1 zeroext %9, double %10)
So here the first argument name seems to be _ZN2xi9spawnable2f2E.
But in my pass when I use the function getName() it returns me an empty string. When I access the full argument I obtain : %"class.xi::spawnable::Spawnable.0"* %1
How can I obtain the same name as in the .ll file?
EDIT: This is a part of the code (I tried to clean it up a little so maybe there are some missing brackets)
virtual bool runOnFunction(Function &F){
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
std::string Name = demangle(F.getName ());
outs() << "Function "<< *(F.getFunctionType()) <<" " << Name << " {\n";
for(LoopInfo::iterator i = LI.begin(), e = LI.end(); i!=e; ++i)
BlocksInLoop (*i,0);
for( Function::iterator b = F.begin() , be = F.end() ;b != be; ++b){
for(BasicBlock::iterator i = b->begin() , ie = b->end();i != ie; ++i){
if(isa<CallInst>(&(*i)) || isa<InvokeInst>(&(*i))){
if (!(i->getMetadata("seen"))){
Function * fct =NULL;
if (isa<CallInst>(&(*i)))
fct = cast<CallInst>(&(*i))->getCalledFunction();
if (isa<InvokeInst>(&(*i)))
fct = cast<InvokeInst>(&(*i))->getCalledFunction();
if (fct){
outs()<<"Call " << *(fct->getFunctionType()) <<" "<< demangle(fct->getName()) << "\n";
for(Function::arg_iterator argi=fct->arg_begin(),arge=fct->arg_end(); argi!=arge;argi++ )
outs()<< argi->getName()<<"\n";
}
}
}
}
}
outs() << "}\n";
return(false);
};
You are analyzing not the call site, but the function itself. When you are looking at the function, you only have formal parameters and can't know what values are passed there.
Instead of calling ->getCalledFunction() and iterating over its args, you should iterate over cast<CallInst>(&(*i)) operands. See ->op_begin() and value_op_begin() methods.
I'm trying to transfer FCN training from BrainScript to a C++ program. To start with I'm just loading and re-training an existing model. I'm getting somewhere, but trainer->TrainMinibatch() is throwing an exception (and I can't work out how to get a description of the exception either). Rough code below:
CNTK::DeviceDescriptor& device= CNTK::DeviceDescriptor::GPUDevice(gpuid);
FunctionPtr rootFunc = nullptr;
try {
rootFunc = Function::Load(modelname, device);
}
catch (char *err) {
printf("Load fail: %s\n",err);
return;
}
catch (...) {
printf("Load fail\n");
return;
}
std::cerr << "Loaded model ok" << std::endl;
MinibatchSourcePtr minibatchSource;
try {
minibatchSource = HG_CreateMinibatchSource(64);
}
catch (char* err) {
std::cerr << "Failed to init src: " << err << std::endl;
return;
}
catch (...) {
std::cerr << "Failed to init src " << std::endl;
return;
}
auto imageStreamInfo = minibatchSource->StreamInfo(L"features");
auto labelStreamInfo = minibatchSource->StreamInfo(L"labels"); // We don't use labels as is FCN
auto inputImageShape = imageStreamInfo.m_sampleLayout;
std::cerr << "Input Shape: " << inputImageShape.AsString() << std::endl;
auto imageInputName = L"features";
auto imageInput = InputVariable(inputImageShape, imageStreamInfo.m_elementType, imageInputName);
auto classifierOutput = rootFunc;
//EITHER - construct error from output+target
std::wstring outputLayerName = L"op";
FunctionPtr outputLayer = rootFunc->FindByName(outputLayerName);
std::wstring targetLayerName = L"opool3";
FunctionPtr targetLayer = rootFunc->FindByName(targetLayerName);
// OR - just get from network
std::wstring errLayerName = L"e";
FunctionPtr errLayer = rootFunc->FindByName(errLayerName);
std::cerr << "Setup-got op layer" << outputLayer->Output().Shape().AsString() << std::endl;
std::cerr << "Setup-got tgt layer" << targetLayer->Output().Shape().AsString() << std::endl;
std::cerr << "Setup-got err layer" << errLayer->Output().Shape().AsString() << std::endl;
auto trainingLoss = CNTK::SquaredError(outputLayer, targetLayer);
auto prediction = CNTK::SquaredError(outputLayer, targetLayer);
LearningRateSchedule learningRatePerSample = TrainingParameterPerSampleSchedule(5e-8);
// Either
auto trainer = CreateTrainer(classifierOutput, trainingLoss->Output(), prediction->Output(), { SGDLearner(classifierOutput->Parameters(), learningRatePerSample) });
// Or
//auto trainer = CreateTrainer(classifierOutput, errLayer, errLayer, { SGDLearner(classifierOutput->Parameters(), learningRatePerSample) });
const size_t minibatchSize = 1;
size_t numMinibatchesToTrain = 100;
size_t outputFrequencyInMinibatches = 10;
try {
for (size_t i = 0; i < numMinibatchesToTrain; ++i)
{
std::cerr << "Iteration: " << i << std::endl;
auto minibatchData = minibatchSource->GetNextMinibatch(minibatchSize, device);
std::cerr << " got data for "<< imageInput.AsString() << std::endl;
trainer->TrainMinibatch({ { imageInput, minibatchData[imageStreamInfo] } }, device); // This line throws exception!
std::cerr << "Eval=" << trainer->PreviousMinibatchEvaluationAverage() << "," << trainer->PreviousMinibatchLossAverage() << std::endl;
}
}
// Question edited as result of comment on exceptions below
catch (const std::exception & err) {
std::cerr << "Training error:" << err.what() << std::endl;
}
catch (...) {
std::cerr << "Training error" << std::endl;
}
It's not clear exactly how to define the loss function (I'm guessing here - there's no documentation really). The network has a loss ('e') used by CNTK.exe/Brainscript, which is the Squared error between output ('op') and a target ('opool3'). I tried both using e directly, and defining the error in C++ using CNTK::SquaredError(). Both give the same output, indicating an exception thrown by trainer->TrainMinibatch:
Loaded model ok
Input Shape:B[1024 x 1024 x 3]
Setup-got op layeB[63 x 127 x 3]
Setup-got tgt layeB[63 x 127 x 3]
Setup-got err layeB[]
Iteration: 0
got data forB,Input('features', [1024 x 1024 x 3], [*, #])
Training error:Values for 1 required arguments 'Input('features', [1024 x 1024 x 3], [, #])', that the requested output(s) 'Output('aggregateLoss', [], []), Output('Block233_Output_0', [], [, #]), Output('aggregateEvalMetric', [], [])' depend on, have not been provided.
What am I doing wrong here?
Thanks!
D.
Edit: Exception is:
Training error:Values for 1 required arguments 'Input('features', [1024 x 1024 x 3], [, #])', that the requested output(s) 'Output('aggregateLoss', [], []), Output('Block233_Output_0', [], [, #]), Output('aggregateEvalMetric', [], [])' depend on, have not been provided.
Update: Having looked at the cntk code (CompositeFunction.cpp), the issue seems to be a mismatch between the input and the required input:
Supplied variable: Input('features', [1024 x 1024 x 3], [*, #])
Required argument: Input('features', [1024 x 1024 x 3], [, #])
The difference being the [*. #] vs [, #]
Not sure how to fix it though!
This issue is because imageInput is a new variable that has nothing to do with the network's arguments. Instead you need to get the input variable(s) associated with the network's arguments and bind those to minibatchData e.g. something like
std::unordered_map<Variable, ValuePtr> inputDataMap = { { classifierOutput.Arguments()[0], minibatchData[imageStreamInfo] } }
Then pass inputDataMap to TrainMinibatch. See also this evaluation example (training and evaluation have pretty similar APIs)
I want to write an LLVM pass that'll extract the arguments of function calls. If the argument is a constant one, my objective is to recover what that constant is.
The IR looks like
%2 = call noalias i8* #malloc(i64 512) #3
The LLVM pass looks like
bool runOnFunction(Function &F) override {
for (auto& B : F) {
for (auto& I : B) {
if(CallInst* call_inst = dyn_cast<CallInst>(&I)) {
Function* fn = call_inst->getCalledFunction();
StringRef fn_name = fn->getName();
errs() << fn_name << " : " << call_inst->getArgOperand(0) << "\n";
for(auto arg = fn->arg_begin(); arg != fn->arg_end(); ++arg) {
errs() << *arg << "\n";
}
}
}
}
return false;
}
If I run the pass through opt, it produces the following
malloc : 0x3df3f40
i64 %0
What does 0x3df3f40 represent? Instead of i64 and 512, why does it produce i64 and %0?
It is a pointer to Value. Try cast<>ing it to ConstantInt and then calling getValue():
for(auto arg = fn->arg_begin(); arg != fn->arg_end(); ++arg) {
if(auto* ci = dyn_cast<ConstantInt>(arg))
errs() << ci->getValue() << "\n";
errs() << *arg << "\n";
}