What's wrong with this LLVM register number? - code-generation

I'm writing a compiler for a simple C-like language for a course I'm taking. This bit of code:
int main() {
printInt(not(0));
return 0;
}
int not(int n) {
if (n == 0) {
return 1;
} else {
int result = 0;
return result;
}
}
..I naively compile to this bitcode:
declare void #printInt(i32)
declare void #printDouble(double)
declare void #printString(i8*)
declare i32 #readInt()
declare double #readDouble()
define i32 #main() {
entry:
%0 = call i32 #not(i32 0)
call void #printInt(i32 %0)
ret i32 0
unreachable
}
define i32 #not(i32 %n_0) {
entry:
%0 = icmp eq i32 %n_0, 0
br i1 %0, label %lab0, label %lab1
lab0:
ret i32 1
br label %lab2
lab1:
%result_0 = alloca i32
store i32 0, i32* %result_0
%1 = load i32* %result_0
ret i32 %1
br label %lab2
lab2:
unreachable
}
However, opt does not accept that code.
opt: core023.ll:25:5: error: instruction expected to be numbered '%2'
%1 = load i32* %result_0
Now, from what I understand of unnamed temporary registers they're supposed to be numbered sequentially starting from 0. Which is the case here. But apparently the "%1 = sub.." line should have been numbered %2. Why is that? Do any of the instructions between %0 and %1 increase the sequence number? Or maybe it's just a follow-on fault from something else?

In LLVM, everything that can have a name but does not is assigned a number. This also includes basic blocks. In your case
lab0:
ret i32 1
br label %lab2
defines two basic blocks because every terminator instruction ends a basic block. This means that, conceptually, your code is parsed as
lab0:
ret i32 1
1:
br label %lab2
and the next free number after that is 2.
To prevent strange behavior like this, I recommend always explicitly naming basic blocks.

Related

C question in logical OR: 2 operands evaluated (0) false, but the result works as TRUE range

My doubt is about the basic theory of "or logical operator". Especifically, logical OR returns true only if either one operand is true.
For instance, in this OR expression (x<O || x> 8) using x=5 when I evalute the 2 operand, I interpret it as both of them are false.
But I have an example that does not fit wiht it rule. On the contrary the expression works as range between 0 and 8, both included.
Following the code:
#include <stdio.h>
int main(void)
{
int x ; //This is the variable for being evaluated
do
{
printf("Imput a figure between 1 and 8 : ");
scanf("%i", &x);
}
while ( x < 1 || x > 8); // Why this expression write in this way determinate the range???
{
printf("Your imput was ::: %d ",x);
printf("\n");
}
printf("\n");
}
I have modified my first question. I really appreciate any helpo in order to clarify my doubt
In advance, thank you very much. Otto
It's not a while loop; it's a do ... while loop. The formatting makes it hard to see. Reformatted:
#include <stdio.h>
int main(void) {
int x;
// Execute the code in the `do { }` block once, no matter what.
// Keep executing it again and again, so long as the condition
// in `while ( )` is true.
do {
printf("Imput a figure between 1 and 8 : ");
scanf("%i", &x);
} while (x < 1 || x > 8);
// This creates a new scope. While perfectly valid C,
// this does absolutely nothing in this particular case here.
{
printf("Your imput was ::: %d ",x);
printf("\n");
}
printf("\n");
}
The block with the two printf calls is not part of the loop. The while (x < 1 || x > 8) makes it so that the code in the do { } block runs, so long as x < 1 or x > 8. In other words, it runs until x is between 1 and 8. This has the effect of asking the user to input a number again and again, until they finally input a number that's between 1 and 8.

stm32f429, spi dr register not write data

