I know how to compile such piece of code with LLVM API (specifically with SwitchInst):
switch (h)
{
case 11:
.......
case 22:
........
}
But I don't know, is it possible to compile with SwitchInst such code:
Select Case x
Case 11 To 40
...........
Case 41 To 70
...........
End Select
How to set ranged Case-Labels ?
switchOperator->addCase(...What I need to put here?..)
No, it's impossible directly because the LLVM switch instruction does not support that:
The ‘switch‘ instruction uses three parameters: an integer comparison
value ‘value‘, a default ‘label‘ destination, and an array of pairs of
comparison value constants and ‘label‘s. The table is not allowed to
contain duplicate constant entries.
Example:
; Implement a jump table:
switch i32 %val, label %otherwise [ i32 0, label %onzero
i32 1, label %onone
i32 2, label %ontwo ]
That said, if your ranges are not too large you can just generate many comparison values (11, 12, 13 ... 40) mapping to the same label.
Related
How do I use multiple if-else statements or the switch operator from C/C++ in Assembly?
Something like this in C:
if ( number == 2 )
printf("TWO");
else if ( number == 3 )
printf("THREE");
else if ( number == 4 )
printf("FOUR");
Or using switch:
switch (i)
{
case 2:
printf("TWO"); break;
case 3:
printf("THREE"); break;
case 4:
printf("FOUR"); break;
}
Thanks.
Architecture is critical for specifics but here's some psuedo code which does what you want.
... # your code
jmp SWITCH
OPTION1:
... # do option 1
jmp DONE
OPTION2:
... # do option 2
jmp DONE
Option3:
... # do option 3
jmp DONE
SWITCH:
if opt1:
jmp OPTION1
if opt2:
jmp OPTION2
if opt3:
jmp OPTION3
DONE:
... #continue your program
A detailed answer will depend upon the particular machine instruction set for which you are writing the assembly language. Basically you write assembly code to perform the C language series of tests (if statements) and branches.
In pseudo-assembly it might look like this:
load r1, number // load the value of number into register 1
cmpi r1, 2 // compare register 1 to the immediate value 2
bne test_for_3 // branch to label "test_for_3" if the compare results is not equal
call printf // I am ignoring the parameter passing here
... // but this is where the code goes to handle
... // the case where number == 2
branch the_end // branch to the label "the_end"
test_for_3: // labels the instruction location (program counter)
// such that branch instructions can reference it
cmpi r1, 3 // compare register 1 to immediate value 3
bne test_for_4 // branch if not equal to label "test_for_4"
... // perform printf "THREE"
branch the_end // branch to the label "the_end"
test_for_4: // labels the instruction location for above branch
cmpi r1, 4 // compare register 1 to immediate value 4
bne the_end // branch if not equal to label "the_end"
... // perform printf "FOUR"
the_end: // labels the instruction location following your 3 test for the value of number
I am having trouble in solving the following flowchart question. Could you please help me as soon as possible ?
Links are given below:-
Problem 3 and Problem 4:
http://placement.freshersworld.com/placement-papers/ThoughtWorks/Placement-Paper-Whole-Testpaper-29732
Problem 3:
Let's understand the instructions first.
Instruction 3 is a bit ambiguous whether it's referring to the box number or the number in the box. This becomes more straightforward when you read the rest of the instructions all referring to making changes to instruction 2. So we can conclude it means the first box number which is also the first number mentioned in the instruction's text rather than the number in the box.
Instruction 4 is a bit confusing due to its seemingly superfluous usage of the word "whose". If instruction 4 is interpreted to mean look at the number in box 6 and go to that instruction number, if you try to work out the rest of the problem, we have an infinite loop. But if we interpret it to mean:
boxes[boxes[6]] then we don't have an infinite loop.
Let's write some code, the following is JavaScript which you can execute in your JavaScript console, in chrome that is ctrl+shift+j:
var instruction2Variables=[null,1,10];
var boxes=[null,8,6,5,7,4,2,2,11,8,-2,2,1];
var instructions=[];
instructions[1]=function()
{
boxes[11]=boxes[11]+3;
};
instructions[2]=function()
{
instruction2Variables[2]=instruction2Variables[1];
};
instructions[3]=function()
{
return instruction2Variables[1]%2==1;
}
instructions[4]=function()
{
return boxes[boxes[6]];
}
instructions[5]=function()
{
instruction2Variables[1]+=2;
}
instructions[6]=function()
{
boxes[11]=boxes[5]+boxes[11];
}
instructions[7]=function()
{
instruction2Variables[1]+=boxes[12];
instruction2Variables[2]-=boxes[12];
}
instructions[8]=function()
{
return instruction2Variables[2]<boxes[1];
}
instructions[9]=function()
{
return 2;
}
var loops=0;
for(var i=1;i<10;i++)
{
loops++;
if(loops>1000){console.log('breaking an endless loop...');break;}
console.log('Instruction '+i);
var result=instructions[i]();
if(i==3)
{
if(!result){i=6;continue;}
}else if(i==4){
console.log('Going to instruction '+result);
i=result;continue;
}else if(i==8){
if(result){i=10;break;}
}
}
boxes.shift();//get rid of our leading null value
console.log(boxes);//[8, 6, 5, 7, 4, 2, 2, 11, 8, -2, 5, 1]
Problem 4:
First we need to realize the yes/no for instruction 3 is actually pointing the wrong way. There is no question in instruction 1, so the "no" result for instruction 3 is supposed to point upwards meaning to repeat instruction 1 again if "yes".
Instruction 2 seems to reference boxes beyond our 12 boxes at first glance, but it really means we're increasing where we're storing our result of what will always be zero.
Solving this is rather easy. Our first loop we will be storing a 0 in box 2. Our second loop we will be storing a 0 in box 4. Our third loop we will be storing a 0 in box 6. After this, we must stop the looping at exactly this point as-to not corrupt our data. Our answer at first glace seems to be 6, but we're changing our box data in instruction 1 and changing instruction 1 in instruction 2. So after we execute instruction 1 for a third time, we will have boxes 2,4, and 6 set to 0. Then we will run instruction 2 for a third time, thus increasing the box reference to box 8. Finally we want to break our loop, so we need box 3 to store a value of 8.
I am learning LLVM basics. I am trying to get into the builder framework and have set up the module, a function header etc, but I have not been able yet to figure out a way to create a simple sequence like this in builder:
%0 = 41
%1 = add i32 42, %0
Meaning how can I use the pseudo register notation through the builder framework?
I have tried to create a plus instruction based on two constants. The core line I'm using to generate the (integer) addition is:
Value *L = (Value *)m_left->Create_LLVM( );
Value *R = (Value *)m_right->Create_LLVM();
if ( L == 0 || R == 0 ) return 0;
llvm::Value *p_instruction = Get_Builder().CreateAdd( L, R, "addtmp" );
This contains lots of my own functions but I guess the basics is clear. I get a Value pointer for the left and right operands which are both constants and then create an add operation with the builder framwork. Again the module and builder are set up correctly, when I call dump() I see all the other stuff I do, but this line above does not create any IR code.
I would expect it co create something like
%4 = add i32 %3, %2
or something similar. Am I misunderstanding something fundamental about the way operations are to be constructed with the builder or is it just some small oversight of some detail?
Thanks
Hard to say what you are doing wrong without the fancy Create_LLVM() functions but in general for adding two constants:
You have to create 2 ConstantInt:
const auto& ctx = getGlobalContext(); // just your LLVMContext
auto* L = ConstantInt::get(Type::getInt32Ty(ctx), 41);
auto* R = ConstantInt::get(Type::getInt32Ty(ctx), 42);
const auto& builder = Get_Builder();
builder.Insert(L); // just a no-op in standard builder impl
builder.Insert(R); // just a no-op in standard builder impl
builder.CreateAdd(L, R, "addtmp");
You should get:
%addtmp = add i32 41, i32 42;
You said that your builder is set up correctly, so it will add the add at the end of the BasicBlock it currently operates on. And I assume you have allready created a Function with at least one BasicBlock.
Edit:
What will bring give you an add instruction in any way is to create it just calling the C++ API without the builder:
BinaryOperator* add = BinaryOperator::Create(BinaryOps::Add, L, R, "addtmp", BB);
where BB is the current BasicBlock.
To get something more sophisticated (adding to variables) the canonical way is this:
At first you need some memory. The AllocaInst allocates memory on the stack:
You can use the builder for this:
auto* A = builder.CreateAlloca (Type::getInt32Ty(ctx), nullptr, "a");
auto* B = builder.CreateAlloca (Type::getInt32Ty(ctx), nullptr, "b");
For simplicity I'll just take the constants from above and store them in A and B.
To store values we need StoreInst:
builder.CreateStore (L, A, /*isVolatile=*/false);
builder.CreateStore (R, B, /*isVolatile=*/false);
For the addition we load the value from memory to a register using LoadInst:
auto* addLHS = builder.CreateLoad(A);
auto* addRHS = builder.CreateLoad(B);
Finally the addition as above:
auto* add = builder.CreateAdd(addLHS, addRHS , "add");
And with the pointer to add you can go on, e.g., returning it or storing it to another variable.
The IR should look like this:
define i32 foo() {
entry:
%a = alloca i32, align 4
%b = alloca i32, align 4
store i32 41, i32* %a, align 4
store i32 42, i32* %b, align 4
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%add = add i32 %0, %1
ret i32 %add
}
I've been going in circles through the LLVM documentation / Stack Overflow and cannot figure out how an integer global variable should be initialized as 0 (first time using LLVM). This is some of my code currently:
TheModule = (argc > 1) ? new Module(argv[1], Context) : new Module("Filename", Context);
// Unrelated code
// currentGlobal->id is just a string
TheModule->getOrInsertGlobal(currentGlobal->id, Builder.getInt32Ty());
llvm::GlobalVariable* gVar = TheModule->getNamedGlobal(currentGlobal->id);
gVar->setLinkage(llvm::GlobalValue::CommonLinkage);
gVar->setAlignment(4);
// What replaces "???" below?
//gVar->setInitializer(???);
This almost does what I want, an example of output it can produce:
#a = common global i32, align 4
#b = common global i32, align 4
#c = common global i32, align 4
However, clang foo.c -S -emit-llvm produces this which I want as well:
#a = common global i32 0, align 4
#b = common global i32 0, align 4
#c = common global i32 0, align 4
As far as I can tell I need a Constant* where I have "???", but am not sure how to do it: http://llvm.org/docs/doxygen/html/classllvm_1_1GlobalVariable.html#a095f8f031d99ce3c0b25478713293dea
Use one of the APInt constructors to get a 0-valued ConstantInt (AP stands for Arbitrary Precision)
ConstantInt* const_int_val = ConstantInt::get(module->getContext(), APInt(32,0));
Then set your initializer value (a Constant subclass)
global_var->setInitializer(const_int_val);
Is there any way of creating a simple java(or c,c ++, python) program that prints 3 (outputs the 3) when given input=6 and it gives output=6 when given input=3 without using "if conditions" ?
Assuming you're happy for it to produce other outputs on inputs that aren't 6 or 3, then you can just compute 9-x.
You can always just use a switch-case statement. Also, if you only want those two answers, you could also take the input as an int and do 9-[your int] and print that answer.
You can use the XOR bit operation. It compares pairs of bits and returns 0 if bits are equals and 1 if bits are different.
We have 3 = 011b and 6 = 110b. This numbers differ by 1 and 3 digit (bit), so XOR mask will be 101b = 5.
Code example:
public static int testMethod(int value){
return System.out.println(value ^ 5);
}
without if or without control flow statement/condition statement ?
you could use switch statement
private void tes(int i) {
switch (i) {
///give output 6 where input is 3
case 3:
System.out.println(6);
break;
///give output 3 where input is 6
case 6:
System.out.println(3);
break;
}
}