mirror of https://github.com/rui314/chibicc
Handle a function returning bool, char or short
x86-64 psABI says that only the least significant 8 bits are significant if RAX has a return value of a function returning bool. Likewise, it looks like only the least significant 1 or 2 bytes are guaranteed to have a correct value for char and short return values, respectively.
This commit is contained in:
parent
6a0ed71107
commit
dcd4579226
15
codegen.c
15
codegen.c
|
@ -291,6 +291,21 @@ static void gen_expr(Node *node) {
|
|||
println(" call %s", node->funcname);
|
||||
println(" add $8, %%rsp");
|
||||
}
|
||||
|
||||
// It looks like the most significant 48 or 56 bits in RAX may
|
||||
// contain garbage if a function return type is short or bool/char,
|
||||
// respectively. We clear the upper bits here.
|
||||
switch (node->ty->kind) {
|
||||
case TY_BOOL:
|
||||
println(" movzx %%al, %%eax");
|
||||
return;
|
||||
case TY_CHAR:
|
||||
println(" movsbl %%al, %%eax");
|
||||
return;
|
||||
case TY_SHORT:
|
||||
println(" movswl %%ax, %%eax");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
2
parse.c
2
parse.c
|
@ -479,7 +479,7 @@ static Type *declspec(Token **rest, Token *tok, VarAttr *attr) {
|
|||
return ty;
|
||||
}
|
||||
|
||||
// func-params = ("void" | param ("," param)*)? ")"
|
||||
// func-params = ("void" | param ("," param)*?)? ")"
|
||||
// param = declspec declarator
|
||||
static Type *func_params(Token **rest, Token *tok, Type *ty) {
|
||||
if (equal(tok, "void") && equal(tok->next, ")")) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -16,3 +17,8 @@ int *ext2 = &ext1;
|
|||
int ext3 = 7;
|
||||
int ext_fn1(int x) { return x; }
|
||||
int ext_fn2(int x) { return x; }
|
||||
|
||||
int false_fn() { return 512; }
|
||||
int true_fn() { return 513; }
|
||||
int char_fn() { return (2<<8)+3; }
|
||||
int short_fn() { return (2<<16)+5; }
|
||||
|
|
|
@ -65,6 +65,11 @@ void ret_none() {
|
|||
return;
|
||||
}
|
||||
|
||||
_Bool true_fn();
|
||||
_Bool false_fn();
|
||||
char char_fn();
|
||||
short short_fn();
|
||||
|
||||
int main() {
|
||||
ASSERT(3, ret3());
|
||||
ASSERT(8, add2(3, 5));
|
||||
|
@ -106,6 +111,11 @@ int main() {
|
|||
|
||||
ret_none();
|
||||
|
||||
ASSERT(1, true_fn());
|
||||
ASSERT(0, false_fn());
|
||||
ASSERT(3, char_fn());
|
||||
ASSERT(5, short_fn());
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
|
||||
void assert(int expected, int actual, char *code);
|
||||
int printf();
|
||||
int sprintf();
|
||||
int strcmp(char *p, char *q);
|
||||
int memcmp(char *p, char *q, long n);
|
||||
|
|
Loading…
Reference in New Issue