code_1
code_2
register on debug
logic analyzer
void SPI_SendData(SPI_RegDef_t *pSPIx,uint8_t *pTxBuffer , uint32_t Len)
{
while(Len > 0)
{
// 1 . wait until TXE is set ,
while(SPI_GetFlagStatus(pSPIx, SPI_TXE_FLAG) == FLAG_RESET);
// 2. check the DFF bit in CR1
if( (pSPIx->CR1 & (1 << SPI_CR1_DFF) ) )
{
// 16 BIT DFF
pSPIx->DR = *((uint16_t*)pTxBuffer); // dereferencing(typecasting );
Len--;
Len--;
(uint16_t*)pTxBuffer++; // typecasting this pointer to uint16 type and incrementing by 2.
/* The buffer is a uint8_t pointer type. When using the 16-bit data frame,
* we pick up 16-bits of data, increment pointer by 2 bytes,*/
}else
{
// 8 BIT DFF
pSPIx->DR = *pTxBuffer;
Len--;
pTxBuffer++;
/*
*(( uint8_t*)&hspi->Instance->DR) = (*pData);
pData += sizeof(uint8_t);
hspi->TxXferCount--;
*/
}
}
}
i see, MOSI always send 255 on logic analyzer but wrong data.
(uint16_t*)pTxBuffer++; increments the pointer by 1 byte, not two that you say you hope it will in the comment.
If you want to do it by converting to halfword pointer and incrementing, then you need to do something like:
pTxBuffer = (uint8_t*)(((uint16_t*)pTxBuffer) + 1);
But that is just a silly way of saying pTxBuffer += 2;
Really it doesn't make sense to have the if inside the loop, because the value of the DFF bit doesn't change unless you write to it, and you don't. I suggest you write one loop over words and one loop over bytes and have the if at the top level.

What does this line of code do? Const uint32_t goodguys = 0x1 << 0

Can someone tell me what is being done here:
Const uint32_t goodguys = 0x1 << 0
I'm assuming it is c++ and it is assigning a tag to a group but I have never seen this done. I am a self taught objective c guy and this just looks very foreign to me.
Well, if there are more lines that look like this that follow the one that you posted, then they could be bitmasks.
For example, if you have the following:
const uint32_t bit_0 = 0x1 << 0;
const uint32_t bit_1 = 0x1 << 1;
const uint32_t bit_2 = 0x1 << 2;
...
then you could use use the bitwise & operator with bit_0, bit_1, bit_2, ... and another number in order to see which bits in that other number are turned on.
const uint32_t num = 5;
...
bool bit_0_on = (num & bit_0) != 0;
bool bit_1_on = (num & bit_1) != 0;
bool bit_2_on = (num & bit_2) != 0;
...
So your 0x1 is simply a way to designate that goodguys is a bitmask, because the hexadecimal 0x designator shows that the author of the code is thinking specifically about bits, instead of decimal digits. And then the << 0 is used to change exactly what the bitmask is masking (you just change the 0 to a 1, 2, etc.).
Although base 10 is a normal way to write numbers in a program, sometimes you want to express the number in octal base or hex base. To write numbers in octal, precede the value with a 0. Thus, 023, really means 19 in base 10. To write numbers in hex, precede the value with a 0x or 0X. Thus, 0x23, really means 35 in base 10.
So
goodguys = 0x1;
really means the same as
goodguys = 1;
The bitwise shift operators shift their first operand left (<<) or right (>>) by the number of positions the second operand specifies. Look at the following two statements
goodguys = 0x1;
goodguys << 2;
The first statement is the same as goodguys = 1;
The second statement says that we should shift the bits to the left by 2 positions. So we end up with
goodguys = 0x100
which is the same as goodguys = 4;
Now you can express the two statements
goodguys = 0x1;
goodguys << 2;
as a single statement
goodguys = 0x1 << 2;
which is similar to what you have. But if you are unfamiliar with hex notation and bitwise shift operators it will look intimidating.
When const is used with a variable, it uses the following syntax:
const variable-name = value;
In this case, the const modifier allows you to assign an initial value to a variable that cannot later be changed by the program. For Instance
const int POWER_UPS = 4;
will assign 4 to variable POWER_UPS. But if you later try to overwrite this value like
POWER_UPS = 8;
you will get a compilation error.
Finally the uint32_t means 32-bit unsigned int type. You will use it when you want to make sure that your variable is 32 bits long and nothing else.

