instruction init

This commit is contained in:
Benedek László 2024-05-16 19:01:49 +02:00
parent 0def8039e1
commit 5fc36bc7f7
5 changed files with 118 additions and 16 deletions

View File

@ -1,4 +1,5 @@
#include "classfile.h" #include "classfile.h"
#include "instruction.h"
#include <assert.h> #include <assert.h>
#include <memory.h> #include <memory.h>
#include <stddef.h> #include <stddef.h>
@ -359,18 +360,18 @@ ClassFile* ClassFile_load(const char* path) {
} }
void ClassFile_info(const ClassFile* cf) { void ClassFile_info(const ClassFile* cf) {
printf( printf("Metadata:\n"
"magic=%X\n" "\tmagic=%X\n"
"minor_version=%hu\n" "\tminor_version=%hu\n"
"major_version=%hu\n" "\tmajor_version=%hu\n"
"constant_pool_count=%hu\n" "\tconstant_pool_count=%hu\n"
"access_flags=%hx\n" "\taccess_flags=%hx\n"
"this_class=%hu\n" "\tthis_class=%hu\n"
"super_class=%hu\n" "\tsuper_class=%hu\n"
"interfaces_count=%hu\n" "\tinterfaces_count=%hu\n"
"fields_count=%hu\n" "\tfields_count=%hu\n"
"methods_count=%hu\n" "\tmethods_count=%hu\n"
"attributes_count=%hu\n", "\tattributes_count=%hu\n\n",
cf->magic, cf->minor_version, cf->major_version, cf->constant_pool_count, cf->access_flags, cf->this_class, cf->super_class, cf->interfaces_count, cf->magic, cf->minor_version, cf->major_version, cf->constant_pool_count, cf->access_flags, cf->this_class, cf->super_class, cf->interfaces_count,
cf->fields_count, cf->methods_count, cf->attributes_count); cf->fields_count, cf->methods_count, cf->attributes_count);
@ -426,7 +427,7 @@ void ClassFile_info(const ClassFile* cf) {
buffer); buffer);
free(buffer); free(buffer);
default: default:
putchar('\n'); printf("\n");
} }
} }
@ -435,7 +436,7 @@ void ClassFile_info(const ClassFile* cf) {
char* super_name = char* super_name =
cf->super_class != 0 ? (char*)cf->constant_pool[cf->constant_pool[cf->super_class - 1].info.class_info.name_index - 1].info.utf8_info.bytes : NULL; cf->super_class != 0 ? (char*)cf->constant_pool[cf->constant_pool[cf->super_class - 1].info.class_info.name_index - 1].info.utf8_info.bytes : NULL;
char* type = (cf->access_flags & ACC_INTERFACE ? "interface" : (cf->access_flags & ACC_ENUM ? "enum" : (cf->access_flags & ACC_MODULE ? "module" : "class"))); char* type = (cf->access_flags & ACC_INTERFACE ? "interface" : (cf->access_flags & ACC_ENUM ? "enum" : (cf->access_flags & ACC_MODULE ? "module" : "class")));
printf("%s%s%s%s %s%s%s ", cf->access_flags & ACC_PUBLIC ? "public " : "", cf->access_flags & ACC_FINAL ? "final " : "", printf("\n%s%s%s%s %s%s%s ", cf->access_flags & ACC_PUBLIC ? "public " : "", cf->access_flags & ACC_FINAL ? "final " : "",
cf->access_flags & ACC_ABSTRACT ? "abstract " : "", type, this_name, super_name ? " extends " : "", super_name ? super_name : ""); cf->access_flags & ACC_ABSTRACT ? "abstract " : "", type, this_name, super_name ? " extends " : "", super_name ? super_name : "");
// interfaces // interfaces
@ -476,7 +477,18 @@ void ClassFile_info(const ClassFile* cf) {
for (u2 j = 0; j < cf->methods[i].attributes_count; j++) { for (u2 j = 0; j < cf->methods[i].attributes_count; j++) {
} }
printf(";\n"); printf("{\n");
// code
for (u2 j = 0; j < cf->methods[i].attributes_count; j++) {
if (cf->methods[i].attributes[j]._tag == CODE) {
Instruction* code = Instruction_parse(cf->methods[i].attributes[j].info.code_attribute.code_length, cf->methods[i].attributes[j].info.code_attribute.code);
Instruction_print_code(code);
// TODO: free code
}
}
printf("\t}\n\n");
} }
} }

View File

@ -8,6 +8,7 @@
typedef uint8_t u1; typedef uint8_t u1;
typedef uint16_t u2; typedef uint16_t u2;
typedef uint32_t u4; typedef uint32_t u4;
typedef uint64_t u8;
typedef enum { typedef enum {
ACC_PUBLIC = 0x0001, ACC_PUBLIC = 0x0001,

65
instruction.c Normal file
View File

@ -0,0 +1,65 @@
#include "instruction.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "classfile.h"
Instruction* Instruction_parse(uint32_t bytes_length, uint8_t* bytes) {
Instruction* start = (Instruction*)malloc(sizeof(Instruction));
Instruction* current = start;
u4 i = 0, n = 0;
while (i < bytes_length) {
current->opcode = bytes[i++];
switch (current->opcode) {
case ALOAD_0:
case RETURN:
current->operands = NULL;
break;
case LDC:
*(u1*)&current->operands = bytes[i++];
break;
case GETSTATIC:
case INVOKESPECIAL:
case INVOKEVIRTUAL:
// current->operands = malloc(sizeof(u2));
*(u2*)&current->operands = (*(u2*)&bytes[i] << 8) | bytes[i + 1];
i += 2;
break;
}
if (i < bytes_length) {
current->next = (Instruction*)malloc(sizeof(Instruction));
current = current->next;
} else {
current->next = NULL;
}
}
return start;
}
void Instruction_print_code(Instruction* code) {
u4 i = 0;
while (code) {
printf("\t\t%hx ", (u1)code[i].opcode);
switch (code[i].opcode) {
case ALOAD_0:
case RETURN:
putchar('\n');
break;
case LDC:
printf("#%hhu\n", *(u1*)&code[i].operands);
break;
case GETSTATIC:
case INVOKESPECIAL:
case INVOKEVIRTUAL:
printf("#%hu\n", *(u2*)&code[i].operands);
break;
}
code = code->next;
}
}

24
instruction.h Normal file
View File

@ -0,0 +1,24 @@
#include <stddef.h>
#include <stdint.h>
#pragma pack(1)
typedef enum {
ALOAD_0 = 0x2a,
INVOKESPECIAL = 0xb7,
RETURN = 0xb1,
GETSTATIC = 0xb2,
LDC = 0x12,
INVOKEVIRTUAL = 0xb6,
} OPCODE;
typedef struct Instruction {
OPCODE opcode;
uint8_t* operands;
struct Instruction* next;
} Instruction;
Instruction* Instruction_parse(uint32_t bytes_length, uint8_t* bytes);
void Instruction_print_code(Instruction* code);
#pragma pack()

2
main.c
View File

@ -1,6 +1,6 @@
#include "classfile.h" #include "classfile.h"
int main(int argc, char **argv) { int main(int argc, char **argv) {
ClassFile *cf = ClassFile_load("test/Main.class"); ClassFile *cf = ClassFile_load("Main.class");
ClassFile_info(cf); ClassFile_info(cf);
} }