commit e479aac9bba98833a5f00a10d408461d6d9ef482
parent 7f78583070c776aa77f7059322381dd116d37eba
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Wed, 12 Jan 2022 20:08:14 -0600
remove extra allocation when generating code
This required updating all the generation functions in x64.c since
they all write to a buffer. Now they write to a `struct data` array.
Diffstat:
8 files changed, 300 insertions(+), 288 deletions(-)
diff --git a/array.h b/array.h
@@ -1,6 +1,9 @@
#define array_add(arr, new) \
_array_add((void **) &(arr->data), &(arr->len), &(arr->cap), &new, sizeof(new), 1);
+#define array_addlit(arr, new) \
+ do {temp = new; array_add(arr, temp); } while (0);
+
#define array_push(arr, new, count) \
_array_add((void **) &(arr->data), &(arr->len), &(arr->cap), new, sizeof(*(arr->data)), count);
diff --git a/ir.c b/ir.c
@@ -2,7 +2,6 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
@@ -409,17 +408,10 @@ genproc(struct decl *decl, struct proc *proc)
}
genblock(out, &proc->block);
-
chooseregs(&iproc);
-
- size_t len = targ.emitproc(NULL, out);
- void *buf = xcalloc(1, len); // FIXME: unnecessary
- len = targ.emitproc(buf, out);
- array_push((&toplevel.text), buf, len);
- free(buf);
array_add((&toplevel.code), iproc);
blockpop();
- return len;
+ return targ.emitproc(&toplevel.text, out);
}
diff --git a/ir.h b/ir.h
@@ -64,6 +64,6 @@ size_t genproc(struct decl *decl, struct proc *proc);
struct target {
uint32_t reserved;
- size_t (*emitsyscall)(char *buf, uint8_t paramcount);
- size_t (*emitproc)(char *buf, struct iproc *proc);
+ size_t (*emitsyscall)(struct data *text, uint8_t paramcount);
+ size_t (*emitproc)(struct data *text, struct iproc *proc);
};
diff --git a/main.c b/main.c
@@ -102,7 +102,6 @@ gentoplevel(struct toplevel *toplevel, struct block *block)
char syscallname[] = "syscall0";
blockpush(block);
typecheck(block);
- size_t len = 0;
struct iproc iproc = { 0 };
uint64_t curaddr = TEXT_OFFSET;
@@ -111,13 +110,8 @@ gentoplevel(struct toplevel *toplevel, struct block *block)
syscallname[7]++;
iproc.s.data = strdup(syscallname);
iproc.addr = curaddr;
- len = targ.emitsyscall(NULL, i);
- void *buf = xcalloc(1, len); // FIXME: unnecessary
- len = targ.emitsyscall(buf, i);
- array_push((&toplevel->text), buf, len);
- free(buf);
array_add((&toplevel->code), iproc);
- curaddr += len;
+ curaddr += targ.emitsyscall(&toplevel->text, i);
}
for (int i = 0; i < block->len; i++) {
struct item *item = &block->data[i];
diff --git a/siphash.c b/siphash.c
@@ -17,7 +17,7 @@
#include <assert.h>
#include <stdint.h>
-#include <stdio.h>
+#include <stddef.h>
/* default: SipHash-2-4 */
#ifndef cROUNDS
@@ -65,6 +65,7 @@
#ifdef DEBUG
#define TRACE \
+#include <stdio.h>
do { \
printf("(%3zu) v0 %016" PRIx64 "\n", inlen, v0); \
printf("(%3zu) v1 %016" PRIx64 "\n", inlen, v1); \
diff --git a/type.c b/type.c
@@ -3,7 +3,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
#include "nooc.h"
#include "parse.h"
diff --git a/x64.c b/x64.c
@@ -8,6 +8,7 @@
#include "ir.h"
#include "x64.h"
#include "util.h"
+#include "array.h"
enum rex {
REX_B = 0x41,
@@ -31,180 +32,190 @@ unsigned short used_reg;
extern struct toplevel toplevel;
static size_t
-add_r64_imm(char *buf, enum reg dest, uint64_t imm)
+add_r64_imm(struct data *text, enum reg dest, uint64_t imm)
{
- if (buf) {
- *(buf++) = REX_W;
- *(buf++) = 0x81;;
- *(buf++) = (MOD_DIRECT << 6) | dest;
- *(buf++) = imm & 0xFF;
- *(buf++) = (imm >> 8) & 0xFF;
- *(buf++) = (imm >> 16) & 0xFF;
- *(buf++) = (imm >> 24) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, REX_W);
+ array_addlit(text, 0x81);
+ array_addlit(text, (MOD_DIRECT << 6) | dest);
+ array_addlit(text, imm & 0xFF);
+ array_addlit(text, (imm >> 8) & 0xFF);
+ array_addlit(text, (imm >> 16) & 0xFF);
+ array_addlit(text, (imm >> 24) & 0xFF);
}
return 7;
}
static size_t
-mov_r64_imm(char *buf, enum reg dest, uint64_t imm)
+mov_r64_imm(struct data *text, enum reg dest, uint64_t imm)
{
- if (buf) {
- *(buf++) = REX_W | (dest >= 8 ? REX_B : 0);
- *(buf++) = 0xb8 + (dest & 0x7);
- *(buf++) = imm & 0xFF;
- *(buf++) = (imm >> 8) & 0xFF;
- *(buf++) = (imm >> 16) & 0xFF;
- *(buf++) = (imm >> 24) & 0xFF;
- *(buf++) = (imm >> 32) & 0xFF;
- *(buf++) = (imm >> 40) & 0xFF;
- *(buf++) = (imm >> 48) & 0xFF;
- *(buf++) = (imm >> 56) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, REX_W | (dest >= 8 ? REX_B : 0));
+ array_addlit(text, 0xb8 + (dest & 0x7));
+ array_addlit(text, imm & 0xFF);
+ array_addlit(text, (imm >> 8) & 0xFF);
+ array_addlit(text, (imm >> 16) & 0xFF);
+ array_addlit(text, (imm >> 24) & 0xFF);
+ array_addlit(text, (imm >> 32) & 0xFF);
+ array_addlit(text, (imm >> 40) & 0xFF);
+ array_addlit(text, (imm >> 48) & 0xFF);
+ array_addlit(text, (imm >> 56) & 0xFF);
}
return 10;
}
static size_t
-mov_r32_imm(char *buf, enum reg dest, uint32_t imm)
+mov_r32_imm(struct data *text, enum reg dest, uint32_t imm)
{
- if (buf) {
- *(buf++) = 0xb8 + (dest & 0x7);
- *(buf++) = imm & 0xFF;
- *(buf++) = (imm >> 8) & 0xFF;
- *(buf++) = (imm >> 16) & 0xFF;
- *(buf++) = (imm >> 24) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, 0xb8 + (dest & 0x7));
+ array_addlit(text, imm & 0xFF);
+ array_addlit(text, (imm >> 8) & 0xFF);
+ array_addlit(text, (imm >> 16) & 0xFF);
+ array_addlit(text, (imm >> 24) & 0xFF);
}
return 5;
}
static size_t
-mov_r16_imm(char *buf, enum reg dest, uint16_t imm)
+mov_r16_imm(struct data *text, enum reg dest, uint16_t imm)
{
- if (buf) {
- *(buf++) = OP_SIZE_OVERRIDE;
- *(buf++) = 0xb8;
- *(buf++) = imm & 0xFF;
- *(buf++) = (imm >> 8) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, OP_SIZE_OVERRIDE);
+ array_addlit(text, 0xb8);
+ array_addlit(text, imm & 0xFF);
+ array_addlit(text, (imm >> 8) & 0xFF);
}
return 4;
}
static size_t
-mov_r8_imm(char *buf, enum reg dest, uint8_t imm)
+mov_r8_imm(struct data *text, enum reg dest, uint8_t imm)
{
- if (buf) {
- *(buf++) = 0xb0 + (dest & 0x7);
- *(buf++) = imm;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, 0xb0 + (dest & 0x7));
+ array_addlit(text, imm);
}
return 2;
}
static size_t
-mov_r64_m64(char *buf, enum reg dest, uint64_t addr)
+mov_r64_m64(struct data *text, enum reg dest, uint64_t addr)
{
- uint8_t sib = 0x25;
- if (buf) {
- *(buf++) = REX_W | (dest >= 8 ? REX_R : 0);
- *(buf++) = 0x8b;
- *(buf++) = (MOD_INDIRECT << 6) | ((dest & 7) << 3) | 4;
- *(buf++) = sib;
- *(buf++) = addr & 0xFF;
- *(buf++) = (addr >> 8) & 0xFF;
- *(buf++) = (addr >> 16) & 0xFF;
- *(buf++) = (addr >> 24) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, REX_W | (dest >= 8 ? REX_R : 0));
+ array_addlit(text, 0x8b);
+ array_addlit(text, (MOD_INDIRECT << 6) | ((dest & 7) << 3) | 4);
+ array_addlit(text, 0x25);
+ array_addlit(text, addr & 0xFF);
+ array_addlit(text, (addr >> 8) & 0xFF);
+ array_addlit(text, (addr >> 16) & 0xFF);
+ array_addlit(text, (addr >> 24) & 0xFF);
}
return 8;
}
static size_t
-mov_r32_m32(char *buf, enum reg dest, uint32_t addr)
+mov_r32_m32(struct data *text, enum reg dest, uint32_t addr)
{
- if (buf) {
- if (dest >= 8) *(buf++) = REX_R;
- *(buf++) = 0x8b;
- *(buf++) = (MOD_INDIRECT << 6) | ((dest & 7) << 3) | 4;
- *(buf++) = 0x25;
- *(buf++) = addr & 0xFF;
- *(buf++) = (addr >> 8) & 0xFF;
- *(buf++) = (addr >> 16) & 0xFF;
- *(buf++) = (addr >> 24) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ if (dest >= 8) array_addlit(text, REX_R);
+ array_addlit(text, 0x8b);
+ array_addlit(text, (MOD_INDIRECT << 6) | ((dest & 7) << 3) | 4);
+ array_addlit(text, 0x25);
+ array_addlit(text, addr & 0xFF);
+ array_addlit(text, (addr >> 8) & 0xFF);
+ array_addlit(text, (addr >> 16) & 0xFF);
+ array_addlit(text, (addr >> 24) & 0xFF);
}
return dest >= 8 ? 8 : 7;
}
static size_t
-mov_r16_m16(char *buf, enum reg dest, uint32_t addr)
+mov_r16_m16(struct data *text, enum reg dest, uint32_t addr)
{
- if (buf) {
- *(buf++) = OP_SIZE_OVERRIDE;
- if (dest >= 8) *(buf++) = REX_R;
- *(buf++) = 0x8b;
- *(buf++) = (MOD_INDIRECT << 6) | ((dest & 7) << 3) | 4;
- *(buf++) = 0x25;
- *(buf++) = addr & 0xFF;
- *(buf++) = (addr >> 8) & 0xFF;
- *(buf++) = (addr >> 16) & 0xFF;
- *(buf++) = (addr >> 24) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, OP_SIZE_OVERRIDE);
+ if (dest >= 8) array_addlit(text, REX_R);
+ array_addlit(text, 0x8b);
+ array_addlit(text, (MOD_INDIRECT << 6) | ((dest & 7) << 3) | 4);
+ array_addlit(text, 0x25);
+ array_addlit(text, addr & 0xFF);
+ array_addlit(text, (addr >> 8) & 0xFF);
+ array_addlit(text, (addr >> 16) & 0xFF);
+ array_addlit(text, (addr >> 24) & 0xFF);
}
return dest >= 8 ? 9 : 8;
}
static size_t
-mov_r8_m8(char *buf, enum reg dest, uint32_t addr)
+mov_r8_m8(struct data *text, enum reg dest, uint32_t addr)
{
- if (buf) {
- if (dest >= 8) *(buf++) = REX_R;
- *(buf++) = 0x8a;
- *(buf++) = (MOD_INDIRECT << 6) | ((dest & 7) << 3) | 4;
- *(buf++) = 0x25;
- *(buf++) = addr & 0xFF;
- *(buf++) = (addr >> 8) & 0xFF;
- *(buf++) = (addr >> 16) & 0xFF;
- *(buf++) = (addr >> 24) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ if (dest >= 8) array_addlit(text, REX_R);
+ array_addlit(text, 0x8a);
+ array_addlit(text, (MOD_INDIRECT << 6) | ((dest & 7) << 3) | 4);
+ array_addlit(text, 0x25);
+ array_addlit(text, addr & 0xFF);
+ array_addlit(text, (addr >> 8) & 0xFF);
+ array_addlit(text, (addr >> 16) & 0xFF);
+ array_addlit(text, (addr >> 24) & 0xFF);
}
return dest >= 8 ? 8 : 7;
}
static size_t
-mov_m64_r64(char *buf, uint64_t addr, enum reg src)
+mov_m64_r64(struct data *text, uint64_t addr, enum reg src)
{
- if (buf) {
- *(buf++) = REX_W;
- *(buf++) = 0xA3;
- *(buf++) = addr & 0xFF;
- *(buf++) = (addr >> 8) & 0xFF;
- *(buf++) = (addr >> 16) & 0xFF;
- *(buf++) = (addr >> 24) & 0xFF;
- *(buf++) = (addr >> 32) & 0xFF;
- *(buf++) = (addr >> 40) & 0xFF;
- *(buf++) = (addr >> 48) & 0xFF;
- *(buf++) = (addr >> 56) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, REX_W);
+ array_addlit(text, 0xA3);
+ array_addlit(text, addr & 0xFF);
+ array_addlit(text, (addr >> 8) & 0xFF);
+ array_addlit(text, (addr >> 16) & 0xFF);
+ array_addlit(text, (addr >> 24) & 0xFF);
+ array_addlit(text, (addr >> 32) & 0xFF);
+ array_addlit(text, (addr >> 40) & 0xFF);
+ array_addlit(text, (addr >> 48) & 0xFF);
+ array_addlit(text, (addr >> 56) & 0xFF);
}
return 10;
}
static size_t
-mov_m32_r32(char *buf, uint64_t addr, enum reg src)
+mov_m32_r32(struct data *text, uint64_t addr, enum reg src)
{
- if (buf) {
- *(buf++) = 0xA3;
- *(buf++) = addr & 0xFF;
- *(buf++) = (addr >> 8) & 0xFF;
- *(buf++) = (addr >> 16) & 0xFF;
- *(buf++) = (addr >> 24) & 0xFF;
- *(buf++) = (addr >> 32) & 0xFF;
- *(buf++) = (addr >> 40) & 0xFF;
- *(buf++) = (addr >> 48) & 0xFF;
- *(buf++) = (addr >> 56) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, 0xA3);
+ array_addlit(text, addr & 0xFF);
+ array_addlit(text, (addr >> 8) & 0xFF);
+ array_addlit(text, (addr >> 16) & 0xFF);
+ array_addlit(text, (addr >> 24) & 0xFF);
+ array_addlit(text, (addr >> 32) & 0xFF);
+ array_addlit(text, (addr >> 40) & 0xFF);
+ array_addlit(text, (addr >> 48) & 0xFF);
+ array_addlit(text, (addr >> 56) & 0xFF);
}
return 9;
@@ -214,21 +225,21 @@ mov_m32_r32(char *buf, uint64_t addr, enum reg src)
#define MOVE_TOREG 1
static size_t
-_move_between_reg_and_memaddr_in_reg(char *buf, enum reg reg, enum reg mem, uint8_t opsize, bool dir)
+_move_between_reg_and_memaddr_in_reg(struct data *text, enum reg reg, enum reg mem, uint8_t opsize, bool dir)
{
- uint8_t rex = opsize == 8 ? REX_W : 0;
+ uint8_t temp, rex = opsize == 8 ? REX_W : 0;
rex |= (reg >= 8 ? REX_R : 0) | (mem >= 8 ? REX_B : 0);
- if (buf) {
+ if (text) {
if (opsize == 2)
- *(buf++) = OP_SIZE_OVERRIDE;
+ array_addlit(text, OP_SIZE_OVERRIDE);
if (rex)
- *(buf++) = rex;
+ array_addlit(text, rex);
- *(buf++) = 0x88 + (opsize != 1) + 2*dir;
+ array_addlit(text, 0x88 + (opsize != 1) + 2*dir);
- *(buf++) = (MOD_INDIRECT << 6) | ((reg & 7) << 3) | (mem & 7);
+ array_addlit(text, (MOD_INDIRECT << 6) | ((reg & 7) << 3) | (mem & 7));
}
// 8 and 2 have a length of 3, but 4 and 1 have a length of 2
@@ -236,101 +247,101 @@ _move_between_reg_and_memaddr_in_reg(char *buf, enum reg reg, enum reg mem, uint
}
static size_t
-mov_mr64_r64(char *buf, enum reg dest, enum reg src)
+mov_mr64_r64(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg(buf, src, dest, 8, MOVE_FROMREG);
+ return _move_between_reg_and_memaddr_in_reg(text, src, dest, 8, MOVE_FROMREG);
}
static size_t
-mov_mr32_r32(char *buf, enum reg dest, enum reg src)
+mov_mr32_r32(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg(buf, src, dest, 4, MOVE_FROMREG);
+ return _move_between_reg_and_memaddr_in_reg(text, src, dest, 4, MOVE_FROMREG);
}
static size_t
-mov_mr16_r16(char *buf, enum reg dest, enum reg src)
+mov_mr16_r16(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg(buf, src, dest, 2, MOVE_FROMREG);
+ return _move_between_reg_and_memaddr_in_reg(text, src, dest, 2, MOVE_FROMREG);
}
static size_t
-mov_mr8_r8(char *buf, enum reg dest, enum reg src)
+mov_mr8_r8(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg(buf, src, dest, 1, MOVE_FROMREG);
+ return _move_between_reg_and_memaddr_in_reg(text, src, dest, 1, MOVE_FROMREG);
}
static size_t
-mov_r64_mr64(char *buf, enum reg dest, enum reg src)
+mov_r64_mr64(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg(buf, dest, src, 8, MOVE_TOREG);
+ return _move_between_reg_and_memaddr_in_reg(text, dest, src, 8, MOVE_TOREG);
}
static size_t
-mov_r32_mr32(char *buf, enum reg dest, enum reg src)
+mov_r32_mr32(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg(buf, dest, src, 4, MOVE_TOREG);
+ return _move_between_reg_and_memaddr_in_reg(text, dest, src, 4, MOVE_TOREG);
}
static size_t
-mov_r16_mr16(char *buf, enum reg dest, enum reg src)
+mov_r16_mr16(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg(buf, dest, src, 2, MOVE_TOREG);
+ return _move_between_reg_and_memaddr_in_reg(text, dest, src, 2, MOVE_TOREG);
}
static size_t
-mov_r8_mr8(char *buf, enum reg dest, enum reg src)
+mov_r8_mr8(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg(buf, dest, src, 1, MOVE_TOREG);
+ return _move_between_reg_and_memaddr_in_reg(text, dest, src, 1, MOVE_TOREG);
}
static size_t
-_move_between_reg_and_reg(char *buf, enum reg dest, enum reg src, uint8_t opsize)
+_move_between_reg_and_reg(struct data *text, enum reg dest, enum reg src, uint8_t opsize)
{
- uint8_t rex = (src >= 8 ? REX_R : 0) | (dest >= 8 ? REX_B : 0) | (opsize == 8 ? REX_W : 0);
- if (buf) {
+ uint8_t temp, rex = (src >= 8 ? REX_R : 0) | (dest >= 8 ? REX_B : 0) | (opsize == 8 ? REX_W : 0);
+ if (text) {
if (opsize == 2)
- *(buf++) = OP_SIZE_OVERRIDE;
+ array_addlit(text, OP_SIZE_OVERRIDE);
if (rex)
- *(buf++) = rex;
+ array_addlit(text, rex);
- *(buf++) = 0x88 + (opsize != 1);
- *(buf++) = (MOD_DIRECT << 6) | ((src & 7) << 3) | (dest & 7);
+ array_addlit(text, 0x88 + (opsize != 1));
+ array_addlit(text, (MOD_DIRECT << 6) | ((src & 7) << 3) | (dest & 7));
}
return 2 + !!rex + (opsize == 2);
}
static size_t
-mov_r64_r64(char *buf, enum reg dest, enum reg src)
+mov_r64_r64(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_reg(buf, dest, src, 8);
+ return _move_between_reg_and_reg(text, dest, src, 8);
}
static size_t
-mov_r32_r32(char *buf, enum reg dest, enum reg src)
+mov_r32_r32(struct data *text, enum reg dest, enum reg src)
{
- return _move_between_reg_and_reg(buf, dest, src, 4);
+ return _move_between_reg_and_reg(text, dest, src, 4);
}
static size_t
-_move_between_reg_and_memaddr_in_reg_with_disp(char *buf, enum reg reg, enum reg mem, int8_t disp, uint8_t opsize, bool dir)
+_move_between_reg_and_memaddr_in_reg_with_disp(struct data *text, enum reg reg, enum reg mem, int8_t disp, uint8_t opsize, bool dir)
{
assert((reg & 7) != 4 && (mem & 7) != 4);
- uint8_t rex = opsize == 8 ? REX_W : 0;
+ uint8_t temp, rex = opsize == 8 ? REX_W : 0;
rex |= (reg >= 8 ? REX_R : 0) | (mem >= 8 ? REX_B : 0);
- if (buf) {
+ if (text) {
if (opsize == 2)
- *(buf++) = OP_SIZE_OVERRIDE;
+ array_addlit(text, OP_SIZE_OVERRIDE);
if (rex)
- *(buf++) = rex;
+ array_addlit(text, rex);
- *(buf++) = 0x88 + (opsize != 1) + 2*dir;
+ array_addlit(text, 0x88 + (opsize != 1) + 2*dir);
- *(buf++) = (MOD_DISP8 << 6) | ((reg & 7) << 3) | (mem & 7);
- *(buf++) = disp;
+ array_addlit(text, (MOD_DISP8 << 6) | ((reg & 7) << 3) | (mem & 7));
+ array_addlit(text, disp);
}
// 8 and 2 have a length of 3, but 4 and 1 have a length of 2
@@ -338,127 +349,133 @@ _move_between_reg_and_memaddr_in_reg_with_disp(char *buf, enum reg reg, enum reg
}
static size_t
-mov_disp8_m64_r64(char *buf, enum reg dest, int8_t disp, enum reg src)
+mov_disp8_m64_r64(struct data *text, enum reg dest, int8_t disp, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg_with_disp(buf, src, dest, disp, 8, MOVE_FROMREG);
+ return _move_between_reg_and_memaddr_in_reg_with_disp(text, src, dest, disp, 8, MOVE_FROMREG);
}
static size_t
-mov_disp8_m32_r32(char *buf, enum reg dest, int8_t disp, enum reg src)
+mov_disp8_m32_r32(struct data *text, enum reg dest, int8_t disp, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg_with_disp(buf, src, dest, disp, 4, MOVE_FROMREG);
+ return _move_between_reg_and_memaddr_in_reg_with_disp(text, src, dest, disp, 4, MOVE_FROMREG);
}
static size_t
-mov_disp8_m16_r16(char *buf, enum reg dest, int8_t disp, enum reg src)
+mov_disp8_m16_r16(struct data *text, enum reg dest, int8_t disp, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg_with_disp(buf, src, dest, disp, 2, MOVE_FROMREG);
+ return _move_between_reg_and_memaddr_in_reg_with_disp(text, src, dest, disp, 2, MOVE_FROMREG);
}
static size_t
-mov_disp8_m8_r8(char *buf, enum reg dest, int8_t disp, enum reg src)
+mov_disp8_m8_r8(struct data *text, enum reg dest, int8_t disp, enum reg src)
{
- return _move_between_reg_and_memaddr_in_reg_with_disp(buf, src, dest, disp, 1, MOVE_FROMREG);
+ return _move_between_reg_and_memaddr_in_reg_with_disp(text, src, dest, disp, 1, MOVE_FROMREG);
}
static size_t
-mov_disp8_r64_m64(char *buf, enum reg dest, enum reg src, int8_t disp)
+mov_disp8_r64_m64(struct data *text, enum reg dest, enum reg src, int8_t disp)
{
- return _move_between_reg_and_memaddr_in_reg_with_disp(buf, dest, src, disp, 8, MOVE_TOREG);
+ return _move_between_reg_and_memaddr_in_reg_with_disp(text, dest, src, disp, 8, MOVE_TOREG);
}
static size_t
-mov_disp8_r32_m32(char *buf, enum reg dest, enum reg src, int8_t disp)
+mov_disp8_r32_m32(struct data *text, enum reg dest, enum reg src, int8_t disp)
{
- return _move_between_reg_and_memaddr_in_reg_with_disp(buf, dest, src, disp, 4, MOVE_TOREG);
+ return _move_between_reg_and_memaddr_in_reg_with_disp(text, dest, src, disp, 4, MOVE_TOREG);
}
static size_t
-mov_disp8_r16_m16(char *buf, enum reg dest, enum reg src, int8_t disp)
+mov_disp8_r16_m16(struct data *text, enum reg dest, enum reg src, int8_t disp)
{
- return _move_between_reg_and_memaddr_in_reg_with_disp(buf, dest, src, disp, 2, MOVE_TOREG);
+ return _move_between_reg_and_memaddr_in_reg_with_disp(text, dest, src, disp, 2, MOVE_TOREG);
}
static size_t
-mov_disp8_r8_m8(char *buf, enum reg dest, enum reg src, int8_t disp)
+mov_disp8_r8_m8(struct data *text, enum reg dest, enum reg src, int8_t disp)
{
- return _move_between_reg_and_memaddr_in_reg_with_disp(buf, dest, src, disp, 1, MOVE_TOREG);
+ return _move_between_reg_and_memaddr_in_reg_with_disp(text, dest, src, disp, 1, MOVE_TOREG);
}
static size_t
-lea_disp8(char *buf, enum reg dest, enum reg src, int8_t disp)
+lea_disp8(struct data *text, enum reg dest, enum reg src, int8_t disp)
{
+ uint8_t temp;
assert(src != 4);
- if (buf) {
- *(buf++) = REX_W;
- *(buf++) = 0x8d;
- *(buf++) = (MOD_DISP8 << 6) | (dest << 3) | src;
- *(buf++) = disp;
+ if (text) {
+ array_addlit(text, REX_W);
+ array_addlit(text, 0x8d);
+ array_addlit(text, (MOD_DISP8 << 6) | (dest << 3) | src);
+ array_addlit(text, disp);
}
return 4;
}
static size_t
-add_r64_r64(char *buf, enum reg dest, enum reg src)
+add_r64_r64(struct data *text, enum reg dest, enum reg src)
{
- if (buf) {
- *(buf++) = REX_W;
- *(buf++) = 0x03;
- *(buf++) = (MOD_DIRECT << 6) | (dest << 3) | src;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, REX_W);
+ array_addlit(text, 0x03);
+ array_addlit(text, (MOD_DIRECT << 6) | (dest << 3) | src);
}
return 3;
}
static size_t
-sub_r64_r64(char *buf, enum reg dest, enum reg src)
+sub_r64_r64(struct data *text, enum reg dest, enum reg src)
{
- if (buf) {
- *(buf++) = REX_W;
- *(buf++) = 0x2b;
- *(buf++) = (MOD_DIRECT << 6) | (dest << 3) | src;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, REX_W);
+ array_addlit(text, 0x2b);
+ array_addlit(text, (MOD_DIRECT << 6) | (dest << 3) | src);
}
return 3;
}
static size_t
-sub_r64_imm(char *buf, enum reg dest, int32_t imm)
+sub_r64_imm(struct data *text, enum reg dest, int32_t imm)
{
- if (buf) {
- *(buf++) = REX_W;
- *(buf++) = 0x81;
- *(buf++) = (MOD_DIRECT << 6) | (5 << 3) | dest;
- *(buf++) = imm & 0xFF;
- *(buf++) = (imm >> 8) & 0xFF;
- *(buf++) = (imm >> 16) & 0xFF;
- *(buf++) = (imm >> 24) & 0xFF;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, REX_W);
+ array_addlit(text, 0x81);
+ array_addlit(text, (MOD_DIRECT << 6) | (5 << 3) | dest);
+ array_addlit(text, imm & 0xFF);
+ array_addlit(text, (imm >> 8) & 0xFF);
+ array_addlit(text, (imm >> 16) & 0xFF);
+ array_addlit(text, (imm >> 24) & 0xFF);
}
return 7;
}
static size_t
-cmp_r64_r64(char *buf, enum reg reg1, enum reg reg2)
+cmp_r64_r64(struct data *text, enum reg reg1, enum reg reg2)
{
- if (buf) {
- *(buf++) = REX_W;
- *(buf++) = 0x3b;
- *(buf++) = (MOD_DIRECT << 6) | (reg1 << 3) | reg2;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, REX_W);
+ array_addlit(text, 0x3b);
+ array_addlit(text, (MOD_DIRECT << 6) | (reg1 << 3) | reg2);
}
return 3;
}
static size_t
-jng(char *buf, int64_t offset)
+jng(struct data *text, int64_t offset)
{
+ uint8_t temp;
if (-256 <= offset && offset <= 255) {
int8_t i = offset;
- if (buf) {
- *(buf++) = 0x7E;
- *(buf++) = i;
+ if (text) {
+ array_addlit(text, 0x7E);
+ array_addlit(text, i);
}
return 2;
} else {
@@ -469,13 +486,14 @@ jng(char *buf, int64_t offset)
}
static size_t
-jg(char *buf, int64_t offset)
+jg(struct data *text, int64_t offset)
{
+ uint8_t temp;
if (-256 <= offset && offset <= 255) {
int8_t i = offset;
- if (buf) {
- *(buf++) = 0x7F;
- *(buf++) = i;
+ if (text) {
+ array_addlit(text, 0x7F);
+ array_addlit(text, i);
}
return 2;
} else {
@@ -486,13 +504,14 @@ jg(char *buf, int64_t offset)
}
static size_t
-jne(char *buf, int64_t offset)
+jne(struct data *text, int64_t offset)
{
+ uint8_t temp;
if (-256 <= offset && offset <= 255) {
int8_t i = offset;
- if (buf) {
- *(buf++) = 0x75;
- *(buf++) = i;
+ if (text) {
+ array_addlit(text, 0x75);
+ array_addlit(text, i);
}
return 2;
} else {
@@ -503,13 +522,14 @@ jne(char *buf, int64_t offset)
}
static size_t
-jmp(char *buf, int64_t offset)
+jmp(struct data *text, int64_t offset)
{
+ uint8_t temp;
if (-256 <= offset && offset <= 255) {
int8_t i = offset;
- if (buf) {
- *(buf++) = 0xEB;
- *(buf++) = i;
+ if (text) {
+ array_addlit(text, 0xEB);
+ array_addlit(text, i);
}
return 2;
} else {
@@ -520,54 +540,58 @@ jmp(char *buf, int64_t offset)
}
static size_t
-call(char *buf, int32_t offset)
+call(struct data *text, int32_t offset)
{
- if (buf) {
- *(buf++) = 0xE8;
- *(buf++) = (uint32_t) offset & 0xff;
- *(buf++) = ((uint32_t) offset >> 8) & 0xff;
- *(buf++) = ((uint32_t) offset >> 16) & 0xff;
- *(buf++) = ((uint32_t) offset >> 24) & 0xff;
+ uint8_t temp;
+ if (text) {
+ array_addlit(text, 0xE8);
+ array_addlit(text, (uint32_t) offset & 0xff);
+ array_addlit(text, ((uint32_t) offset >> 8) & 0xff);
+ array_addlit(text, ((uint32_t) offset >> 16) & 0xff);
+ array_addlit(text, ((uint32_t) offset >> 24) & 0xff);
}
return 5;
}
static size_t
-ret(char *buf)
+ret(struct data *text)
{
- if (buf)
- *buf = 0xC3;
+ uint8_t temp;
+ if (text)
+ array_addlit(text, 0xC3);
return 1;
}
static size_t
-_pushpop_r64(char *buf, uint8_t ioff, enum reg reg)
+_pushpop_r64(struct data *text, uint8_t ioff, enum reg reg)
{
- if (buf) {
+ uint8_t temp;
+ if (text) {
if (reg >= 8)
- *(buf++) = REX_B;
+ array_addlit(text, REX_B);
- *buf = 0x50 + ioff + (reg & 7);
+ array_addlit(text, 0x50 + ioff + (reg & 7));
}
return reg >= 8 ? 2 : 1;
}
static size_t
-push_r64(char *buf, enum reg reg)
+push_r64(struct data *text, enum reg reg)
{
- return _pushpop_r64(buf, 0, reg);
+ return _pushpop_r64(text, 0, reg);
}
static size_t
-pop_r64(char *buf, enum reg reg)
+pop_r64(struct data *text, enum reg reg)
{
- return _pushpop_r64(buf, 8, reg);
+ return _pushpop_r64(text, 8, reg);
}
-static size_t emitsyscall(char *buf, uint8_t paramcount);
+static size_t emitsyscall(struct data *text, uint8_t paramcount);
+static size_t emitproc(struct data *text, struct iproc *proc);
const struct target x64_target = {
.reserved = (1 << RSP) | (1 << RBP) | (1 << R12) | (1 << R13),
@@ -578,40 +602,41 @@ const struct target x64_target = {
#define NEXT ins++; assert(ins <= end);
static size_t
-emitsyscall(char *buf, uint8_t paramcount)
+emitsyscall(struct data *text, uint8_t paramcount)
{
assert(paramcount < 8);
size_t total = 0;
- total += push_r64(buf ? buf + total : NULL, RBP);
- total += mov_r64_r64(buf ? buf + total : NULL, RBP, RSP);
+ uint8_t temp;
+ total += push_r64(text, RBP);
+ total += mov_r64_r64(text, RBP, RSP);
for (size_t i = 0; i < paramcount; i++) {
- total += push_r64(buf ? buf + total : NULL, abi_arg[i]);
- total += mov_disp8_r64_m64(buf ? buf + total : NULL, abi_arg[i], RBP, 8*i + 16);
+ total += push_r64(text, abi_arg[i]);
+ total += mov_disp8_r64_m64(text, abi_arg[i], RBP, 8*i + 16);
}
- if (buf) {
- *(buf + total++) = 0x0f;
- *(buf + total++) = 0x05;
- } else {
- total += 2;
+ if (text) {
+ array_addlit(text, 0x0f);
+ array_addlit(text, 0x05);
}
- total += mov_disp8_r64_m64(buf ? buf + total : NULL, RDI, RBP, 8*paramcount + 16);
- total += mov_mr64_r64(buf ? buf + total : NULL, RDI, RAX);
+ total += 2;
+
+ total += mov_disp8_r64_m64(text, RDI, RBP, 8*paramcount + 16);
+ total += mov_mr64_r64(text, RDI, RAX);
for (size_t i = paramcount - 1; i < paramcount; i--) {
- total += pop_r64(buf ? buf + total : NULL, abi_arg[i]);
+ total += pop_r64(text, abi_arg[i]);
}
- total += pop_r64(buf ? buf + total : NULL, RBP);
- total += ret(buf ? buf + total : NULL);
+ total += pop_r64(text, RBP);
+ total += ret(text);
return total;
}
size_t
-emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end, uint64_t end_label)
+emitblock(struct data *text, struct iproc *proc, struct instr *start, struct instr *end, uint64_t end_label)
{
struct instr *ins = start ? start : proc->data;
end = end ? end : &proc->data[proc->len];
@@ -624,8 +649,8 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end,
size_t total = 0;
if (!start) {
- total += push_r64(buf ? buf + total : NULL, RBP);
- total += mov_r64_r64(buf ? buf + total : NULL, RBP, RSP);
+ total += push_r64(text, RBP);
+ total += mov_r64_r64(text, RBP, RSP);
}
while (ins < end) {
@@ -640,13 +665,13 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end,
switch (ins->op) {
// FIXME: we don't handle jumps backward yet
case IR_JUMP:
- total += jmp(buf ? buf + total : NULL, emitblock(NULL, proc, ins + 1, end, ins->id));
+ total += jmp(text, emitblock(NULL, proc, ins + 1, end, ins->id));
NEXT;
break;
case IR_RETURN:
- total += add_r64_imm(buf ? buf + total : NULL, RSP, localalloc);
- total += pop_r64(buf ? buf + total : NULL, RBP);
- total += ret(buf ? buf + total : NULL);
+ total += add_r64_imm(text, RSP, localalloc);
+ total += pop_r64(text, RBP);
+ total += ret(text);
NEXT;
break;
case IR_SIZE:
@@ -658,7 +683,7 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end,
src = proc->intervals.data[ins->id].reg;
NEXT;
assert(ins->op == IR_EXTRA);
- total += mov_mr64_r64(buf ? buf + total : NULL, proc->intervals.data[ins->id].reg, src);
+ total += mov_mr64_r64(text, proc->intervals.data[ins->id].reg, src);
NEXT;
break;
default:
@@ -676,9 +701,9 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end,
switch (ins->op) {
case IR_CEQ:
- total += mov_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ total += mov_r64_r64(text, dest, proc->intervals.data[ins->id].reg);
NEXT;
- total += cmp_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ total += cmp_r64_r64(text, dest, proc->intervals.data[ins->id].reg);
NEXT;
if (ins->op == IR_CONDJUMP) {
curi++;
@@ -686,32 +711,32 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end,
NEXT;
assert(ins->op == IR_EXTRA);
if (ins->id == tmp) {
- total += jne(buf ? buf + total : NULL, emitblock(NULL, proc, ins + 1, end, label));
+ total += jne(text, emitblock(NULL, proc, ins + 1, end, label));
}
NEXT;
}
break;
case IR_ADD:
- total += mov_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ total += mov_r64_r64(text, dest, proc->intervals.data[ins->id].reg);
NEXT;
- total += add_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ total += add_r64_r64(text, dest, proc->intervals.data[ins->id].reg);
NEXT;
break;
case IR_IMM:
- total += mov_r64_imm(buf ? buf + total : NULL, dest, ins->id);
+ total += mov_r64_imm(text, dest, ins->id);
NEXT;
break;
case IR_IN:
- total += mov_disp8_r64_m64(buf ? buf + total : NULL, dest, RBP, 8*ins->id + 16);
+ total += mov_disp8_r64_m64(text, dest, RBP, 8*ins->id + 16);
NEXT;
break;
case IR_LOAD:
- total += mov_r64_mr64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ total += mov_r64_mr64(text, dest, proc->intervals.data[ins->id].reg);
NEXT;
break;
case IR_ALLOC:
- total += mov_r64_r64(buf ? buf + total : NULL, dest, RSP);
- total += sub_r64_imm(buf ? buf + total : NULL, RSP, 8); // FIXME: hardcoding
+ total += mov_r64_r64(text, dest, RSP);
+ total += sub_r64_imm(text, RSP, 8); // FIXME: hardcoding
localalloc += 8;
NEXT;
break;
@@ -725,25 +750,25 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end,
for (int i = 0; i < 16; i++) {
if (active & (1 << i)) {
- total += push_r64(buf ? buf + total : NULL, i);
+ total += push_r64(text, i);
}
}
NEXT;
while (ins->op == IR_CALLARG) {
count++;
- total += push_r64(buf ? buf + total : NULL, proc->intervals.data[ins->id].reg);
+ total += push_r64(text, proc->intervals.data[ins->id].reg);
NEXT;
}
// we assume call is constant width - this should probably change
offset = -(proc->addr + total - toplevel.code.data[dest].addr + call(NULL, 0));
- total += call(buf ? buf + total : NULL, offset);
+ total += call(text, offset);
// FIXME: this won't work with non-64-bit things
- total += add_r64_imm(buf ? buf + total : NULL, RSP, 8*count);
+ total += add_r64_imm(text, RSP, 8*count);
for (int i = 15; i >= 0; i--) {
if (active & (1 << i)) {
- total += pop_r64(buf ? buf + total : NULL, i);
+ total += pop_r64(text, i);
}
}
break;
@@ -768,7 +793,7 @@ done:
// FIXME: use array_push
size_t
-emitproc(char *buf, struct iproc *proc)
+emitproc(struct data *text, struct iproc *proc)
{
- return emitblock(buf, proc, NULL, NULL, 0);
+ return emitblock(text, proc, NULL, NULL, 0);
}
diff --git a/x64.h b/x64.h
@@ -19,5 +19,3 @@ enum reg {
extern char abi_arg[];
extern unsigned short used_reg;
-
-size_t emitproc(char *buf, struct iproc *proc);