How do I change the name of Emacs auto-recovery file?

At the moment it saves the file with format:
.#main.c -> sara#sara.home.com.27017:1231918415
This makes it problematic since it ends with ".c".
I need it to be .#main.c#
Update: I have emacs 22.1
That's not the auto-recovery file, that's the link used as a locking token for the file.
update
If I tell you, will you introduce me to Summer Glau?
It's probably not going to be easy to change that; I just dug a bit and it looks like it's set in the C code. But let's ask the next question: why do you want to? I'm guessing you're hitting a regular expression for .c files that you don't want to match these. If so, note that all these lockfile links start with .# -- invariably, that's hardcoded -- so you could always exclude files with names that match "^.#" (depending on which regex syntax you use.)
If you really want to hack at it, it's in filelock.c at about line 320 in EMACS 22. Here's the code:
/* Write the name of the lock file for FN into LFNAME. Length will be
that of FN plus two more for the leading `.#' plus 1 for the
trailing period plus one for the digit after it plus one for the
null. */
#define MAKE_LOCK_NAME(lock, file) \
(lock = (char *) alloca (SBYTES (file) + 2 + 1 + 1 + 1), \
fill_in_lock_file_name (lock, (file)))
static void
fill_in_lock_file_name (lockfile, fn)
register char *lockfile;
register Lisp_Object fn;
{
register char *p;
struct stat st;
int count = 0;
strcpy (lockfile, SDATA (fn));
/* Shift the nondirectory part of the file name (including the null)
right two characters. Here is one of the places where we'd have to
do something to support 14-character-max file names. */
for (p = lockfile + strlen (lockfile); p != lockfile && *p != '/'; p--)
p[2] = *p;
/* Insert the `.#'. */
p[1] = '.';
p[2] = '#';
p = p + strlen (p);
while (lstat (lockfile, &st) == 0 && !S_ISLNK (st.st_mode))
{
if (count > 9)
{
*p = '\0';
return;
}
sprintf (p, ".%d", count++);
}
}
You can upgrade to emacs 24.3 and add to your .emacs file the following line:
(setq create-lockfiles nil)
That's strange, the default should have # at each end..
You can customize the name by redefining the auto-save-file-name-p and make-auto-save-file-name functions. In GNU emacs you would add the elisp to your .emacs file.

Why does Perl's Inline::C sort 4.0e-5 after 4.4e-5?

I built a Perl Inline::C module, but there is some oddity with the sorting. Does anyone know why it would sort like this? Why is the 4.0e-5 is not first?
my $ref = [ 5.0e-5,4.2e-5,4.3e-5,4.4e-5,4.4e-5,4.2e-5,4.2e-5,4.0e-5];
use Inline C => <<'END_OF_C_CODE';
void test(SV* sv, ...) {
I32 i;
I32 arrayLen;
AV* data;
float retval;
SV** pvalue;
Inline_Stack_Vars;
data = SvUV(Inline_Stack_Item(0));
/* Determine the length of the array */
arrayLen = av_len(data);
// sort
sortsv(AvARRAY(data),arrayLen+1,Perl_sv_cmp_locale);
for (i = 0; i < arrayLen+1; i++) {
pvalue = av_fetch(data,i,0); /* fetch the scalar located at i .*/
retval = SvNV(*pvalue); /* dereference the scalar into a number. */
printf("%f \n",newSVnv(retval));
}
}
END_OF_C_CODE
test($ref);
0.000042
0.000042
0.000042
0.000043
0.000044
0.000044
0.000040
0.000050
Because you are sorting lexically, Try this code:
#!/usr/bin/perl
use strict;
use warnings;
my $ref = [ 5.0e-5,4.2e-5,4.3e-5,4.4e-5,4.4e-5,4.2e-5,4.2e-5,4.0e-5];
print "Perl with cmp\n";
for my $val (sort #$ref) {
printf "%f \n", $val;
}
print "Perl with <=>\n";
for my $val (sort { $a <=> $b } #$ref) {
printf "%f \n", $val;
}
print "C\n";
test($ref);
use Inline C => <<'END_OF_C_CODE';
void test(SV* sv, ...) {
I32 i;
I32 arrayLen;
AV* data;
float retval;
SV** pvalue;
Inline_Stack_Vars;
data = SvUV(Inline_Stack_Item(0));
/* Determine the length of the array */
arrayLen = av_len(data);
// sort
sortsv(AvARRAY(data),av_len(data)+1,Perl_sv_cmp_locale);
arrayLen = av_len(data);
for (i = 0; i < arrayLen+1; i++) {
pvalue = av_fetch(data,i,0); /* fetch the scalar located at i .*/
retval = SvNV(*pvalue); /* dereference the scalar into a number. */
printf("%f \n",newSVnv(retval));
}
}
END_OF_C_CODE
Of course, lexically 0.00040 is smaller than 0.00042 as well, but you aren't comparing 0.00040 to 0.00042; you are comparing the number 0.00040 converted to a string with the number 0.00042 converted to a string. When a number gets too large or small, Perl's stringifying logic resorts to using scientific notation. So you are sorting the set of strings
"4.2e-05", "4.2e-05", "4.2e-05", "4.3e-05", "4.4e-05", "4.4e-05", "4e-05", "5e-05"
which are properly sorted. Perl happily turns those strings back into their numbers when you ask it to with the %f format in printf. You could stringify the numbers yourself, but since you have stated you want this to be faster, that would be a mistake. You should not to be trying to optimize the program before you know where it slow (premature optimization is the root of all evil*). Write your code then run Devel::NYTProf against it to find where it is slow. If necessary, rewrite those portions in XS or Inline::C (I prefer XS). You will find that you get more speed out of choosing the right data structure than micro-optimizations like this.
* Knuth, Donald. Structured Programming with go to Statements, ACM Journal Computing Surveys, Vol 6, No. 4, Dec. 1974. p.268.
Perl_sv_cmp_locale is your sorting function which I suspect is lexical comparison. Look for numeric sorting one or write your own.
Have an answer with help from the people over at http://www.perlmonks.org/?node_id=761015
I ran some profiling (DProf) and it's a 4x improvement in speed
Total Elapsed Time = 0.543205 Seconds
User+System Time = 0.585454 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c Name
100. 0.590 0.490 100000 0.0000 0.0000 test_inline_c_pkg::percent2
Total Elapsed Time = 2.151647 Seconds
User+System Time = 1.991647 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c Name
104. 2.080 1.930 100000 0.0000 0.0000 main::percent2
Here is the code
use Inline C => <<'END_OF_C_CODE';
#define SvSIOK(sv) ((SvFLAGS(sv) & (SVf_IOK|SVf_IVisUV)) == SVf_IOK)
#define SvNSIV(sv) (SvNOK(sv) ? SvNVX(sv) : (SvSIOK(sv) ? SvIVX(sv) : sv_2nv(sv)))
static I32 S_sv_ncmp(pTHX_ SV *a, SV *b) {
const NV nv1 = SvNSIV(a);
const NV nv2 = SvNSIV(b);
return nv1 < nv2 ? -1 : nv1 > nv2 ? 1 : 0;
}
void test(SV* sv, ...) {
I32 i;
I32 arrayLen;
AV* data;
float retval;
SV** pvalue;
Inline_Stack_Vars;
data = SvUV(Inline_Stack_Item(0));
/* Determine the length of the array */
arrayLen = av_len(data);
/* sort descending (send numerical sort function S_sv_ncmp) */
sortsv(AvARRAY(data),arrayLen+1, S_sv_ncmp);
for (i = 0; i < arrayLen+1; i++) {
pvalue = av_fetch(data,i,0); /* fetch the scalar located at i .*/
retval = SvNV(*pvalue); /* dereference the scalar into a number. */
printf("%f \n",newSVnv(retval));
}
}
END_OF_C_CODE