diff options
82 files changed, 981 insertions, 11486 deletions
@@ -25,6 +25,7 @@ else liblog \ libnetutils \ libpixelflinger \ + libusbhost \ libzipfile \ )) endif diff --git a/adb/commandline.c b/adb/commandline.c index dcba83b..3600e5a 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -838,12 +838,24 @@ top: return adb_send_emulator_command(argc, argv); } - if(!strcmp(argv[0], "shell")) { + if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) { int r; int fd; + char h = (argv[0][0] == 'h'); + + if (h) { + printf("\x1b[41;33m"); + fflush(stdout); + } + if(argc < 2) { - return interactive_shell(); + r = interactive_shell(); + if (h) { + printf("\x1b[0m"); + fflush(stdout); + } + return r; } snprintf(buf, sizeof buf, "shell:%s", argv[1]); @@ -877,6 +889,10 @@ top: adb_sleep_ms(1000); do_cmd(ttype, serial, "wait-for-device", 0); } else { + if (h) { + printf("\x1b[0m"); + fflush(stdout); + } return r; } } diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c index 24b7e72..39835ac 100644 --- a/debuggerd/debuggerd.c +++ b/debuggerd/debuggerd.c @@ -40,6 +40,7 @@ #include <private/android_filesystem_config.h> +#include <byteswap.h> #include "utility.h" #ifdef WITH_VFP @@ -354,6 +355,73 @@ void dump_crash_banner(int tfd, unsigned pid, unsigned tid, int sig) if(sig) dump_fault_addr(tfd, tid, sig); } +/* After randomization (ASLR), stack contents that point to randomized + * code become uninterpretable (e.g. can't be resolved to line numbers). + * Here, we bundle enough information so that stack analysis on the + * server side can still be performed. This means we are leaking some + * information about the device (its randomization base). We have to make + * sure an attacker has no way of intercepting the tombstone. + */ + +typedef struct { + int32_t mmap_addr; + char tag[4]; /* 'P', 'R', 'E', ' ' */ +} prelink_info_t __attribute__((packed)); + +static inline void set_prelink(long *prelink_addr, + prelink_info_t *info) +{ + // We will assume the binary is little-endian, and test the + // host endianness here. + unsigned long test_endianness = 0xFF; + + if (sizeof(prelink_info_t) == 8 && prelink_addr) { + if (*(unsigned char *)&test_endianness) + *prelink_addr = info->mmap_addr; + else + *prelink_addr = bswap_32(info->mmap_addr); + } +} + +static int check_prelinked(const char *fname, + long *prelink_addr) +{ + *prelink_addr = 0; + if (sizeof(prelink_info_t) != 8) return 0; + + int fd = open(fname, O_RDONLY); + if (fd < 0) return 0; + off_t end = lseek(fd, 0, SEEK_END); + int nr = sizeof(prelink_info_t); + + off_t sz = lseek(fd, -nr, SEEK_CUR); + if ((long)(end - sz) != (long)nr) return 0; + if (sz == (off_t)-1) return 0; + + prelink_info_t info; + int num_read = read(fd, &info, nr); + if (num_read < 0) return 0; + if (num_read != sizeof(info)) return 0; + + int prelinked = 0; + if (!strncmp(info.tag, "PRE ", 4)) { + set_prelink(prelink_addr, &info); + prelinked = 1; + } + if (close(fd) < 0) return 0; + return prelinked; +} + +void dump_randomization_base(int tfd, bool at_fault) { + bool only_in_tombstone = !at_fault; + long prelink_addr; + check_prelinked("/system/lib/libc.so", &prelink_addr); + _LOG(tfd, only_in_tombstone, + "\nlibc base address: %08x\n", prelink_addr); +} + +/* End of ASLR-related logic. */ + static void parse_elf_info(mapinfo *milist, pid_t pid) { mapinfo *mi; @@ -439,6 +507,7 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) dump_pc_and_lr(tfd, tid, milist, stack_depth, at_fault); } + dump_randomization_base(tfd, at_fault); dump_stack_and_code(tfd, tid, milist, stack_depth, sp_list, at_fault); while(milist) { diff --git a/fastboot/engine.c b/fastboot/engine.c index 48073ee..28a0ad9 100644 --- a/fastboot/engine.c +++ b/fastboot/engine.c @@ -277,11 +277,11 @@ void fb_queue_notice(const char *notice) a->data = (void*) notice; } -void fb_execute_queue(usb_handle *usb) +int fb_execute_queue(usb_handle *usb) { Action *a; char resp[FB_RESPONSE_SZ+1]; - int status; + int status = 0; a = action_list; resp[FB_RESPONSE_SZ] = 0; @@ -314,5 +314,5 @@ void fb_execute_queue(usb_handle *usb) } fprintf(stderr,"finished. total time: %.3fs\n", (now() - start)); + return status; } - diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c index f3bfbeba..63208bc 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.c @@ -552,11 +552,12 @@ int main(int argc, char **argv) void *data; unsigned sz; unsigned page_size = 2048; + int status; skip(1); if (argc == 0) { usage(); - return 0; + return 1; } if (!strcmp(*argv, "devices")) { @@ -688,6 +689,7 @@ int main(int argc, char **argv) argc = do_oem_command(argc, argv); } else { usage(); + return 1; } } @@ -703,6 +705,6 @@ int main(int argc, char **argv) usb = open_device(); - fb_execute_queue(usb); - return 0; + status = fb_execute_queue(usb); + return (status) ? 1 : 0; } diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h index a36c569..a4b27a0 100644 --- a/fastboot/fastboot.h +++ b/fastboot/fastboot.h @@ -49,7 +49,7 @@ void fb_queue_reboot(void); void fb_queue_command(const char *cmd, const char *msg); void fb_queue_download(const char *name, void *data, unsigned size); void fb_queue_notice(const char *notice); -void fb_execute_queue(usb_handle *usb); +int fb_execute_queue(usb_handle *usb); /* util stuff */ void die(const char *fmt, ...); diff --git a/fastboot/usb_osx.c b/fastboot/usb_osx.c index 9488687..570a456 100644 --- a/fastboot/usb_osx.c +++ b/fastboot/usb_osx.c @@ -231,8 +231,7 @@ static int try_interfaces(IOUSBDeviceInterface182 **dev, usb_handle *handle) { kr = (*interface)->ClearPipeStallBothEnds(interface, handle->bulkIn); if (kr != 0) { - ERR("could not clear input pipe; result %d", kr); - return -1; + ERR("could not clear input pipe; result %x, ignoring...\n", kr); } } @@ -240,8 +239,7 @@ static int try_interfaces(IOUSBDeviceInterface182 **dev, usb_handle *handle) { kr = (*interface)->ClearPipeStallBothEnds(interface, handle->bulkOut); if (kr != 0) { - ERR("could not clear output pipe; result %d", kr); - return -1; + ERR("could not clear output pipe; result %x, ignoring....\n", kr); } } diff --git a/include/acc/acc.h b/include/acc/acc.h deleted file mode 100644 index 1182355..0000000 --- a/include/acc/acc.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_ACC_ACC_H -#define ANDROID_ACC_ACC_H - -#include <stdint.h> -#include <sys/types.h> - -typedef char ACCchar; -typedef int32_t ACCint; -typedef uint32_t ACCuint; -typedef ssize_t ACCsizei; -typedef unsigned int ACCenum; -typedef void ACCvoid; -typedef struct ACCscript ACCscript; - -#define ACC_NO_ERROR 0x0000 -#define ACC_INVALID_ENUM 0x0500 -#define ACC_INVALID_OPERATION 0x0502 -#define ACC_INVALID_VALUE 0x0501 -#define ACC_OUT_OF_MEMORY 0x0505 - -#define ACC_COMPILE_STATUS 0x8B81 -#define ACC_INFO_LOG_LENGTH 0x8B84 - - -// ---------------------------------------------------------------------------- - -#ifdef __cplusplus -extern "C" { -#endif - -ACCscript* accCreateScript(); - -void accDeleteScript(ACCscript* script); - -typedef ACCvoid* (*ACCSymbolLookupFn)(ACCvoid* pContext, const ACCchar * name); - -void accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn, - ACCvoid* pContext); - -ACCenum accGetError( ACCscript* script ); - -void accScriptSource(ACCscript* script, - ACCsizei count, - const ACCchar** string, - const ACCint* length); - -void accCompileScript(ACCscript* script); - -void accGetScriptiv(ACCscript* script, - ACCenum pname, - ACCint* params); - -void accGetScriptInfoLog(ACCscript* script, - ACCsizei maxLength, - ACCsizei* length, - ACCchar* infoLog); - -void accGetScriptLabel(ACCscript* script, const ACCchar * name, - ACCvoid** address); - -void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount, - ACCsizei maxStringCount, ACCchar** strings); - -/* Used to implement disassembly */ - -void accGetProgramBinary(ACCscript* script, - ACCvoid** base, - ACCsizei* length); - -#ifdef __cplusplus -}; -#endif - -// ---------------------------------------------------------------------------- - -#endif diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h index 32b7026..5e1e031 100644 --- a/include/arch/linux-arm/AndroidConfig.h +++ b/include/arch/linux-arm/AndroidConfig.h @@ -206,7 +206,9 @@ /* * Add any extra platform-specific defines here. */ +#ifndef __linux__ #define __linux__ +#endif /* * Define if we have <malloc.h> header diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 8acca5a..126ba70 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -161,6 +161,7 @@ static struct fs_path_config android_files[] = { { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/main.conf" }, { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/input.conf" }, { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/audio.conf" }, + { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/network.conf" }, { 00444, AID_NET_BT, AID_NET_BT, "system/etc/bluetooth/blacklist.conf" }, { 00640, AID_SYSTEM, AID_SYSTEM, "system/etc/bluetooth/auto_pairing.conf" }, { 00444, AID_RADIO, AID_AUDIO, "system/etc/AudioPara4.csv" }, diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h new file mode 100644 index 0000000..f7cc52e --- /dev/null +++ b/include/usbhost/usbhost.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __USB_HOST_H +#define __USB_HOST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +struct usb_host_context; +struct usb_endpoint_descriptor; + +struct usb_descriptor_iter { + unsigned char* config; + unsigned char* config_end; + unsigned char* curr_desc; +}; + +/* Callback for notification when new USB devices are attached. + * Return true to exit from usb_host_run. + */ +typedef int (* usb_device_added_cb)(const char *dev_name, void *client_data); + +/* Callback for notification when USB devices are removed. + * Return true to exit from usb_host_run. + */ +typedef int (* usb_device_removed_cb)(const char *dev_name, void *client_data); + +/* Callback indicating that initial device discovery is done. + * Return true to exit from usb_host_run. + */ +typedef int (* usb_discovery_done_cb)(void *client_data); + +/* Call this to initialize the USB host library. */ +struct usb_host_context *usb_host_init(void); + +/* Call this to cleanup the USB host library. */ +void usb_host_cleanup(struct usb_host_context *context); + +/* Call this to monitor the USB bus for new and removed devices. + * This is intended to be called from a dedicated thread, + * as it will not return until one of the callbacks returns true. + * added_cb will be called immediately for each existing USB device, + * and subsequently each time a new device is added. + * removed_cb is called when USB devices are removed from the bus. + * discovery_done_cb is called after the initial discovery of already + * connected devices is complete. + */ +void usb_host_run(struct usb_host_context *context, + usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + usb_discovery_done_cb discovery_done_cb, + void *client_data); + +/* Creates a usb_device object for a USB device */ +struct usb_device *usb_device_open(const char *dev_name); + +/* Releases all resources associated with the USB device */ +void usb_device_close(struct usb_device *device); + +/* Returns the name for the USB device, which is the same as + * the dev_name passed to usb_device_open() + */ +const char* usb_device_get_name(struct usb_device *device); + +/* Returns a unique ID for the device. Currently this is generated from the + * dev_name path. + */ +int usb_device_get_unique_id(struct usb_device *device); + +int usb_device_get_unique_id_from_name(const char* name); + +/* Returns the USB vendor ID from the device descriptor for the USB device */ +uint16_t usb_device_get_vendor_id(struct usb_device *device); + +/* Returns the USB product ID from the device descriptor for the USB device */ +uint16_t usb_device_get_product_id(struct usb_device *device); + +/* Sends a control message to the specified device on endpoint zero */ +int usb_device_send_control(struct usb_device *device, + int requestType, + int request, + int value, + int index, + int length, + void* buffer); + +/* Returns a USB descriptor string for the given string ID. + * Used to implement usb_device_get_manufacturer_name, + * usb_device_get_product_name and usb_device_get_serial. + * Call free() to free the result when you are done with it. + */ +char* usb_device_get_string(struct usb_device *device, int id); + +/* Returns the manufacturer name for the USB device. + * Call free() to free the result when you are done with it. + */ +char* usb_device_get_manufacturer_name(struct usb_device *device); + +/* Returns the product name for the USB device. + * Call free() to free the result when you are done with it. + */ +char* usb_device_get_product_name(struct usb_device *device); + +/* Returns the USB serial number for the USB device. + * Call free() to free the result when you are done with it. + */ +char* usb_device_get_serial(struct usb_device *device); + +/* Returns true if we have write access to the USB device, + * and false if we only have access to the USB device configuration. + */ +int usb_device_is_writeable(struct usb_device *device); + +/* Initializes a usb_descriptor_iter, which can be used to iterate through all + * the USB descriptors for a USB device. + */ +void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter); + +/* Returns the next USB descriptor for a device, or NULL if we have reached the + * end of the list. + */ +struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter); + +/* Claims the specified interface of a USB device */ +int usb_device_claim_interface(struct usb_device *device, unsigned int interface); + +/* Releases the specified interface of a USB device */ +int usb_device_release_interface(struct usb_device *device, unsigned int interface); + + +/* Creates a new usb_endpoint for the specified endpoint of a USB device. + * This can be used to read or write data across the endpoint. + */ +struct usb_endpoint *usb_endpoint_open(struct usb_device *dev, + const struct usb_endpoint_descriptor *desc); + +/* Releases all resources associated with the endpoint */ +void usb_endpoint_close(struct usb_endpoint *ep); + +/* Begins a read or write operation on the specified endpoint */ +int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len); + + /* Waits for the results of a previous usb_endpoint_queue operation on the + * specified endpoint. Returns number of bytes transferred, or a negative + * value for error. + */ +int usb_endpoint_wait(struct usb_device *device, int *out_ep_num); + +/* Cancels a pending usb_endpoint_queue() operation on an endpoint. */ +int usb_endpoint_cancel(struct usb_endpoint *ep); + +/* Returns the usb_device for the given endpoint */ +struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep); + +/* Returns the endpoint address for the given endpoint */ +int usb_endpoint_number(struct usb_endpoint *ep); + +/* Returns the maximum packet size for the given endpoint. + * For bulk endpoints this should be 512 for highspeed or 64 for fullspeed. + */ +int usb_endpoint_max_packet(struct usb_endpoint *ep); + +#ifdef __cplusplus +} +#endif +#endif /* __USB_HOST_H */ diff --git a/init/builtins.c b/init/builtins.c index e0ccf9f..4326ebc 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -258,7 +258,6 @@ static struct { const char *name; unsigned flag; } mount_flags[] = { - { "move", MS_MOVE }, { "noatime", MS_NOATIME }, { "nosuid", MS_NOSUID }, { "nodev", MS_NODEV }, diff --git a/init/devices.c b/init/devices.c index d7aa3a6..5a580fa 100644 --- a/init/devices.c +++ b/init/devices.c @@ -261,6 +261,57 @@ static void parse_event(const char *msg, struct uevent *uevent) uevent->firmware, uevent->major, uevent->minor); } +static char **get_character_device_symlinks(struct uevent *uevent) +{ + const char *parent; + char *slash; + char **links; + int link_num = 0; + int width; + + if (strncmp(uevent->path, "/devices/platform/", 18)) + return NULL; + + links = malloc(sizeof(char *) * 2); + if (!links) + return NULL; + memset(links, 0, sizeof(char *) * 2); + + /* skip "/devices/platform/<driver>" */ + parent = strchr(uevent->path + 18, '/'); + if (!*parent) + goto err; + + if (!strncmp(parent, "/usb", 4)) { + /* skip root hub name and device. use device interface */ + while (*++parent && *parent != '/'); + if (*parent) + while (*++parent && *parent != '/'); + if (!*parent) + goto err; + slash = strchr(++parent, '/'); + if (!slash) + goto err; + width = slash - parent; + if (width <= 0) + goto err; + + if (asprintf(&links[link_num], "/dev/usb/%s%.*s", uevent->subsystem, width, parent) > 0) + link_num++; + else + links[link_num] = NULL; + mkdir("/dev/usb", 0755); + } + else { + goto err; + } + + return links; +err: + free(links); + return NULL; +} + static char **parse_platform_block_device(struct uevent *uevent) { const char *driver; @@ -404,6 +455,7 @@ static void handle_device_event(struct uevent *uevent) name += 4; } else base = "/dev/"; + links = get_character_device_symlinks(uevent); } if (!devpath_ready) diff --git a/init/init.c b/init/init.c index 8f95da7..98539b8 100755 --- a/init/init.c +++ b/init/init.c @@ -673,7 +673,7 @@ int main(int argc, char **argv) mkdir("/proc", 0755); mkdir("/sys", 0755); - mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755"); + mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); diff --git a/libacc/Android.mk b/libacc/Android.mk deleted file mode 100644 index 5101e16..0000000 --- a/libacc/Android.mk +++ /dev/null @@ -1,31 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -# Shared library for target -# ======================================================== - -LOCAL_MODULE:= libacc -LOCAL_SRC_FILES := acc.cpp - -LOCAL_SHARED_LIBRARIES := libdl libcutils - -include $(BUILD_SHARED_LIBRARY) - -# Static library for host -# ======================================================== - -include $(CLEAR_VARS) -LOCAL_MODULE:= libacc -LOCAL_SRC_FILES := acc.cpp - -LOCAL_CFLAGS := -O0 -g - -LOCAL_STATIC_LIBRARIES := libcutils -LOCAL_LDLIBS := -ldl - -include $(BUILD_HOST_STATIC_LIBRARY) - -# Build children -# ======================================================== - -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/libacc/FEATURES b/libacc/FEATURES deleted file mode 100644 index 20f9d98..0000000 --- a/libacc/FEATURES +++ /dev/null @@ -1,89 +0,0 @@ - -Supported C language subset: - - - Expressions: - - * binary operators, by decreasing priority order: '*' '/' '%', - '+' '-', '>>' '<<', '<' '<=' '>' '>=', '==' '!=', '&', - '^', '|', '=', '&&', '||'. - - * '&&' and '||' have the same semantics as C : left to right - evaluation and early exit. - - * Parenthesis are supported. - - * Comma operator is supported. - - * Trinary operator (?:) is not supported. - - * Unary operators: '&', '*' (pointer indirection), '-' - (negation), '+', '!', '~', '++' and '--'. - - * Pointer indirection ('*') is supported. - - * Square brackets are supported. - - * '=' and <op>= are supported. - - * Function calls are supported with standard Linux calling - convention. Function pointers are supported. - Functions can be used before being declared. - - - sizeof() is not supported. - - - Types: - + int, short, char, float, double - + pointers - + variables can be initialized in declarations. - + Only ANSI-style function declarations are supported. - - "..." is not supported. - - short is supported - - const is not supported - - signed and unsigned are not supported. - - arrays are supported - - long doubles are not supported - - structs and unions are supported - - typedef is supported - - explicit storage class specifiers are not supported: register, auto, static, extern - - - Unknown functions and variables are bound at compile time by calling - back to the caller. For the 'acc' command-line tool unknown functions - and variables are looked up using dlsym, to allow using many libc - functions and variables. - - - Instructions: blocks ('{' '}') are supported as in C. 'if' and - 'else' can be used for tests. The 'while' and 'for' C constructs - are supported for loops. 'break' can be used to exit - loops. 'return' is used for the return value of a function. - - - switch / case is not supported. - - goto and labels are not supported. - - continue is not supported. - - - Identifiers are parsed the same way as C. Local variables are - handled, but there is no local name space (not a problem if - different names are used for local and global variables). - - - Numbers can be entered in decimal, hexadecimal ('0x' or '0X' - prefix), or octal ('0' prefix). - - - Float and double constants are supported. - - - '#define' is supported without function like arguments. - - Macro recursion is allowed. - - Self-referential macros are handled as in gcc. - - '#pragma' is supported. The pragma text is passed to a callback function, - and is used to implement meta-information. - - Other preprocessor directives are ignored. - - - C Strings and C character constants are supported. All ANSI C - character escapes are supported. - - - Both C comments ( /* */ ) and C++ comments ( // ... end-of-line ) are - supported. - - - Some syntax errors are reported, others may cause a crash. - - - Memory: the code, data, and symbol sizes are limited to 100KB - (it can be changed in the source code). - diff --git a/libacc/LICENSE b/libacc/LICENSE deleted file mode 100644 index aea41e0..0000000 --- a/libacc/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - Obfuscated Tiny C Compiler - - Copyright (C) 2001-2003 Fabrice Bellard - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product and its documentation - *is* required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - diff --git a/libacc/MODULE_LICENSE_BSD_LIKE b/libacc/MODULE_LICENSE_BSD_LIKE deleted file mode 100644 index e69de29..0000000 --- a/libacc/MODULE_LICENSE_BSD_LIKE +++ /dev/null diff --git a/libacc/acc.cpp b/libacc/acc.cpp deleted file mode 100644 index 6e13f9a..0000000 --- a/libacc/acc.cpp +++ /dev/null @@ -1,6407 +0,0 @@ -/* - * Android "Almost" C Compiler. - * This is a compiler for a small subset of the C language, intended for use - * in scripting environments where speed and memory footprint are important. - * - * This code is based upon the "unobfuscated" version of the - * Obfuscated Tiny C compiler, see the file LICENSE for details. - * - */ - -#define LOG_TAG "acc" -#include <cutils/log.h> - -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <cutils/hashmap.h> - -#include <sys/mman.h> - -#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) -#define MAP_ANONYMOUS MAP_ANON -#endif - -#if defined(__arm__) -#define DEFAULT_ARM_CODEGEN -#define PROVIDE_ARM_CODEGEN -#elif defined(__i386__) -#define DEFAULT_X86_CODEGEN -#define PROVIDE_X86_CODEGEN -#elif defined(__x86_64__) -#define DEFAULT_X64_CODEGEN -#define PROVIDE_X64_CODEGEN -#endif - -#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) -#define ARM_USE_VFP -#endif - -#include <acc/acc.h> - -#define LOG_API(...) do {} while(0) -// #define LOG_API(...) fprintf (stderr, __VA_ARGS__) - -#define LOG_STACK(...) do {} while(0) -// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__) - -// #define PROVIDE_TRACE_CODEGEN - -// Uncomment to disable ARM peephole optimizations -// #define DISABLE_ARM_PEEPHOLE - -// Uncomment to save input to a text file in DEBUG_DUMP_PATTERN -// #define DEBUG_SAVE_INPUT_TO_FILE - -#ifdef DEBUG_SAVE_INPUT_TO_FILE -#ifdef ARM_USE_VFP -#define DEBUG_DUMP_PATTERN "/data/misc/acc_dump/%d.c" -#else -#define DEBUG_DUMP_PATTERN "/tmp/acc_dump/%d.c" -#endif -#endif - -#define assert(b) assertImpl(b, __LINE__) - -namespace acc { - -// Subset of STL vector. -template<class E> class Vector { - public: - Vector() { - mpBase = 0; - mUsed = 0; - mSize = 0; - } - - ~Vector() { - if (mpBase) { - clear(); - free(mpBase); - } - } - - inline E& operator[](size_t i) { - return mpBase[i]; - } - - inline E& front() { - return mpBase[0]; - } - - inline E& back() { - return mpBase[mUsed - 1]; - } - - void pop_back() { - mUsed -= 1; - mpBase[mUsed].~E(); - } - - void push_back(const E& item) { - * ensure(1) = item; - } - - inline size_t size() { - return mUsed; - } - - void clear() { - if (mpBase) { - size_t used = mUsed; - for(size_t i = 0; i < used; i++) { - mpBase[i].~E(); - } - } - mUsed = 0; - } - -private: - E* ensure(int n) { - size_t newUsed = mUsed + n; - if (newUsed > mSize) { - size_t newSize = mSize * 2 + 10; - if (newSize < newUsed) { - newSize = newUsed; - } - mpBase = (E*) realloc(mpBase, sizeof(E) * newSize); - mSize = newSize; - } - E* result = mpBase + mUsed; - mUsed = newUsed; - return result; - } - - E* mpBase; - size_t mUsed; - size_t mSize; -}; - -class ErrorSink { -public: - void error(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - verror(fmt, ap); - va_end(ap); - } - - virtual ~ErrorSink() {} - virtual void verror(const char* fmt, va_list ap) = 0; -}; - -class Compiler : public ErrorSink { - typedef int tokenid_t; - enum TypeTag { - TY_UNKNOWN = -1, - TY_INT, // 0 - TY_CHAR, // 1 - TY_SHORT, // 2 - TY_VOID, // 3 - TY_FLOAT, // 4 - TY_DOUBLE, // 5 - TY_POINTER, // 6 - TY_ARRAY, // 7 - TY_STRUCT, // 8 - TY_FUNC, // 9 - TY_PARAM // 10 - }; - - enum StorageClass { - SC_DEFAULT, // 0 - SC_AUTO, // 1 - SC_REGISTER, // 2 - SC_STATIC, // 3 - SC_EXTERN, // 4 - SC_TYPEDEF // 5 - }; - - struct Type { - TypeTag tag; - StorageClass storageClass; - tokenid_t id; // For function arguments, global vars, local vars, struct elements - tokenid_t structTag; // For structs the name of the struct - int length; // length of array, offset of struct element. -1 means struct is forward defined - int alignment; // for structs only - Type* pHead; // For a struct this is the prototype struct. - Type* pTail; - }; - - enum ExpressionType { - ET_RVALUE, - ET_LVALUE - }; - - struct ExpressionValue { - ExpressionValue() { - et = ET_RVALUE; - pType = NULL; - } - ExpressionType et; - Type* pType; - }; - - class ICodeBuf { - public: - virtual ~ICodeBuf() {} - virtual void init(int size) = 0; - virtual void setErrorSink(ErrorSink* pErrorSink) = 0; - virtual void o4(int n) = 0; - virtual void ob(int n) = 0; - virtual void* getBase() = 0; - virtual intptr_t getSize() = 0; - virtual intptr_t getPC() = 0; - // Call this before trying to modify code in the buffer. - virtual void flush() = 0; - }; - - class CodeBuf : public ICodeBuf { - char* ind; // Output code pointer - char* pProgramBase; - ErrorSink* mErrorSink; - int mSize; - bool mOverflowed; - - void release() { - if (pProgramBase != 0) { - munmap(pProgramBase, mSize); - pProgramBase = 0; - } - } - - bool check(int n) { - int newSize = ind - pProgramBase + n; - bool overflow = newSize > mSize; - if (overflow && !mOverflowed) { - mOverflowed = true; - if (mErrorSink) { - mErrorSink->error("Code too large: %d bytes", newSize); - } - } - return overflow; - } - - public: - CodeBuf() { - pProgramBase = 0; - ind = 0; - mErrorSink = 0; - mSize = 0; - mOverflowed = false; - } - - virtual ~CodeBuf() { - release(); - } - - virtual void init(int size) { - release(); - mSize = size; - pProgramBase = (char*) mmap(NULL, size, - PROT_EXEC | PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - ind = pProgramBase; - } - - virtual void setErrorSink(ErrorSink* pErrorSink) { - mErrorSink = pErrorSink; - } - - virtual void o4(int n) { - if(check(4)) { - return; - } - * (int*) ind = n; - ind += 4; - } - - /* - * Output a byte. Handles all values, 0..ff. - */ - virtual void ob(int n) { - if(check(1)) { - return; - } - *ind++ = n; - } - - virtual void* getBase() { - return (void*) pProgramBase; - } - - virtual intptr_t getSize() { - return ind - pProgramBase; - } - - virtual intptr_t getPC() { - return (intptr_t) ind; - } - - virtual void flush() {} - }; - - /** - * A code generator creates an in-memory program, generating the code on - * the fly. There is one code generator implementation for each supported - * architecture. - * - * The code generator implements the following abstract machine: - * R0 - the accumulator. - * FP - a frame pointer for accessing function arguments and local - * variables. - * SP - a stack pointer for storing intermediate results while evaluating - * expressions. The stack pointer grows downwards. - * - * The function calling convention is that all arguments are placed on the - * stack such that the first argument has the lowest address. - * After the call, the result is in R0. The caller is responsible for - * removing the arguments from the stack. - * The R0 register is not saved across function calls. The - * FP and SP registers are saved. - */ - - class CodeGenerator { - public: - CodeGenerator() { - mErrorSink = 0; - pCodeBuf = 0; - pushType(); - } - virtual ~CodeGenerator() {} - - virtual void init(ICodeBuf* pCodeBuf) { - this->pCodeBuf = pCodeBuf; - pCodeBuf->setErrorSink(mErrorSink); - } - - virtual void setErrorSink(ErrorSink* pErrorSink) { - mErrorSink = pErrorSink; - if (pCodeBuf) { - pCodeBuf->setErrorSink(mErrorSink); - } - } - - /* Give the code generator some utility types so it can - * use its own types as needed for the results of some - * operations like gcmp. - */ - - void setTypes(Type* pInt) { - mkpInt = pInt; - } - - /* Emit a function prolog. - * pDecl is the function declaration, which gives the arguments. - * Save the old value of the FP. - * Set the new value of the FP. - * Convert from the native platform calling convention to - * our stack-based calling convention. This may require - * pushing arguments from registers to the stack. - * Allocate "N" bytes of stack space. N isn't known yet, so - * just emit the instructions for adjusting the stack, and return - * the address to patch up. The patching will be done in - * functionExit(). - * returns address to patch with local variable size. - */ - virtual int functionEntry(Type* pDecl) = 0; - - /* Emit a function epilog. - * Restore the old SP and FP register values. - * Return to the calling function. - * argCount - the number of arguments to the function. - * localVariableAddress - returned from functionEntry() - * localVariableSize - the size in bytes of the local variables. - */ - virtual void functionExit(Type* pDecl, int localVariableAddress, - int localVariableSize) = 0; - - /* load immediate value to R0 */ - virtual void li(int i) = 0; - - /* Load floating point value from global address. */ - virtual void loadFloat(int address, Type* pType) = 0; - - /* Add the struct offset in bytes to R0, change the type to pType */ - virtual void addStructOffsetR0(int offset, Type* pType) = 0; - - /* Jump to a target, and return the address of the word that - * holds the target data, in case it needs to be fixed up later. - */ - virtual int gjmp(int t) = 0; - - /* Test R0 and jump to a target if the test succeeds. - * l = 0: je, l == 1: jne - * Return the address of the word that holds the targed data, in - * case it needs to be fixed up later. - */ - virtual int gtst(bool l, int t) = 0; - - /* Compare TOS against R0, and store the boolean result in R0. - * Pops TOS. - * op specifies the comparison. - */ - virtual void gcmp(int op) = 0; - - /* Perform the arithmetic op specified by op. TOS is the - * left argument, R0 is the right argument. - * Pops TOS. - */ - virtual void genOp(int op) = 0; - - /* Compare 0 against R0, and store the boolean result in R0. - * op specifies the comparison. - */ - virtual void gUnaryCmp(int op) = 0; - - /* Perform the arithmetic op specified by op. 0 is the - * left argument, R0 is the right argument. - */ - virtual void genUnaryOp(int op) = 0; - - /* Push R0 onto the stack. (Also known as "dup" for duplicate.) - */ - virtual void pushR0() = 0; - - /* Turn R0, TOS into R0 TOS R0 */ - - virtual void over() = 0; - - /* Pop R0 from the stack. (Also known as "drop") - */ - virtual void popR0() = 0; - - /* Store R0 to the address stored in TOS. - * The TOS is popped. - */ - virtual void storeR0ToTOS() = 0; - - /* Load R0 from the address stored in R0. - */ - virtual void loadR0FromR0() = 0; - - /* Load the absolute address of a variable to R0. - * If ea <= LOCAL, then this is a local variable, or an - * argument, addressed relative to FP. - * else it is an absolute global address. - * - * et is ET_RVALUE for things like string constants, ET_LVALUE for - * variables. - */ - virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) = 0; - - /* Load the pc-relative address of a forward-referenced variable to R0. - * Return the address of the 4-byte constant so that it can be filled - * in later. - */ - virtual int leaForward(int ea, Type* pPointerType) = 0; - - /** - * Convert R0 to the given type. - */ - - void convertR0(Type* pType) { - convertR0Imp(pType, false); - } - - void castR0(Type* pType) { - convertR0Imp(pType, true); - } - - virtual void convertR0Imp(Type* pType, bool isCast) = 0; - - /* Emit code to adjust the stack for a function call. Return the - * label for the address of the instruction that adjusts the - * stack size. This will be passed as argument "a" to - * endFunctionCallArguments. - */ - virtual int beginFunctionCallArguments() = 0; - - /* Emit code to store R0 to the stack at byte offset l. - * Returns stack size of object (typically 4 or 8 bytes) - */ - virtual size_t storeR0ToArg(int l, Type* pArgType) = 0; - - /* Patch the function call preamble. - * a is the address returned from beginFunctionCallArguments - * l is the number of bytes the arguments took on the stack. - * Typically you would also emit code to convert the argument - * list into whatever the native function calling convention is. - * On ARM for example you would pop the first 5 arguments into - * R0..R4 - */ - virtual void endFunctionCallArguments(Type* pDecl, int a, int l) = 0; - - /* Emit a call to an unknown function. The argument "symbol" needs to - * be stored in the location where the address should go. It forms - * a chain. The address will be patched later. - * Return the address of the word that has to be patched. - */ - virtual int callForward(int symbol, Type* pFunc) = 0; - - /* Call a function pointer. L is the number of bytes the arguments - * take on the stack. The address of the function is stored at - * location SP + l. - */ - virtual void callIndirect(int l, Type* pFunc) = 0; - - /* Adjust SP after returning from a function call. l is the - * number of bytes of arguments stored on the stack. isIndirect - * is true if this was an indirect call. (In which case the - * address of the function is stored at location SP + l.) - */ - virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) = 0; - - /* Generate a symbol at the current PC. t is the head of a - * linked list of addresses to patch. - */ - virtual void gsym(int t) = 0; - - /* Resolve a forward reference function at the current PC. - * t is the head of a - * linked list of addresses to patch. - * (Like gsym, but using absolute address, not PC relative address.) - */ - virtual void resolveForward(int t) = 0; - - /* - * Do any cleanup work required at the end of a compile. - * For example, an instruction cache might need to be - * invalidated. - * Return non-zero if there is an error. - */ - virtual int finishCompile() = 0; - - /** - * Adjust relative branches by this amount. - */ - virtual int jumpOffset() = 0; - - /** - * Memory alignment (in bytes) for this type of data - */ - virtual size_t alignmentOf(Type* type) = 0; - - /** - * Array element alignment (in bytes) for this type of data. - */ - virtual size_t sizeOf(Type* type) = 0; - - virtual Type* getR0Type() { - return mExpressionStack.back().pType; - } - - virtual ExpressionType getR0ExpressionType() { - return mExpressionStack.back().et; - } - - virtual void setR0ExpressionType(ExpressionType et) { - mExpressionStack.back().et = et; - } - - virtual size_t getExpressionStackDepth() { - return mExpressionStack.size(); - } - - virtual void forceR0RVal() { - if (getR0ExpressionType() == ET_LVALUE) { - loadR0FromR0(); - } - } - - protected: - /* - * Output a byte. Handles all values, 0..ff. - */ - void ob(int n) { - pCodeBuf->ob(n); - } - - void o4(int data) { - pCodeBuf->o4(data); - } - - intptr_t getBase() { - return (intptr_t) pCodeBuf->getBase(); - } - - intptr_t getPC() { - return pCodeBuf->getPC(); - } - - intptr_t getSize() { - return pCodeBuf->getSize(); - } - - void flush() { - pCodeBuf->flush(); - } - - void error(const char* fmt,...) { - va_list ap; - va_start(ap, fmt); - mErrorSink->verror(fmt, ap); - va_end(ap); - } - - void assertImpl(bool test, int line) { - if (!test) { - error("code generator assertion failed at line %s:%d.", __FILE__, line); - LOGD("code generator assertion failed at line %s:%d.", __FILE__, line); - * (char*) 0 = 0; - } - } - - void setR0Type(Type* pType) { - assert(pType != NULL); - mExpressionStack.back().pType = pType; - mExpressionStack.back().et = ET_RVALUE; - } - - void setR0Type(Type* pType, ExpressionType et) { - assert(pType != NULL); - mExpressionStack.back().pType = pType; - mExpressionStack.back().et = et; - } - - Type* getTOSType() { - return mExpressionStack[mExpressionStack.size()-2].pType; - } - - void pushType() { - if (mExpressionStack.size()) { - mExpressionStack.push_back(mExpressionStack.back()); - } else { - mExpressionStack.push_back(ExpressionValue()); - } - - } - - void overType() { - size_t size = mExpressionStack.size(); - if (size >= 2) { - mExpressionStack.push_back(mExpressionStack.back()); - mExpressionStack[size-1] = mExpressionStack[size-2]; - mExpressionStack[size-2] = mExpressionStack[size]; - } - } - - void popType() { - mExpressionStack.pop_back(); - } - - bool bitsSame(Type* pA, Type* pB) { - return collapseType(pA->tag) == collapseType(pB->tag); - } - - TypeTag collapseType(TypeTag tag) { - static const TypeTag collapsedTag[] = { - TY_INT, - TY_INT, - TY_INT, - TY_VOID, - TY_FLOAT, - TY_DOUBLE, - TY_INT, - TY_INT, - TY_VOID, - TY_VOID, - TY_VOID - }; - return collapsedTag[tag]; - } - - TypeTag collapseTypeR0() { - return collapseType(getR0Type()->tag); - } - - static bool isFloatType(Type* pType) { - return isFloatTag(pType->tag); - } - - static bool isFloatTag(TypeTag tag) { - return tag == TY_FLOAT || tag == TY_DOUBLE; - } - - static bool isPointerType(Type* pType) { - return isPointerTag(pType->tag); - } - - static bool isPointerTag(TypeTag tag) { - return tag == TY_POINTER || tag == TY_ARRAY; - } - - Type* getPointerArithmeticResultType(Type* a, Type* b) { - TypeTag aTag = a->tag; - TypeTag bTag = b->tag; - if (aTag == TY_POINTER) { - return a; - } - if (bTag == TY_POINTER) { - return b; - } - if (aTag == TY_ARRAY) { - return a->pTail; - } - if (bTag == TY_ARRAY) { - return b->pTail; - } - return NULL; - } - Type* mkpInt; - - private: - Vector<ExpressionValue> mExpressionStack; - ICodeBuf* pCodeBuf; - ErrorSink* mErrorSink; - }; - -#ifdef PROVIDE_ARM_CODEGEN - - static size_t rotateRight(size_t n, size_t rotate) { - return (n >> rotate) | (n << (32 - rotate)); - } - - static size_t rotateLeft(size_t n, size_t rotate) { - return (n << rotate) | (n >> (32 - rotate)); - } - - static bool encode12BitImmediate(size_t immediate, size_t* pResult) { - for(size_t i = 0; i < 16; i++) { - size_t rotate = i * 2; - size_t mask = rotateRight(0xff, rotate); - if ((immediate | mask) == mask) { - size_t bits8 = rotateLeft(immediate, rotate); - // assert(bits8 <= 0xff); - *pResult = (i << 8) | bits8; - return true; - } - } - return false; - } - - static size_t decode12BitImmediate(size_t immediate) { - size_t data = immediate & 0xff; - size_t rotate = 2 * ((immediate >> 8) & 0xf); - return rotateRight(data, rotate); - } - - static bool isPowerOfTwo(size_t n) { - return (n != 0) & ((n & (n-1)) == 0); - } - - static size_t log2(size_t n) { - int result = 0; - while (n >>= 1) { - result++; - } - return result; - } - - class ARMCodeBuf : public ICodeBuf { - ICodeBuf* mpBase; - ErrorSink* mErrorSink; - - class CircularQueue { - static const int SIZE = 16; // Must be power of 2 - static const int MASK = SIZE-1; - unsigned int mBuf[SIZE]; - int mHead; - int mCount; - - public: - CircularQueue() { - mHead = 0; - mCount = 0; - } - - void pushBack(unsigned int data) { - mBuf[(mHead + mCount) & MASK] = data; - mCount += 1; - } - - unsigned int popFront() { - unsigned int result = mBuf[mHead]; - mHead = (mHead + 1) & MASK; - mCount -= 1; - return result; - } - - void popBack(int n) { - mCount -= n; - } - - inline int count() { - return mCount; - } - - bool empty() { - return mCount == 0; - } - - bool full() { - return mCount == SIZE; - } - - // The valid indexes are 1 - count() to 0 - unsigned int operator[](int i) { - return mBuf[(mHead + mCount + i) & MASK]; - } - }; - - CircularQueue mQ; - - void error(const char* fmt,...) { - va_list ap; - va_start(ap, fmt); - mErrorSink->verror(fmt, ap); - va_end(ap); - } - - void flush() { - while (!mQ.empty()) { - mpBase->o4(mQ.popFront()); - } - mpBase->flush(); - } - - public: - ARMCodeBuf(ICodeBuf* pBase) { - mpBase = pBase; - } - - virtual ~ARMCodeBuf() { - delete mpBase; - } - - void init(int size) { - mpBase->init(size); - } - - void setErrorSink(ErrorSink* pErrorSink) { - mErrorSink = pErrorSink; - mpBase->setErrorSink(pErrorSink); - } - - void o4(int n) { - if (mQ.full()) { - mpBase->o4(mQ.popFront()); - } - mQ.pushBack(n); - -#ifndef DISABLE_ARM_PEEPHOLE - // Peephole check - bool didPeep; - do { - static const unsigned int opMask = 0x01e00000; - static const unsigned int immediateMask = 0x00000fff; - static const unsigned int BMask = 0x00400000; - didPeep = false; - if (mQ.count() >= 4) { - - // Operand by a small constant - // push;mov #imm;pop;op ==> op #imm - - if (mQ[-4] == 0xe92d0001 && // stmfd r13!, {r0} - (mQ[-3] & ~immediateMask) == 0xe3a00000 && // mov r0, #X - mQ[-2] == 0xe8bd0002 && // ldmea r13!, {r1} - (mQ[-1] & ~opMask) == (0xe0810000 & ~opMask)) { // OP r0, r1, r0 - unsigned int movConst = mQ[-3]; - unsigned int op = mQ[-1]; - unsigned int combined = 0xe2000000 | (op & opMask) | (movConst & immediateMask); - // fprintf(stderr, "op %x movConst %x combined %x\n", op, movConst, combined); - if (! (combined == 0xe2800000 || combined == 0xe2400000)) { // add/sub #0 - mQ.popBack(4); - mQ.pushBack(combined); - didPeep = true; - } else { - mQ.popBack(4); - didPeep = true; - } - } - } - - // Load local variable - // sub r0,r11,#imm;ldr/ldrb r0,[r0] ==> ldr/ldrb r0, [r11,#-imm] - if (mQ.count() >= 2) { - if ((mQ[-2] & ~immediateMask) == 0xe24b0000) { // sub r0,r11,#imm - const unsigned int encodedImmediate = mQ[-2] & immediateMask; - const unsigned int ld = mQ[-1]; - if ((ld & ~BMask) == 0xe5900000) { // ldr{b} r0, [r0] - unsigned int combined = encodedImmediate | (0xE51B0000 | (ld & BMask)); // ldr r0, [r11, #-0] - mQ.popBack(2); - mQ.pushBack(combined); - didPeep = true; - } else if (ld == 0xedd07a00) { // ldcl p10, c7, [r0, #0x000] - unsigned int decodedImmediate = decode12BitImmediate(encodedImmediate); - if (decodedImmediate <= 1020 && ((decodedImmediate & 3) == 0)) { - unsigned int combined = (decodedImmediate >> 2) | 0xed5b7a00; // ldcl p10, c7, [r11, #-0] - mQ.popBack(2); - mQ.pushBack(combined); - didPeep = true; - } - } - } - } - - // Constant array lookup - - if (mQ.count() >= 6 && - mQ[-6] == 0xe92d0001 && // stmfd r13!, {r0} - (mQ[-5] & ~immediateMask)== 0xe3a00000 && // mov r0, #0x00000001 - mQ[-4] == 0xe8bd0002 && // ldmea r13!, {r1} - (mQ[-3] & ~immediateMask)== 0xe3a02000 && // mov r2, #0x00000004 - mQ[-2] == 0xe0000092 && // mul r0, r2, r0 - mQ[-1] == 0xe0810000) { // add r0, r1, r0 - unsigned int mov1 = mQ[-5]; - unsigned int mov2 = mQ[-3]; - unsigned int const1 = decode12BitImmediate(mov1); - unsigned int const2 = decode12BitImmediate(mov2); - unsigned int comboConst = const1 * const2; - size_t immediate = 0; - if (encode12BitImmediate(comboConst, &immediate)) { - mQ.popBack(6); - unsigned int add = immediate | 0xE2800000; // add r0, r0, #n - if (comboConst) { - mQ.pushBack(add); - } - didPeep = true; - } - } - - // Pointer arithmetic with a stride that is a power of two - - if (mQ.count() >= 3 && - (mQ[-3] & ~ immediateMask) == 0xe3a02000 && // mov r2, #stride - mQ[-2] == 0xe0000092 && // mul r0, r2, r0 - mQ[-1] == 0xe0810000) { // add r0, r1, r0 - int stride = decode12BitImmediate(mQ[-3]); - if (isPowerOfTwo(stride)) { - mQ.popBack(3); - unsigned int add = 0xe0810000 | (log2(stride) << 7); // add r0, r1, r0, LSL #log2(stride) - mQ.pushBack(add); - didPeep = true; - } - } - - } while (didPeep); -#endif - } - - void ob(int n) { - error("ob() not supported."); - } - - void* getBase() { - flush(); - return mpBase->getBase(); - } - - intptr_t getSize() { - flush(); - return mpBase->getSize(); - } - - intptr_t getPC() { - flush(); - return mpBase->getPC(); - } - }; - - class ARMCodeGenerator : public CodeGenerator { - public: - ARMCodeGenerator() { -#ifdef ARM_USE_VFP - // LOGD("Using ARM VFP hardware floating point."); -#else - // LOGD("Using ARM soft floating point."); -#endif - } - - virtual ~ARMCodeGenerator() {} - - /* returns address to patch with local variable size - */ - virtual int functionEntry(Type* pDecl) { - mStackUse = 0; - // sp -> arg4 arg5 ... - // Push our register-based arguments back on the stack - int regArgCount = calcRegArgCount(pDecl); - if (regArgCount > 0) { - mStackUse += regArgCount * 4; - o4(0xE92D0000 | ((1 << regArgCount) - 1)); // stmfd sp!, {} - } - // sp -> arg0 arg1 ... - o4(0xE92D4800); // stmfd sp!, {fp, lr} - mStackUse += 2 * 4; - // sp, fp -> oldfp, retadr, arg0 arg1 .... - o4(0xE1A0B00D); // mov fp, sp - LOG_STACK("functionEntry: %d\n", mStackUse); - int pc = getPC(); - o4(0xE24DD000); // sub sp, sp, # <local variables> - // We don't know how many local variables we are going to use, - // but we will round the allocation up to a multiple of - // STACK_ALIGNMENT, so it won't affect the stack alignment. - return pc; - } - - virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) { - // Round local variable size up to a multiple of stack alignment - localVariableSize = ((localVariableSize + STACK_ALIGNMENT - 1) / - STACK_ALIGNMENT) * STACK_ALIGNMENT; - // Patch local variable allocation code: - if (localVariableSize < 0 || localVariableSize > 255) { - error("localVariables out of range: %d", localVariableSize); - } - *(char*) (localVariableAddress) = localVariableSize; - -#ifdef ARM_USE_VFP - { - Type* pReturnType = pDecl->pHead; - switch(pReturnType->tag) { - case TY_FLOAT: - o4(0xEE170A90); // fmrs r0, s15 - break; - case TY_DOUBLE: - o4(0xEC510B17); // fmrrd r0, r1, d7 - break; - default: - break; - } - } -#endif - - // sp -> locals .... fp -> oldfp, retadr, arg0, arg1, ... - o4(0xE1A0E00B); // mov lr, fp - o4(0xE59BB000); // ldr fp, [fp] - o4(0xE28ED004); // add sp, lr, #4 - // sp -> retadr, arg0, ... - o4(0xE8BD4000); // ldmfd sp!, {lr} - // sp -> arg0 .... - - // We store the PC into the lr so we can adjust the sp before - // returning. We need to pull off the registers we pushed - // earlier. We don't need to actually store them anywhere, - // just adjust the stack. - int regArgCount = calcRegArgCount(pDecl); - if (regArgCount) { - o4(0xE28DD000 | (regArgCount << 2)); // add sp, sp, #argCount << 2 - } - o4(0xE12FFF1E); // bx lr - } - - /* load immediate value */ - virtual void li(int t) { - liReg(t, 0); - setR0Type(mkpInt); - } - - virtual void loadFloat(int address, Type* pType) { - setR0Type(pType); - // Global, absolute address - o4(0xE59F0000); // ldr r0, .L1 - o4(0xEA000000); // b .L99 - o4(address); // .L1: .word ea - // .L99: - - switch (pType->tag) { - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEDD07A00); // flds s15, [r0] -#else - o4(0xE5900000); // ldr r0, [r0] -#endif - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xED907B00); // fldd d7, [r0] -#else - o4(0xE1C000D0); // ldrd r0, [r0] -#endif - break; - default: - assert(false); - break; - } - } - - - virtual void addStructOffsetR0(int offset, Type* pType) { - if (offset) { - size_t immediate = 0; - if (encode12BitImmediate(offset, &immediate)) { - o4(0xE2800000 | immediate); // add r0, r0, #offset - } else { - error("structure offset out of range: %d", offset); - } - } - setR0Type(pType, ET_LVALUE); - } - - virtual int gjmp(int t) { - int pc = getPC(); - o4(0xEA000000 | encodeAddress(t)); // b .L33 - return pc; - } - - /* l = 0: je, l == 1: jne */ - virtual int gtst(bool l, int t) { - Type* pR0Type = getR0Type(); - TypeTag tagR0 = pR0Type->tag; - switch(tagR0) { - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEEF57A40); // fcmpzs s15 - o4(0xEEF1FA10); // fmstat -#else - callRuntime((void*) runtime_is_non_zero_f); - o4(0xE3500000); // cmp r0,#0 -#endif - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xEEB57B40); // fcmpzd d7 - o4(0xEEF1FA10); // fmstat -#else - callRuntime((void*) runtime_is_non_zero_d); - o4(0xE3500000); // cmp r0,#0 -#endif - break; - default: - o4(0xE3500000); // cmp r0,#0 - break; - } - int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq - int pc = getPC(); - o4(branch | encodeAddress(t)); - return pc; - } - - virtual void gcmp(int op) { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = collapseType(pR0Type->tag); - TypeTag tagTOS = collapseType(pTOSType->tag); - if (tagR0 == TY_INT && tagTOS == TY_INT) { - setupIntPtrArgs(); - o4(0xE1510000); // cmp r1, r1 - switch(op) { - case OP_EQUALS: - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 - break; - case OP_NOT_EQUALS: - o4(0x03A00000); // moveq r0,#0 - o4(0x13A00001); // movne r0,#1 - break; - case OP_LESS_EQUAL: - o4(0xD3A00001); // movle r0,#1 - o4(0xC3A00000); // movgt r0,#0 - break; - case OP_GREATER: - o4(0xD3A00000); // movle r0,#0 - o4(0xC3A00001); // movgt r0,#1 - break; - case OP_GREATER_EQUAL: - o4(0xA3A00001); // movge r0,#1 - o4(0xB3A00000); // movlt r0,#0 - break; - case OP_LESS: - o4(0xA3A00000); // movge r0,#0 - o4(0xB3A00001); // movlt r0,#1 - break; - default: - error("Unknown comparison op %d", op); - break; - } - } else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) { - setupDoubleArgs(); -#ifdef ARM_USE_VFP - o4(0xEEB46BC7); // fcmped d6, d7 - o4(0xEEF1FA10); // fmstat - switch(op) { - case OP_EQUALS: - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 - break; - case OP_NOT_EQUALS: - o4(0x03A00000); // moveq r0,#0 - o4(0x13A00001); // movne r0,#1 - break; - case OP_LESS_EQUAL: - o4(0xD3A00001); // movle r0,#1 - o4(0xC3A00000); // movgt r0,#0 - break; - case OP_GREATER: - o4(0xD3A00000); // movle r0,#0 - o4(0xC3A00001); // movgt r0,#1 - break; - case OP_GREATER_EQUAL: - o4(0xA3A00001); // movge r0,#1 - o4(0xB3A00000); // movlt r0,#0 - break; - case OP_LESS: - o4(0xA3A00000); // movge r0,#0 - o4(0xB3A00001); // movlt r0,#1 - break; - default: - error("Unknown comparison op %d", op); - break; - } -#else - switch(op) { - case OP_EQUALS: - callRuntime((void*) runtime_cmp_eq_dd); - break; - case OP_NOT_EQUALS: - callRuntime((void*) runtime_cmp_ne_dd); - break; - case OP_LESS_EQUAL: - callRuntime((void*) runtime_cmp_le_dd); - break; - case OP_GREATER: - callRuntime((void*) runtime_cmp_gt_dd); - break; - case OP_GREATER_EQUAL: - callRuntime((void*) runtime_cmp_ge_dd); - break; - case OP_LESS: - callRuntime((void*) runtime_cmp_lt_dd); - break; - default: - error("Unknown comparison op %d", op); - break; - } -#endif - } else { - setupFloatArgs(); -#ifdef ARM_USE_VFP - o4(0xEEB47AE7); // fcmpes s14, s15 - o4(0xEEF1FA10); // fmstat - switch(op) { - case OP_EQUALS: - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 - break; - case OP_NOT_EQUALS: - o4(0x03A00000); // moveq r0,#0 - o4(0x13A00001); // movne r0,#1 - break; - case OP_LESS_EQUAL: - o4(0xD3A00001); // movle r0,#1 - o4(0xC3A00000); // movgt r0,#0 - break; - case OP_GREATER: - o4(0xD3A00000); // movle r0,#0 - o4(0xC3A00001); // movgt r0,#1 - break; - case OP_GREATER_EQUAL: - o4(0xA3A00001); // movge r0,#1 - o4(0xB3A00000); // movlt r0,#0 - break; - case OP_LESS: - o4(0xA3A00000); // movge r0,#0 - o4(0xB3A00001); // movlt r0,#1 - break; - default: - error("Unknown comparison op %d", op); - break; - } -#else - switch(op) { - case OP_EQUALS: - callRuntime((void*) runtime_cmp_eq_ff); - break; - case OP_NOT_EQUALS: - callRuntime((void*) runtime_cmp_ne_ff); - break; - case OP_LESS_EQUAL: - callRuntime((void*) runtime_cmp_le_ff); - break; - case OP_GREATER: - callRuntime((void*) runtime_cmp_gt_ff); - break; - case OP_GREATER_EQUAL: - callRuntime((void*) runtime_cmp_ge_ff); - break; - case OP_LESS: - callRuntime((void*) runtime_cmp_lt_ff); - break; - default: - error("Unknown comparison op %d", op); - break; - } -#endif - } - setR0Type(mkpInt); - } - - virtual void genOp(int op) { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = pR0Type->tag; - TypeTag tagTOS = pTOSType->tag; - bool isFloatR0 = isFloatTag(tagR0); - bool isFloatTOS = isFloatTag(tagTOS); - if (!isFloatR0 && !isFloatTOS) { - setupIntPtrArgs(); - bool isPtrR0 = isPointerTag(tagR0); - bool isPtrTOS = isPointerTag(tagTOS); - if (isPtrR0 || isPtrTOS) { - if (isPtrR0 && isPtrTOS) { - if (op != OP_MINUS) { - error("Unsupported pointer-pointer operation %d.", op); - } - if (! typeEqual(pR0Type, pTOSType)) { - error("Incompatible pointer types for subtraction."); - } - o4(0xE0410000); // sub r0,r1,r0 - setR0Type(mkpInt); - int size = sizeOf(pR0Type->pHead); - if (size != 1) { - pushR0(); - li(size); - // TODO: Optimize for power-of-two. - genOp(OP_DIV); - } - } else { - if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { - error("Unsupported pointer-scalar operation %d", op); - } - Type* pPtrType = getPointerArithmeticResultType( - pR0Type, pTOSType); - int size = sizeOf(pPtrType->pHead); - if (size != 1) { - // TODO: Optimize for power-of-two. - liReg(size, 2); - if (isPtrR0) { - o4(0x0E0010192); // mul r1,r2,r1 - } else { - o4(0x0E0000092); // mul r0,r2,r0 - } - } - switch(op) { - case OP_PLUS: - o4(0xE0810000); // add r0,r1,r0 - break; - case OP_MINUS: - o4(0xE0410000); // sub r0,r1,r0 - break; - } - setR0Type(pPtrType); - } - } else { - switch(op) { - case OP_MUL: - o4(0x0E0000091); // mul r0,r1,r0 - break; - case OP_DIV: - callRuntime((void*) runtime_DIV); - break; - case OP_MOD: - callRuntime((void*) runtime_MOD); - break; - case OP_PLUS: - o4(0xE0810000); // add r0,r1,r0 - break; - case OP_MINUS: - o4(0xE0410000); // sub r0,r1,r0 - break; - case OP_SHIFT_LEFT: - o4(0xE1A00011); // lsl r0,r1,r0 - break; - case OP_SHIFT_RIGHT: - o4(0xE1A00051); // asr r0,r1,r0 - break; - case OP_BIT_AND: - o4(0xE0010000); // and r0,r1,r0 - break; - case OP_BIT_XOR: - o4(0xE0210000); // eor r0,r1,r0 - break; - case OP_BIT_OR: - o4(0xE1810000); // orr r0,r1,r0 - break; - case OP_BIT_NOT: - o4(0xE1E00000); // mvn r0, r0 - break; - default: - error("Unimplemented op %d\n", op); - break; - } - } - } else { - Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; - if (pResultType->tag == TY_DOUBLE) { - setupDoubleArgs(); - - switch(op) { - case OP_MUL: -#ifdef ARM_USE_VFP - o4(0xEE267B07); // fmuld d7, d6, d7 -#else - callRuntime((void*) runtime_op_mul_dd); -#endif - break; - case OP_DIV: -#ifdef ARM_USE_VFP - o4(0xEE867B07); // fdivd d7, d6, d7 -#else - callRuntime((void*) runtime_op_div_dd); -#endif - break; - case OP_PLUS: -#ifdef ARM_USE_VFP - o4(0xEE367B07); // faddd d7, d6, d7 -#else - callRuntime((void*) runtime_op_add_dd); -#endif - break; - case OP_MINUS: -#ifdef ARM_USE_VFP - o4(0xEE367B47); // fsubd d7, d6, d7 -#else - callRuntime((void*) runtime_op_sub_dd); -#endif - break; - default: - error("Unsupported binary floating operation %d\n", op); - break; - } - } else { - setupFloatArgs(); - switch(op) { - case OP_MUL: -#ifdef ARM_USE_VFP - o4(0xEE677A27); // fmuls s15, s14, s15 -#else - callRuntime((void*) runtime_op_mul_ff); -#endif - break; - case OP_DIV: -#ifdef ARM_USE_VFP - o4(0xEEC77A27); // fdivs s15, s14, s15 -#else - callRuntime((void*) runtime_op_div_ff); -#endif - break; - case OP_PLUS: -#ifdef ARM_USE_VFP - o4(0xEE777A27); // fadds s15, s14, s15 -#else - callRuntime((void*) runtime_op_add_ff); -#endif - break; - case OP_MINUS: -#ifdef ARM_USE_VFP - o4(0xEE777A67); // fsubs s15, s14, s15 -#else - callRuntime((void*) runtime_op_sub_ff); -#endif - break; - default: - error("Unsupported binary floating operation %d\n", op); - break; - } - } - setR0Type(pResultType); - } - } - - virtual void gUnaryCmp(int op) { - if (op != OP_LOGICAL_NOT) { - error("Unknown unary cmp %d", op); - } else { - Type* pR0Type = getR0Type(); - TypeTag tag = collapseType(pR0Type->tag); - switch(tag) { - case TY_INT: - o4(0xE3A01000); // mov r1, #0 - o4(0xE1510000); // cmp r1, r0 - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 - break; - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEEF57A40); // fcmpzs s15 - o4(0xEEF1FA10); // fmstat - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 -#else - callRuntime((void*) runtime_is_zero_f); -#endif - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xEEB57B40); // fcmpzd d7 - o4(0xEEF1FA10); // fmstat - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 -#else - callRuntime((void*) runtime_is_zero_d); -#endif - break; - default: - error("gUnaryCmp unsupported type"); - break; - } - } - setR0Type(mkpInt); - } - - virtual void genUnaryOp(int op) { - Type* pR0Type = getR0Type(); - TypeTag tag = collapseType(pR0Type->tag); - switch(tag) { - case TY_INT: - switch(op) { - case OP_MINUS: - o4(0xE3A01000); // mov r1, #0 - o4(0xE0410000); // sub r0,r1,r0 - break; - case OP_BIT_NOT: - o4(0xE1E00000); // mvn r0, r0 - break; - default: - error("Unknown unary op %d\n", op); - break; - } - break; - case TY_FLOAT: - case TY_DOUBLE: - switch (op) { - case OP_MINUS: - if (tag == TY_FLOAT) { -#ifdef ARM_USE_VFP - o4(0xEEF17A67); // fnegs s15, s15 -#else - callRuntime((void*) runtime_op_neg_f); -#endif - } else { -#ifdef ARM_USE_VFP - o4(0xEEB17B47); // fnegd d7, d7 -#else - callRuntime((void*) runtime_op_neg_d); -#endif - } - break; - case OP_BIT_NOT: - error("Can't apply '~' operator to a float or double."); - break; - default: - error("Unknown unary op %d\n", op); - break; - } - break; - default: - error("genUnaryOp unsupported type"); - break; - } - } - - virtual void pushR0() { - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - -#ifdef ARM_USE_VFP - switch (r0ct ) { - case TY_FLOAT: - o4(0xED6D7A01); // fstmfds sp!,{s15} - mStackUse += 4; - break; - case TY_DOUBLE: - o4(0xED2D7B02); // fstmfdd sp!,{d7} - mStackUse += 8; - break; - default: - o4(0xE92D0001); // stmfd sp!,{r0} - mStackUse += 4; - } -#else - - if (r0ct != TY_DOUBLE) { - o4(0xE92D0001); // stmfd sp!,{r0} - mStackUse += 4; - } else { - o4(0xE92D0003); // stmfd sp!,{r0,r1} - mStackUse += 8; - } -#endif - pushType(); - LOG_STACK("pushR0: %d\n", mStackUse); - } - - virtual void over() { - // We know it's only used for int-ptr ops (++/--) - - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - - Type* pTOSType = getTOSType(); - TypeTag tosct = collapseType(pTOSType->tag); - - assert (r0ct == TY_INT && tosct == TY_INT); - - o4(0xE8BD0002); // ldmfd sp!,{r1} - o4(0xE92D0001); // stmfd sp!,{r0} - o4(0xE92D0002); // stmfd sp!,{r1} - overType(); - mStackUse += 4; - } - - virtual void popR0() { - Type* pTOSType = getTOSType(); - TypeTag tosct = collapseType(pTOSType->tag); -#ifdef ARM_USE_VFP - if (tosct == TY_FLOAT || tosct == TY_DOUBLE) { - error("Unsupported popR0 float/double"); - } -#endif - switch (tosct){ - case TY_INT: - case TY_FLOAT: - o4(0xE8BD0001); // ldmfd sp!,{r0} - mStackUse -= 4; - break; - case TY_DOUBLE: - o4(0xE8BD0003); // ldmfd sp!,{r0, r1} // Restore R0 - mStackUse -= 8; - break; - default: - error("Can't pop this type."); - break; - } - popType(); - LOG_STACK("popR0: %d\n", mStackUse); - } - - virtual void storeR0ToTOS() { - Type* pPointerType = getTOSType(); - assert(pPointerType->tag == TY_POINTER); - Type* pDestType = pPointerType->pHead; - convertR0(pDestType); - o4(0xE8BD0004); // ldmfd sp!,{r2} - popType(); - mStackUse -= 4; - switch (pDestType->tag) { - case TY_POINTER: - case TY_INT: - o4(0xE5820000); // str r0, [r2] - break; - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEDC27A00); // fsts s15, [r2, #0] -#else - o4(0xE5820000); // str r0, [r2] -#endif - break; - case TY_SHORT: - o4(0xE1C200B0); // strh r0, [r2] - break; - case TY_CHAR: - o4(0xE5C20000); // strb r0, [r2] - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xED827B00); // fstd d7, [r2, #0] -#else - o4(0xE1C200F0); // strd r0, [r2] -#endif - break; - case TY_STRUCT: - { - int size = sizeOf(pDestType); - if (size > 0) { - liReg(size, 1); - callRuntime((void*) runtime_structCopy); - } - } - break; - default: - error("storeR0ToTOS: unimplemented type %d", - pDestType->tag); - break; - } - setR0Type(pDestType); - } - - virtual void loadR0FromR0() { - Type* pPointerType = getR0Type(); - assert(pPointerType->tag == TY_POINTER); - Type* pNewType = pPointerType->pHead; - TypeTag tag = pNewType->tag; - switch (tag) { - case TY_POINTER: - case TY_INT: - o4(0xE5900000); // ldr r0, [r0] - break; - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEDD07A00); // flds s15, [r0, #0] -#else - o4(0xE5900000); // ldr r0, [r0] -#endif - break; - case TY_SHORT: - o4(0xE1D000F0); // ldrsh r0, [r0] - break; - case TY_CHAR: - o4(0xE5D00000); // ldrb r0, [r0] - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xED907B00); // fldd d7, [r0, #0] -#else - o4(0xE1C000D0); // ldrd r0, [r0] -#endif - break; - case TY_ARRAY: - pNewType = pNewType->pTail; - break; - case TY_STRUCT: - break; - default: - error("loadR0FromR0: unimplemented type %d", tag); - break; - } - setR0Type(pNewType); - } - - virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) { - if (ea > -LOCAL && ea < LOCAL) { - // Local, fp relative - - size_t immediate = 0; - bool inRange = false; - if (ea < 0) { - inRange = encode12BitImmediate(-ea, &immediate); - o4(0xE24B0000 | immediate); // sub r0, fp, #ea - } else { - inRange = encode12BitImmediate(ea, &immediate); - o4(0xE28B0000 | immediate); // add r0, fp, #ea - } - if (! inRange) { - error("Offset out of range: %08x", ea); - } - } else { - // Global, absolute. - o4(0xE59F0000); // ldr r0, .L1 - o4(0xEA000000); // b .L99 - o4(ea); // .L1: .word 0 - // .L99: - } - setR0Type(pPointerType, et); - } - - virtual int leaForward(int ea, Type* pPointerType) { - setR0Type(pPointerType); - int result = ea; - int pc = getPC(); - int offset = 0; - if (ea) { - offset = (pc - ea - 8) >> 2; - if ((offset & 0xffff) != offset) { - error("function forward reference out of bounds"); - } - } else { - offset = 0; - } - o4(0xE59F0000 | offset); // ldr r0, .L1 - - if (ea == 0) { - o4(0xEA000000); // b .L99 - result = getPC(); - o4(ea); // .L1: .word 0 - // .L99: - } - return result; - } - - virtual void convertR0Imp(Type* pType, bool isCast){ - Type* pR0Type = getR0Type(); - if (isPointerType(pType) && isPointerType(pR0Type)) { - Type* pA = pR0Type; - Type* pB = pType; - // Array decays to pointer - if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) { - pA = pA->pTail; - } - if (! (typeEqual(pA, pB) - || pB->pHead->tag == TY_VOID - || (pA->tag == TY_POINTER && pB->tag == TY_POINTER && isCast) - )) { - error("Incompatible pointer or array types"); - } - } else if (bitsSame(pType, pR0Type)) { - // do nothing special - } else { - TypeTag r0Tag = collapseType(pR0Type->tag); - TypeTag destTag = collapseType(pType->tag); - if (r0Tag == TY_INT) { - if (destTag == TY_FLOAT) { -#ifdef ARM_USE_VFP - o4(0xEE070A90); // fmsr s15, r0 - o4(0xEEF87AE7); // fsitos s15, s15 - -#else - callRuntime((void*) runtime_int_to_float); -#endif - } else { - assert(destTag == TY_DOUBLE); -#ifdef ARM_USE_VFP - o4(0xEE070A90); // fmsr s15, r0 - o4(0xEEB87BE7); // fsitod d7, s15 - -#else - callRuntime((void*) runtime_int_to_double); -#endif - } - } else if (r0Tag == TY_FLOAT) { - if (destTag == TY_INT) { -#ifdef ARM_USE_VFP - o4(0xEEFD7AE7); // ftosizs s15, s15 - o4(0xEE170A90); // fmrs r0, s15 -#else - callRuntime((void*) runtime_float_to_int); -#endif - } else { - assert(destTag == TY_DOUBLE); -#ifdef ARM_USE_VFP - o4(0xEEB77AE7); // fcvtds d7, s15 -#else - callRuntime((void*) runtime_float_to_double); -#endif - } - } else { - if (r0Tag == TY_DOUBLE) { - if (destTag == TY_INT) { -#ifdef ARM_USE_VFP - o4(0xEEFD7BC7); // ftosizd s15, d7 - o4(0xEE170A90); // fmrs r0, s15 -#else - callRuntime((void*) runtime_double_to_int); -#endif - } else { - if(destTag == TY_FLOAT) { -#ifdef ARM_USE_VFP - o4(0xEEF77BC7); // fcvtsd s15, d7 -#else - callRuntime((void*) runtime_double_to_float); -#endif - } else { - incompatibleTypes(pR0Type, pType); - } - } - } else { - incompatibleTypes(pR0Type, pType); - } - } - } - setR0Type(pType); - } - - virtual int beginFunctionCallArguments() { - int pc = getPC(); - o4(0xE24DDF00); // Placeholder sub sp, sp, #0 - return pc; - } - - virtual size_t storeR0ToArg(int l, Type* pArgType) { - convertR0(pArgType); - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); -#ifdef ARM_USE_VFP - switch(r0ct) { - case TY_INT: - if (l < 0 || l > 4096-4) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xE58D0000 | l); // str r0, [sp, #l] - return 4; - case TY_FLOAT: - if (l < 0 || l > 1020 || (l & 3)) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xEDCD7A00 | (l >> 2)); // fsts s15, [sp, #l] - return 4; - case TY_DOUBLE: { - // Align to 8 byte boundary - int l2 = (l + 7) & ~7; - if (l2 < 0 || l2 > 1020 || (l2 & 3)) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xED8D7B00 | (l2 >> 2)); // fstd d7, [sp, #l2] - return (l2 - l) + 8; - } - default: - assert(false); - return 0; - } -#else - switch(r0ct) { - case TY_INT: - case TY_FLOAT: - if (l < 0 || l > 4096-4) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xE58D0000 + l); // str r0, [sp, #l] - return 4; - case TY_DOUBLE: { - // Align to 8 byte boundary - int l2 = (l + 7) & ~7; - if (l2 < 0 || l2 > 4096-8) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xE58D0000 + l2); // str r0, [sp, #l] - o4(0xE58D1000 + l2 + 4); // str r1, [sp, #l+4] - return (l2 - l) + 8; - } - default: - assert(false); - return 0; - } -#endif - } - - virtual void endFunctionCallArguments(Type* pDecl, int a, int l) { - int argumentStackUse = l; - // Have to calculate register arg count from actual stack size, - // in order to properly handle ... functions. - int regArgCount = l >> 2; - if (regArgCount > 4) { - regArgCount = 4; - } - if (regArgCount > 0) { - argumentStackUse -= regArgCount * 4; - o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{} - } - mStackUse += argumentStackUse; - - // Align stack. - int missalignment = mStackUse - ((mStackUse / STACK_ALIGNMENT) - * STACK_ALIGNMENT); - mStackAlignmentAdjustment = 0; - if (missalignment > 0) { - mStackAlignmentAdjustment = STACK_ALIGNMENT - missalignment; - } - l += mStackAlignmentAdjustment; - - if (l < 0 || l > 0x3FC) { - error("L out of range for stack adjustment: 0x%08x", l); - } - flush(); - * (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2 - mStackUse += mStackAlignmentAdjustment; - LOG_STACK("endFunctionCallArguments mStackUse: %d, mStackAlignmentAdjustment %d\n", - mStackUse, mStackAlignmentAdjustment); - } - - virtual int callForward(int symbol, Type* pFunc) { - setR0Type(pFunc->pHead); - // Forward calls are always short (local) - int pc = getPC(); - o4(0xEB000000 | encodeAddress(symbol)); - return pc; - } - - virtual void callIndirect(int l, Type* pFunc) { - assert(pFunc->tag == TY_FUNC); - popType(); // Get rid of indirect fn pointer type - int argCount = l >> 2; - int poppedArgs = argCount > 4 ? 4 : argCount; - int adjustedL = l - (poppedArgs << 2) + mStackAlignmentAdjustment; - if (adjustedL < 0 || adjustedL > 4096-4) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xE59DC000 | (0xfff & adjustedL)); // ldr r12, [sp,#adjustedL] - o4(0xE12FFF3C); // blx r12 - Type* pReturnType = pFunc->pHead; - setR0Type(pReturnType); -#ifdef ARM_USE_VFP - switch(pReturnType->tag) { - case TY_FLOAT: - o4(0xEE070A90); // fmsr s15, r0 - break; - case TY_DOUBLE: - o4(0xEC410B17); // fmdrr d7, r0, r1 - break; - default: - break; - } -#endif - } - - virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) { - int argCount = l >> 2; - // Have to calculate register arg count from actual stack size, - // in order to properly handle ... functions. - int regArgCount = l >> 2; - if (regArgCount > 4) { - regArgCount = 4; - } - int stackArgs = argCount - regArgCount; - int stackUse = stackArgs + (isIndirect ? 1 : 0) - + (mStackAlignmentAdjustment >> 2); - if (stackUse) { - if (stackUse < 0 || stackUse > 255) { - error("L out of range for stack adjustment: 0x%08x", l); - } - o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2 - mStackUse -= stackUse * 4; - LOG_STACK("adjustStackAfterCall: %d\n", mStackUse); - } - } - - virtual int jumpOffset() { - return 8; - } - - /* output a symbol and patch all calls to it */ - virtual void gsym(int t) { - int n; - int base = getBase(); - int pc = getPC(); - while (t) { - int data = * (int*) t; - int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2); - if (decodedOffset == 0) { - n = 0; - } else { - n = base + decodedOffset; /* next value */ - } - *(int *) t = (data & ~BRANCH_REL_ADDRESS_MASK) - | encodeRelAddress(pc - t - 8); - t = n; - } - } - - /* output a symbol and patch all calls to it */ - virtual void resolveForward(int t) { - if (t) { - int pc = getPC(); - *(int *) t = pc; - } - } - - virtual int finishCompile() { -#if defined(__arm__) - const long base = long(getBase()); - const long curr = long(getPC()); - int err = cacheflush(base, curr, 0); - return err; -#else - return 0; -#endif - } - - /** - * alignment (in bytes) for this type of data - */ - virtual size_t alignmentOf(Type* pType){ - switch(pType->tag) { - case TY_CHAR: - return 1; - case TY_SHORT: - return 2; - case TY_DOUBLE: - return 8; - case TY_ARRAY: - return alignmentOf(pType->pHead); - case TY_STRUCT: - return pType->pHead->alignment & 0x7fffffff; - case TY_FUNC: - error("alignment of func not supported"); - return 1; - default: - return 4; - } - } - - /** - * Array element alignment (in bytes) for this type of data. - */ - virtual size_t sizeOf(Type* pType){ - switch(pType->tag) { - case TY_INT: - return 4; - case TY_SHORT: - return 2; - case TY_CHAR: - return 1; - case TY_FLOAT: - return 4; - case TY_DOUBLE: - return 8; - case TY_POINTER: - return 4; - case TY_ARRAY: - return pType->length * sizeOf(pType->pHead); - case TY_STRUCT: - return pType->pHead->length; - default: - error("Unsupported type %d", pType->tag); - return 0; - } - } - - private: - - static const int BRANCH_REL_ADDRESS_MASK = 0x00ffffff; - - /** Encode a relative address that might also be - * a label. - */ - int encodeAddress(int value) { - int base = getBase(); - if (value >= base && value <= getPC() ) { - // This is a label, encode it relative to the base. - value = value - base; - } - return encodeRelAddress(value); - } - - int encodeRelAddress(int value) { - return BRANCH_REL_ADDRESS_MASK & (value >> 2); - } - - int calcRegArgCount(Type* pDecl) { - int reg = 0; - Type* pArgs = pDecl->pTail; - while (pArgs && reg < 4) { - Type* pArg = pArgs->pHead; - if ( pArg->tag == TY_DOUBLE) { - int evenReg = (reg + 1) & ~1; - if (evenReg >= 4) { - break; - } - reg = evenReg + 2; - } else { - reg++; - } - pArgs = pArgs->pTail; - } - return reg; - } - - void setupIntPtrArgs() { - o4(0xE8BD0002); // ldmfd sp!,{r1} - mStackUse -= 4; - popType(); - } - - /* Pop TOS to R1 (use s14 if VFP) - * Make sure both R0 and TOS are floats. (Could be ints) - * We know that at least one of R0 and TOS is already a float - */ - void setupFloatArgs() { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = collapseType(pR0Type->tag); - TypeTag tagTOS = collapseType(pTOSType->tag); - if (tagR0 != TY_FLOAT) { - assert(tagR0 == TY_INT); -#ifdef ARM_USE_VFP - o4(0xEE070A90); // fmsr s15, r0 - o4(0xEEF87AE7); // fsitos s15, s15 -#else - callRuntime((void*) runtime_int_to_float); -#endif - } - if (tagTOS != TY_FLOAT) { - assert(tagTOS == TY_INT); - assert(tagR0 == TY_FLOAT); -#ifdef ARM_USE_VFP - o4(0xECBD7A01); // fldmfds sp!, {s14} - o4(0xEEB87AC7); // fsitos s14, s14 -#else - o4(0xE92D0001); // stmfd sp!,{r0} // push R0 - o4(0xE59D0004); // ldr r0, [sp, #4] - callRuntime((void*) runtime_int_to_float); - o4(0xE1A01000); // mov r1, r0 - o4(0xE8BD0001); // ldmfd sp!,{r0} // pop R0 - o4(0xE28DD004); // add sp, sp, #4 // Pop sp -#endif - } else { - // Pop TOS -#ifdef ARM_USE_VFP - o4(0xECBD7A01); // fldmfds sp!, {s14} - -#else - o4(0xE8BD0002); // ldmfd sp!,{r1} -#endif - } - mStackUse -= 4; - popType(); - } - - /* Pop TOS into R2..R3 (use D6 if VFP) - * Make sure both R0 and TOS are doubles. Could be floats or ints. - * We know that at least one of R0 and TOS are already a double. - */ - - void setupDoubleArgs() { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = collapseType(pR0Type->tag); - TypeTag tagTOS = collapseType(pTOSType->tag); - if (tagR0 != TY_DOUBLE) { - if (tagR0 == TY_INT) { -#ifdef ARM_USE_VFP - o4(0xEE070A90); // fmsr s15, r0 - o4(0xEEB87BE7); // fsitod d7, s15 - -#else - callRuntime((void*) runtime_int_to_double); -#endif - } else { - assert(tagR0 == TY_FLOAT); -#ifdef ARM_USE_VFP - o4(0xEEB77AE7); // fcvtds d7, s15 -#else - callRuntime((void*) runtime_float_to_double); -#endif - } - } - if (tagTOS != TY_DOUBLE) { -#ifdef ARM_USE_VFP - if (tagTOS == TY_INT) { - o4(0xECFD6A01); // fldmfds sp!,{s13} - o4(0xEEB86BE6); // fsitod d6, s13 - } else { - assert(tagTOS == TY_FLOAT); - o4(0xECFD6A01); // fldmfds sp!,{s13} - o4(0xEEB76AE6); // fcvtds d6, s13 - } -#else - o4(0xE92D0003); // stmfd sp!,{r0,r1} // push r0,r1 - o4(0xE59D0008); // ldr r0, [sp, #8] - if (tagTOS == TY_INT) { - callRuntime((void*) runtime_int_to_double); - } else { - assert(tagTOS == TY_FLOAT); - callRuntime((void*) runtime_float_to_double); - } - o4(0xE1A02000); // mov r2, r0 - o4(0xE1A03001); // mov r3, r1 - o4(0xE8BD0003); // ldmfd sp!,{r0, r1} // Restore R0 - o4(0xE28DD004); // add sp, sp, #4 // Pop sp -#endif - mStackUse -= 4; - } else { -#ifdef ARM_USE_VFP - o4(0xECBD6B02); // fldmfdd sp!, {d6} -#else - o4(0xE8BD000C); // ldmfd sp!,{r2,r3} -#endif - mStackUse -= 8; - } - popType(); - } - - void liReg(int t, int reg) { - assert(reg >= 0 && reg < 16); - int rN = (reg & 0xf) << 12; - size_t encodedImmediate; - if (encode12BitImmediate(t, &encodedImmediate)) { - o4(0xE3A00000 | encodedImmediate | rN); // mov rN, #0 - } else if (encode12BitImmediate(-(t+1), &encodedImmediate)) { - // mvn means move constant ^ ~0 - o4(0xE3E00000 | encodedImmediate | rN); // mvn rN, #0 - } else { - o4(0xE51F0000 | rN); // ldr rN, .L3 - o4(0xEA000000); // b .L99 - o4(t); // .L3: .word 0 - // .L99: - } - } - - void incompatibleTypes(Type* pR0Type, Type* pType) { - error("Incompatible types old: %d new: %d", pR0Type->tag, pType->tag); - } - - void callRuntime(void* fn) { - o4(0xE59FC000); // ldr r12, .L1 - o4(0xEA000000); // b .L99 - o4((int) fn); //.L1: .word fn - o4(0xE12FFF3C); //.L99: blx r12 - } - - // Integer math: - - static int runtime_DIV(int b, int a) { - return a / b; - } - - static int runtime_MOD(int b, int a) { - return a % b; - } - - static void runtime_structCopy(void* src, size_t size, void* dest) { - memcpy(dest, src, size); - } - -#ifndef ARM_USE_VFP - - // Comparison to zero - - static int runtime_is_non_zero_f(float a) { - return a != 0; - } - - static int runtime_is_non_zero_d(double a) { - return a != 0; - } - - // Comparison to zero - - static int runtime_is_zero_f(float a) { - return a == 0; - } - - static int runtime_is_zero_d(double a) { - return a == 0; - } - - // Type conversion - - static int runtime_float_to_int(float a) { - return (int) a; - } - - static double runtime_float_to_double(float a) { - return (double) a; - } - - static int runtime_double_to_int(double a) { - return (int) a; - } - - static float runtime_double_to_float(double a) { - return (float) a; - } - - static float runtime_int_to_float(int a) { - return (float) a; - } - - static double runtime_int_to_double(int a) { - return (double) a; - } - - // Comparisons float - - static int runtime_cmp_eq_ff(float b, float a) { - return a == b; - } - - static int runtime_cmp_ne_ff(float b, float a) { - return a != b; - } - - static int runtime_cmp_lt_ff(float b, float a) { - return a < b; - } - - static int runtime_cmp_le_ff(float b, float a) { - return a <= b; - } - - static int runtime_cmp_ge_ff(float b, float a) { - return a >= b; - } - - static int runtime_cmp_gt_ff(float b, float a) { - return a > b; - } - - // Comparisons double - - static int runtime_cmp_eq_dd(double b, double a) { - return a == b; - } - - static int runtime_cmp_ne_dd(double b, double a) { - return a != b; - } - - static int runtime_cmp_lt_dd(double b, double a) { - return a < b; - } - - static int runtime_cmp_le_dd(double b, double a) { - return a <= b; - } - - static int runtime_cmp_ge_dd(double b, double a) { - return a >= b; - } - - static int runtime_cmp_gt_dd(double b, double a) { - return a > b; - } - - // Math float - - static float runtime_op_add_ff(float b, float a) { - return a + b; - } - - static float runtime_op_sub_ff(float b, float a) { - return a - b; - } - - static float runtime_op_mul_ff(float b, float a) { - return a * b; - } - - static float runtime_op_div_ff(float b, float a) { - return a / b; - } - - static float runtime_op_neg_f(float a) { - return -a; - } - - // Math double - - static double runtime_op_add_dd(double b, double a) { - return a + b; - } - - static double runtime_op_sub_dd(double b, double a) { - return a - b; - } - - static double runtime_op_mul_dd(double b, double a) { - return a * b; - } - - static double runtime_op_div_dd(double b, double a) { - return a / b; - } - - static double runtime_op_neg_d(double a) { - return -a; - } - -#endif - - static const int STACK_ALIGNMENT = 8; - int mStackUse; - // This variable holds the amount we adjusted the stack in the most - // recent endFunctionCallArguments call. It's examined by the - // following adjustStackAfterCall call. - int mStackAlignmentAdjustment; - }; - -#endif // PROVIDE_ARM_CODEGEN - -#ifdef PROVIDE_X86_CODEGEN - - class X86CodeGenerator : public CodeGenerator { - public: - X86CodeGenerator() {} - virtual ~X86CodeGenerator() {} - - /* returns address to patch with local variable size - */ - virtual int functionEntry(Type* pDecl) { - o(0xe58955); /* push %ebp, mov %esp, %ebp */ - return oad(0xec81, 0); /* sub $xxx, %esp */ - } - - virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) { - o(0xc3c9); /* leave, ret */ - *(int *) localVariableAddress = localVariableSize; /* save local variables */ - } - - /* load immediate value */ - virtual void li(int i) { - oad(0xb8, i); /* mov $xx, %eax */ - setR0Type(mkpInt); - } - - virtual void loadFloat(int address, Type* pType) { - setR0Type(pType); - switch (pType->tag) { - case TY_FLOAT: - oad(0x05D9, address); // flds - break; - case TY_DOUBLE: - oad(0x05DD, address); // fldl - break; - default: - assert(false); - break; - } - } - - virtual void addStructOffsetR0(int offset, Type* pType) { - if (offset) { - oad(0x05, offset); // addl offset, %eax - } - setR0Type(pType, ET_LVALUE); - } - - virtual int gjmp(int t) { - return psym(0xe9, t); - } - - /* l = 0: je, l == 1: jne */ - virtual int gtst(bool l, int t) { - Type* pR0Type = getR0Type(); - TypeTag tagR0 = pR0Type->tag; - bool isFloatR0 = isFloatTag(tagR0); - if (isFloatR0) { - o(0xeed9); // fldz - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - } else { - o(0xc085); // test %eax, %eax - } - // Use two output statements to generate one instruction. - o(0x0f); // je/jne xxx - return psym(0x84 + l, t); - } - - virtual void gcmp(int op) { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = pR0Type->tag; - TypeTag tagTOS = pTOSType->tag; - bool isFloatR0 = isFloatTag(tagR0); - bool isFloatTOS = isFloatTag(tagTOS); - if (!isFloatR0 && !isFloatTOS) { - int t = decodeOp(op); - o(0x59); /* pop %ecx */ - o(0xc139); /* cmp %eax,%ecx */ - li(0); - o(0x0f); /* setxx %al */ - o(t + 0x90); - o(0xc0); - popType(); - } else { - setupFloatOperands(); - switch (op) { - case OP_EQUALS: - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0940f); // sete %al - o(0xc29b0f); // setnp %dl - o(0xd021); // andl %edx, %eax - break; - case OP_NOT_EQUALS: - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0950f); // setne %al - o(0xc29a0f); // setp %dl - o(0xd009); // orl %edx, %eax - break; - case OP_GREATER_EQUAL: - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x05c4f6); // testb $5, %ah - o(0xc0940f); // sete %al - break; - case OP_LESS: - o(0xc9d9); // fxch %st(1) - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0970f); // seta %al - break; - case OP_LESS_EQUAL: - o(0xc9d9); // fxch %st(1) - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0930f); // setea %al - break; - case OP_GREATER: - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x45c4f6); // testb $69, %ah - o(0xc0940f); // sete %al - break; - default: - error("Unknown comparison op"); - } - o(0xc0b60f); // movzbl %al, %eax - } - setR0Type(mkpInt); - } - - virtual void genOp(int op) { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = pR0Type->tag; - TypeTag tagTOS = pTOSType->tag; - bool isFloatR0 = isFloatTag(tagR0); - bool isFloatTOS = isFloatTag(tagTOS); - if (!isFloatR0 && !isFloatTOS) { - bool isPtrR0 = isPointerTag(tagR0); - bool isPtrTOS = isPointerTag(tagTOS); - if (isPtrR0 || isPtrTOS) { - if (isPtrR0 && isPtrTOS) { - if (op != OP_MINUS) { - error("Unsupported pointer-pointer operation %d.", op); - } - if (! typeEqual(pR0Type, pTOSType)) { - error("Incompatible pointer types for subtraction."); - } - o(0x59); /* pop %ecx */ - o(decodeOp(op)); - popType(); - setR0Type(mkpInt); - int size = sizeOf(pR0Type->pHead); - if (size != 1) { - pushR0(); - li(size); - // TODO: Optimize for power-of-two. - genOp(OP_DIV); - } - } else { - if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { - error("Unsupported pointer-scalar operation %d", op); - } - Type* pPtrType = getPointerArithmeticResultType( - pR0Type, pTOSType); - o(0x59); /* pop %ecx */ - int size = sizeOf(pPtrType->pHead); - if (size != 1) { - // TODO: Optimize for power-of-two. - if (isPtrR0) { - oad(0xC969, size); // imull $size, %ecx - } else { - oad(0xC069, size); // mul $size, %eax - } - } - o(decodeOp(op)); - popType(); - setR0Type(pPtrType); - } - } else { - o(0x59); /* pop %ecx */ - o(decodeOp(op)); - if (op == OP_MOD) - o(0x92); /* xchg %edx, %eax */ - popType(); - } - } else { - Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; - setupFloatOperands(); - // Both float. x87 R0 == left hand, x87 R1 == right hand - switch (op) { - case OP_MUL: - o(0xc9de); // fmulp - break; - case OP_DIV: - o(0xf1de); // fdivp - break; - case OP_PLUS: - o(0xc1de); // faddp - break; - case OP_MINUS: - o(0xe1de); // fsubp - break; - default: - error("Unsupported binary floating operation."); - break; - } - setR0Type(pResultType); - } - } - - virtual void gUnaryCmp(int op) { - if (op != OP_LOGICAL_NOT) { - error("Unknown unary cmp %d", op); - } else { - Type* pR0Type = getR0Type(); - TypeTag tag = collapseType(pR0Type->tag); - switch(tag) { - case TY_INT: { - oad(0xb9, 0); /* movl $0, %ecx */ - int t = decodeOp(op); - o(0xc139); /* cmp %eax,%ecx */ - li(0); - o(0x0f); /* setxx %al */ - o(t + 0x90); - o(0xc0); - } - break; - case TY_FLOAT: - case TY_DOUBLE: - o(0xeed9); // fldz - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0950f); // setne %al - o(0xc29a0f); // setp %dl - o(0xd009); // orl %edx, %eax - o(0xc0b60f); // movzbl %al, %eax - o(0x01f083); // xorl $1, %eax - break; - default: - error("gUnaryCmp unsupported type"); - break; - } - } - setR0Type(mkpInt); - } - - virtual void genUnaryOp(int op) { - Type* pR0Type = getR0Type(); - TypeTag tag = collapseType(pR0Type->tag); - switch(tag) { - case TY_INT: - oad(0xb9, 0); /* movl $0, %ecx */ - o(decodeOp(op)); - break; - case TY_FLOAT: - case TY_DOUBLE: - switch (op) { - case OP_MINUS: - o(0xe0d9); // fchs - break; - case OP_BIT_NOT: - error("Can't apply '~' operator to a float or double."); - break; - default: - error("Unknown unary op %d\n", op); - break; - } - break; - default: - error("genUnaryOp unsupported type"); - break; - } - } - - virtual void pushR0() { - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - switch(r0ct) { - case TY_INT: - o(0x50); /* push %eax */ - break; - case TY_FLOAT: - o(0x50); /* push %eax */ - o(0x241cd9); // fstps 0(%esp) - break; - case TY_DOUBLE: - o(0x50); /* push %eax */ - o(0x50); /* push %eax */ - o(0x241cdd); // fstpl 0(%esp) - break; - default: - error("pushR0 unsupported type %d", r0ct); - break; - } - pushType(); - } - - virtual void over() { - // We know it's only used for int-ptr ops (++/--) - - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - - Type* pTOSType = getTOSType(); - TypeTag tosct = collapseType(pTOSType->tag); - - assert (r0ct == TY_INT && tosct == TY_INT); - - o(0x59); /* pop %ecx */ - o(0x50); /* push %eax */ - o(0x51); /* push %ecx */ - - overType(); - } - - virtual void popR0() { - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - switch(r0ct) { - case TY_INT: - o(0x58); /* popl %eax */ - break; - case TY_FLOAT: - o(0x2404d9); // flds (%esp) - o(0x58); /* popl %eax */ - break; - case TY_DOUBLE: - o(0x2404dd); // fldl (%esp) - o(0x58); /* popl %eax */ - o(0x58); /* popl %eax */ - break; - default: - error("popR0 unsupported type %d", r0ct); - break; - } - popType(); - } - - virtual void storeR0ToTOS() { - Type* pPointerType = getTOSType(); - assert(pPointerType->tag == TY_POINTER); - Type* pTargetType = pPointerType->pHead; - convertR0(pTargetType); - o(0x59); /* pop %ecx */ - popType(); - switch (pTargetType->tag) { - case TY_POINTER: - case TY_INT: - o(0x0189); /* movl %eax/%al, (%ecx) */ - break; - case TY_SHORT: - o(0x018966); /* movw %ax, (%ecx) */ - break; - case TY_CHAR: - o(0x0188); /* movl %eax/%al, (%ecx) */ - break; - case TY_FLOAT: - o(0x19d9); /* fstps (%ecx) */ - break; - case TY_DOUBLE: - o(0x19dd); /* fstpl (%ecx) */ - break; - case TY_STRUCT: - { - // TODO: use alignment information to use movsw/movsl instead of movsb - int size = sizeOf(pTargetType); - if (size > 0) { - o(0x9c); // pushf - o(0x57); // pushl %edi - o(0x56); // pushl %esi - o(0xcf89); // movl %ecx, %edi - o(0xc689); // movl %eax, %esi - oad(0xb9, size); // mov #size, %ecx - o(0xfc); // cld - o(0xf3); // rep - o(0xa4); // movsb - o(0x5e); // popl %esi - o(0x5f); // popl %edi - o(0x9d); // popf - } - } - break; - default: - error("storeR0ToTOS: unsupported type %d", - pTargetType->tag); - break; - } - setR0Type(pTargetType); - } - - virtual void loadR0FromR0() { - Type* pPointerType = getR0Type(); - assert(pPointerType->tag == TY_POINTER); - Type* pNewType = pPointerType->pHead; - TypeTag tag = pNewType->tag; - switch (tag) { - case TY_POINTER: - case TY_INT: - o2(0x008b); /* mov (%eax), %eax */ - break; - case TY_SHORT: - o(0xbf0f); /* movswl (%eax), %eax */ - ob(0); - break; - case TY_CHAR: - o(0xbe0f); /* movsbl (%eax), %eax */ - ob(0); /* add zero in code */ - break; - case TY_FLOAT: - o2(0x00d9); // flds (%eax) - break; - case TY_DOUBLE: - o2(0x00dd); // fldl (%eax) - break; - case TY_ARRAY: - pNewType = pNewType->pTail; - break; - case TY_STRUCT: - break; - default: - error("loadR0FromR0: unsupported type %d", tag); - break; - } - setR0Type(pNewType); - } - - virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) { - gmov(10, ea); /* leal EA, %eax */ - setR0Type(pPointerType, et); - } - - virtual int leaForward(int ea, Type* pPointerType) { - oad(0xb8, ea); /* mov $xx, %eax */ - setR0Type(pPointerType); - return getPC() - 4; - } - - virtual void convertR0Imp(Type* pType, bool isCast){ - Type* pR0Type = getR0Type(); - if (pR0Type == NULL) { - assert(false); - setR0Type(pType); - return; - } - if (isPointerType(pType) && isPointerType(pR0Type)) { - Type* pA = pR0Type; - Type* pB = pType; - // Array decays to pointer - if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) { - pA = pA->pTail; - } - if (! (typeEqual(pA, pB) - || pB->pHead->tag == TY_VOID - || (pA->tag == TY_POINTER && pB->tag == TY_POINTER && isCast) - )) { - error("Incompatible pointer or array types"); - } - } else if (bitsSame(pType, pR0Type)) { - // do nothing special - } else if (isFloatType(pType) && isFloatType(pR0Type)) { - // do nothing special, both held in same register on x87. - } else { - TypeTag r0Tag = collapseType(pR0Type->tag); - TypeTag destTag = collapseType(pType->tag); - if (r0Tag == TY_INT && isFloatTag(destTag)) { - // Convert R0 from int to float - o(0x50); // push %eax - o(0x2404DB); // fildl 0(%esp) - o(0x58); // pop %eax - } else if (isFloatTag(r0Tag) && destTag == TY_INT) { - // Convert R0 from float to int. Complicated because - // need to save and restore the rounding mode. - o(0x50); // push %eax - o(0x50); // push %eax - o(0x02247cD9); // fnstcw 2(%esp) - o(0x2444b70f); // movzwl 2(%esp), %eax - o(0x02); - o(0x0cb4); // movb $12, %ah - o(0x24048966); // movw %ax, 0(%esp) - o(0x242cd9); // fldcw 0(%esp) - o(0x04245cdb); // fistpl 4(%esp) - o(0x02246cd9); // fldcw 2(%esp) - o(0x58); // pop %eax - o(0x58); // pop %eax - } else { - error("Incompatible types old: %d new: %d", - pR0Type->tag, pType->tag); - } - } - setR0Type(pType); - } - - virtual int beginFunctionCallArguments() { - return oad(0xec81, 0); /* sub $xxx, %esp */ - } - - virtual size_t storeR0ToArg(int l, Type* pArgType) { - convertR0(pArgType); - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - switch(r0ct) { - case TY_INT: - oad(0x248489, l); /* movl %eax, xxx(%esp) */ - return 4; - case TY_FLOAT: - oad(0x249CD9, l); /* fstps xxx(%esp) */ - return 4; - case TY_DOUBLE: - oad(0x249CDD, l); /* fstpl xxx(%esp) */ - return 8; - default: - assert(false); - return 0; - } - } - - virtual void endFunctionCallArguments(Type* pDecl, int a, int l) { - * (int*) a = l; - } - - virtual int callForward(int symbol, Type* pFunc) { - assert(pFunc->tag == TY_FUNC); - setR0Type(pFunc->pHead); - return psym(0xe8, symbol); /* call xxx */ - } - - virtual void callIndirect(int l, Type* pFunc) { - assert(pFunc->tag == TY_FUNC); - popType(); // Get rid of indirect fn pointer type - setR0Type(pFunc->pHead); - oad(0x2494ff, l); /* call *xxx(%esp) */ - } - - virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) { - assert(pDecl->tag == TY_FUNC); - if (isIndirect) { - l += 4; - } - if (l > 0) { - oad(0xc481, l); /* add $xxx, %esp */ - } - } - - virtual int jumpOffset() { - return 5; - } - - /* output a symbol and patch all calls to it */ - virtual void gsym(int t) { - int n; - int pc = getPC(); - while (t) { - n = *(int *) t; /* next value */ - *(int *) t = pc - t - 4; - t = n; - } - } - - /* output a symbol and patch all calls to it, using absolute address */ - virtual void resolveForward(int t) { - int n; - int pc = getPC(); - while (t) { - n = *(int *) t; /* next value */ - *(int *) t = pc; - t = n; - } - } - - virtual int finishCompile() { - size_t pagesize = 4096; - size_t base = (size_t) getBase() & ~ (pagesize - 1); - size_t top = ((size_t) getPC() + pagesize - 1) & ~ (pagesize - 1); - int err = mprotect((void*) base, top - base, PROT_READ | PROT_WRITE | PROT_EXEC); - if (err) { - error("mprotect() failed: %d", errno); - } - return err; - } - - /** - * Alignment (in bytes) for this type of data - */ - virtual size_t alignmentOf(Type* pType){ - switch (pType->tag) { - case TY_CHAR: - return 1; - case TY_SHORT: - return 2; - case TY_ARRAY: - return alignmentOf(pType->pHead); - case TY_STRUCT: - return pType->pHead->alignment & 0x7fffffff; - case TY_FUNC: - error("alignment of func not supported"); - return 1; - default: - return 4; - } - } - - /** - * Array element alignment (in bytes) for this type of data. - */ - virtual size_t sizeOf(Type* pType){ - switch(pType->tag) { - case TY_INT: - return 4; - case TY_SHORT: - return 2; - case TY_CHAR: - return 1; - case TY_FLOAT: - return 4; - case TY_DOUBLE: - return 8; - case TY_POINTER: - return 4; - case TY_ARRAY: - return pType->length * sizeOf(pType->pHead); - case TY_STRUCT: - return pType->pHead->length; - default: - error("Unsupported type %d", pType->tag); - return 0; - } - } - - private: - - /** Output 1 to 4 bytes. - * - */ - void o(int n) { - /* cannot use unsigned, so we must do a hack */ - while (n && n != -1) { - ob(n & 0xff); - n = n >> 8; - } - } - - /* Output exactly 2 bytes - */ - void o2(int n) { - ob(n & 0xff); - ob(0xff & (n >> 8)); - } - - /* psym is used to put an instruction with a data field which is a - reference to a symbol. It is in fact the same as oad ! */ - int psym(int n, int t) { - return oad(n, t); - } - - /* instruction + address */ - int oad(int n, int t) { - o(n); - int result = getPC(); - o4(t); - return result; - } - - static const int operatorHelper[]; - - int decodeOp(int op) { - if (op < 0 || op > OP_COUNT) { - error("Out-of-range operator: %d\n", op); - op = 0; - } - return operatorHelper[op]; - } - - void gmov(int l, int t) { - o(l + 0x83); - oad((t > -LOCAL && t < LOCAL) << 7 | 5, t); - } - - void setupFloatOperands() { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = pR0Type->tag; - TypeTag tagTOS = pTOSType->tag; - bool isFloatR0 = isFloatTag(tagR0); - bool isFloatTOS = isFloatTag(tagTOS); - if (! isFloatR0) { - // Convert R0 from int to float - o(0x50); // push %eax - o(0x2404DB); // fildl 0(%esp) - o(0x58); // pop %eax - } - if (! isFloatTOS){ - o(0x2404DB); // fildl 0(%esp); - o(0x58); // pop %eax - } else { - if (tagTOS == TY_FLOAT) { - o(0x2404d9); // flds (%esp) - o(0x58); // pop %eax - } else { - o(0x2404dd); // fldl (%esp) - o(0x58); // pop %eax - o(0x58); // pop %eax - } - } - popType(); - } - }; - -#endif // PROVIDE_X86_CODEGEN - -#ifdef PROVIDE_TRACE_CODEGEN - class TraceCodeGenerator : public CodeGenerator { - private: - CodeGenerator* mpBase; - - public: - TraceCodeGenerator(CodeGenerator* pBase) { - mpBase = pBase; - } - - virtual ~TraceCodeGenerator() { - delete mpBase; - } - - virtual void init(ICodeBuf* pCodeBuf) { - mpBase->init(pCodeBuf); - } - - void setErrorSink(ErrorSink* pErrorSink) { - mpBase->setErrorSink(pErrorSink); - } - - /* returns address to patch with local variable size - */ - virtual int functionEntry(Type* pDecl) { - int result = mpBase->functionEntry(pDecl); - fprintf(stderr, "functionEntry(pDecl) -> %d\n", result); - return result; - } - - virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) { - fprintf(stderr, "functionExit(pDecl, %d, %d)\n", - localVariableAddress, localVariableSize); - mpBase->functionExit(pDecl, localVariableAddress, localVariableSize); - } - - /* load immediate value */ - virtual void li(int t) { - fprintf(stderr, "li(%d)\n", t); - mpBase->li(t); - } - - virtual void loadFloat(int address, Type* pType) { - fprintf(stderr, "loadFloat(%d, type=%d)\n", address, pType->tag); - mpBase->loadFloat(address, pType); - } - - virtual void addStructOffsetR0(int offset, Type* pType) { - fprintf(stderr, "addStructOffsetR0(%d, type=%d)\n", offset, pType->tag); - mpBase->addStructOffsetR0(offset, pType); - } - - virtual int gjmp(int t) { - int result = mpBase->gjmp(t); - fprintf(stderr, "gjmp(%d) = %d\n", t, result); - return result; - } - - /* l = 0: je, l == 1: jne */ - virtual int gtst(bool l, int t) { - int result = mpBase->gtst(l, t); - fprintf(stderr, "gtst(%d,%d) = %d\n", l, t, result); - return result; - } - - virtual void gcmp(int op) { - fprintf(stderr, "gcmp(%d)\n", op); - mpBase->gcmp(op); - } - - virtual void genOp(int op) { - fprintf(stderr, "genOp(%d)\n", op); - mpBase->genOp(op); - } - - - virtual void gUnaryCmp(int op) { - fprintf(stderr, "gUnaryCmp(%d)\n", op); - mpBase->gUnaryCmp(op); - } - - virtual void genUnaryOp(int op) { - fprintf(stderr, "genUnaryOp(%d)\n", op); - mpBase->genUnaryOp(op); - } - - virtual void pushR0() { - fprintf(stderr, "pushR0()\n"); - mpBase->pushR0(); - } - - virtual void over() { - fprintf(stderr, "over()\n"); - mpBase->over(); - } - - virtual void popR0() { - fprintf(stderr, "popR0()\n"); - mpBase->popR0(); - } - - virtual void storeR0ToTOS() { - fprintf(stderr, "storeR0ToTOS()\n"); - mpBase->storeR0ToTOS(); - } - - virtual void loadR0FromR0() { - fprintf(stderr, "loadR0FromR0()\n"); - mpBase->loadR0FromR0(); - } - - virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) { - fprintf(stderr, "leaR0(%d, %d, %d)\n", ea, - pPointerType->pHead->tag, et); - mpBase->leaR0(ea, pPointerType, et); - } - - virtual int leaForward(int ea, Type* pPointerType) { - fprintf(stderr, "leaForward(%d)\n", ea); - return mpBase->leaForward(ea, pPointerType); - } - - virtual void convertR0Imp(Type* pType, bool isCast){ - fprintf(stderr, "convertR0(pType tag=%d, %d)\n", pType->tag, isCast); - mpBase->convertR0Imp(pType, isCast); - } - - virtual int beginFunctionCallArguments() { - int result = mpBase->beginFunctionCallArguments(); - fprintf(stderr, "beginFunctionCallArguments() = %d\n", result); - return result; - } - - virtual size_t storeR0ToArg(int l, Type* pArgType) { - fprintf(stderr, "storeR0ToArg(%d, pArgType=%d)\n", l, - pArgType->tag); - return mpBase->storeR0ToArg(l, pArgType); - } - - virtual void endFunctionCallArguments(Type* pDecl, int a, int l) { - fprintf(stderr, "endFunctionCallArguments(%d, %d)\n", a, l); - mpBase->endFunctionCallArguments(pDecl, a, l); - } - - virtual int callForward(int symbol, Type* pFunc) { - int result = mpBase->callForward(symbol, pFunc); - fprintf(stderr, "callForward(%d) = %d\n", symbol, result); - return result; - } - - virtual void callIndirect(int l, Type* pFunc) { - fprintf(stderr, "callIndirect(%d returntype = %d)\n", l, - pFunc->pHead->tag); - mpBase->callIndirect(l, pFunc); - } - - virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) { - fprintf(stderr, "adjustStackAfterCall(pType, %d, %d)\n", l, isIndirect); - mpBase->adjustStackAfterCall(pDecl, l, isIndirect); - } - - virtual int jumpOffset() { - return mpBase->jumpOffset(); - } - - /* output a symbol and patch all calls to it */ - virtual void gsym(int t) { - fprintf(stderr, "gsym(%d)\n", t); - mpBase->gsym(t); - } - - virtual void resolveForward(int t) { - mpBase->resolveForward(t); - } - - virtual int finishCompile() { - int result = mpBase->finishCompile(); - fprintf(stderr, "finishCompile() = %d\n", result); - return result; - } - - /** - * Alignment (in bytes) for this type of data - */ - virtual size_t alignmentOf(Type* pType){ - return mpBase->alignmentOf(pType); - } - - /** - * Array element alignment (in bytes) for this type of data. - */ - virtual size_t sizeOf(Type* pType){ - return mpBase->sizeOf(pType); - } - - virtual Type* getR0Type() { - return mpBase->getR0Type(); - } - - virtual ExpressionType getR0ExpressionType() { - return mpBase->getR0ExpressionType(); - } - - virtual void setR0ExpressionType(ExpressionType et) { - mpBase->setR0ExpressionType(et); - } - - virtual size_t getExpressionStackDepth() { - return mpBase->getExpressionStackDepth(); - } - - virtual void forceR0RVal() { - return mpBase->forceR0RVal(); - } - }; - -#endif // PROVIDE_TRACE_CODEGEN - - class Arena { - public: - // Used to record a given allocation amount. - // Used: - // Mark mark = arena.mark(); - // ... lots of arena.allocate() - // arena.free(mark); - - struct Mark { - size_t chunk; - size_t offset; - }; - - Arena() { - mCurrentChunk = 0; - Chunk start(CHUNK_SIZE); - mData.push_back(start); - } - - ~Arena() { - for(size_t i = 0; i < mData.size(); i++) { - mData[i].free(); - } - } - - // Alloc using the standard alignment size safe for any variable - void* alloc(size_t size) { - return alloc(size, 8); - } - - Mark mark(){ - Mark result; - result.chunk = mCurrentChunk; - result.offset = mData[mCurrentChunk].mOffset; - return result; - } - - void freeToMark(const Mark& mark) { - mCurrentChunk = mark.chunk; - mData[mCurrentChunk].mOffset = mark.offset; - } - - private: - // Allocate memory aligned to a given size - // and a given power-of-two-sized alignment (e.g. 1,2,4,8,...) - // Memory is not zero filled. - - void* alloc(size_t size, size_t alignment) { - while (size > mData[mCurrentChunk].remainingCapacity(alignment)) { - if (mCurrentChunk + 1 < mData.size()) { - mCurrentChunk++; - } else { - size_t allocSize = CHUNK_SIZE; - if (allocSize < size + alignment - 1) { - allocSize = size + alignment - 1; - } - Chunk chunk(allocSize); - mData.push_back(chunk); - mCurrentChunk++; - } - } - return mData[mCurrentChunk].allocate(size, alignment); - } - - static const size_t CHUNK_SIZE = 128*1024; - // Note: this class does not deallocate its - // memory when it's destroyed. It depends upon - // its parent to deallocate the memory. - struct Chunk { - Chunk() { - mpData = 0; - mSize = 0; - mOffset = 0; - } - - Chunk(size_t size) { - mSize = size; - mpData = (char*) malloc(size); - mOffset = 0; - } - - ~Chunk() { - // Doesn't deallocate memory. - } - - void* allocate(size_t size, size_t alignment) { - size_t alignedOffset = aligned(mOffset, alignment); - void* result = mpData + alignedOffset; - mOffset = alignedOffset + size; - return result; - } - - void free() { - if (mpData) { - ::free(mpData); - mpData = 0; - } - } - - size_t remainingCapacity(size_t alignment) { - return aligned(mSize, alignment) - aligned(mOffset, alignment); - } - - // Assume alignment is a power of two - inline size_t aligned(size_t v, size_t alignment) { - size_t mask = alignment-1; - return (v + mask) & ~mask; - } - - char* mpData; - size_t mSize; - size_t mOffset; - }; - - size_t mCurrentChunk; - - Vector<Chunk> mData; - }; - - struct VariableInfo; - - struct Token { - int hash; - size_t length; - char* pText; - tokenid_t id; - - // Current values for the token - char* mpMacroDefinition; - VariableInfo* mpVariableInfo; - VariableInfo* mpStructInfo; - }; - - class TokenTable { - public: - // Don't use 0..0xff, allows characters and operators to be tokens too. - - static const int TOKEN_BASE = 0x100; - TokenTable() { - mpMap = hashmapCreate(128, hashFn, equalsFn); - } - - ~TokenTable() { - hashmapFree(mpMap); - } - - void setArena(Arena* pArena) { - mpArena = pArena; - } - - // Returns a token for a given string of characters. - tokenid_t intern(const char* pText, size_t length) { - Token probe; - int hash = hashmapHash((void*) pText, length); - { - Token probe; - probe.hash = hash; - probe.length = length; - probe.pText = (char*) pText; - Token* pValue = (Token*) hashmapGet(mpMap, &probe); - if (pValue) { - return pValue->id; - } - } - - Token* pToken = (Token*) mpArena->alloc(sizeof(Token)); - memset(pToken, 0, sizeof(*pToken)); - pToken->hash = hash; - pToken->length = length; - pToken->pText = (char*) mpArena->alloc(length + 1); - memcpy(pToken->pText, pText, length); - pToken->pText[length] = 0; - pToken->id = mTokens.size() + TOKEN_BASE; - mTokens.push_back(pToken); - hashmapPut(mpMap, pToken, pToken); - return pToken->id; - } - - // Return the Token for a given tokenid. - Token& operator[](tokenid_t id) { - return *mTokens[id - TOKEN_BASE]; - } - - inline size_t size() { - return mTokens.size(); - } - - private: - - static int hashFn(void* pKey) { - Token* pToken = (Token*) pKey; - return pToken->hash; - } - - static bool equalsFn(void* keyA, void* keyB) { - Token* pTokenA = (Token*) keyA; - Token* pTokenB = (Token*) keyB; - // Don't need to compare hash values, they should always be equal - return pTokenA->length == pTokenB->length - && strcmp(pTokenA->pText, pTokenB->pText) == 0; - } - - Hashmap* mpMap; - Vector<Token*> mTokens; - Arena* mpArena; - }; - - class InputStream { - public: - virtual ~InputStream() {} - virtual int getChar() = 0; - }; - - class TextInputStream : public InputStream { - public: - TextInputStream(const char* text, size_t textLength) - : pText(text), mTextLength(textLength), mPosition(0) { - } - - virtual int getChar() { - return mPosition < mTextLength ? pText[mPosition++] : EOF; - } - - private: - const char* pText; - size_t mTextLength; - size_t mPosition; - }; - - class String { - public: - String() { - mpBase = 0; - mUsed = 0; - mSize = 0; - } - - String(const char* item, int len, bool adopt) { - if (len < 0) { - len = strlen(item); - } - if (adopt) { - mpBase = (char*) item; - mUsed = len; - mSize = len + 1; - } else { - mpBase = 0; - mUsed = 0; - mSize = 0; - appendBytes(item, len); - } - } - - String(const String& other) { - mpBase = 0; - mUsed = 0; - mSize = 0; - appendBytes(other.getUnwrapped(), other.len()); - } - - ~String() { - if (mpBase) { - free(mpBase); - } - } - - String& operator=(const String& other) { - clear(); - appendBytes(other.getUnwrapped(), other.len()); - return *this; - } - - inline char* getUnwrapped() const { - return mpBase; - } - - void clear() { - mUsed = 0; - if (mSize > 0) { - mpBase[0] = 0; - } - } - - void appendCStr(const char* s) { - appendBytes(s, strlen(s)); - } - - void appendBytes(const char* s, int n) { - memcpy(ensure(n), s, n + 1); - } - - void append(char c) { - * ensure(1) = c; - } - - void append(String& other) { - appendBytes(other.getUnwrapped(), other.len()); - } - - char* orphan() { - char* result = mpBase; - mpBase = 0; - mUsed = 0; - mSize = 0; - return result; - } - - void printf(const char* fmt,...) { - va_list ap; - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); - } - - void vprintf(const char* fmt, va_list ap) { - char* temp; - int numChars = vasprintf(&temp, fmt, ap); - memcpy(ensure(numChars), temp, numChars+1); - free(temp); - } - - inline size_t len() const { - return mUsed; - } - - private: - char* ensure(int n) { - size_t newUsed = mUsed + n; - if (newUsed > mSize) { - size_t newSize = mSize * 2 + 10; - if (newSize < newUsed) { - newSize = newUsed; - } - mpBase = (char*) realloc(mpBase, newSize + 1); - mSize = newSize; - } - mpBase[newUsed] = '\0'; - char* result = mpBase + mUsed; - mUsed = newUsed; - return result; - } - - char* mpBase; - size_t mUsed; - size_t mSize; - }; - - void internKeywords() { - // Note: order has to match TOK_ constants - static const char* keywords[] = { - "int", - "char", - "void", - "if", - "else", - "while", - "break", - "return", - "for", - "auto", - "case", - "const", - "continue", - "default", - "do", - "double", - "enum", - "extern", - "float", - "goto", - "long", - "register", - "short", - "signed", - "sizeof", - "static", - "struct", - "switch", - "typedef", - "union", - "unsigned", - "volatile", - "_Bool", - "_Complex", - "_Imaginary", - "inline", - "restrict", - - // predefined tokens that can also be symbols start here: - "pragma", - "define", - "line", - 0}; - - for(int i = 0; keywords[i]; i++) { - mTokenTable.intern(keywords[i], strlen(keywords[i])); - } - } - - struct InputState { - InputStream* pStream; - int oldCh; - }; - - struct VariableInfo { - void* pAddress; - void* pForward; // For a forward direction, linked list of data to fix up - tokenid_t tok; - size_t level; - VariableInfo* pOldDefinition; - Type* pType; - bool isStructTag; - }; - - class SymbolStack { - public: - SymbolStack() { - mpArena = 0; - mpTokenTable = 0; - } - - void setArena(Arena* pArena) { - mpArena = pArena; - } - - void setTokenTable(TokenTable* pTokenTable) { - mpTokenTable = pTokenTable; - } - - void pushLevel() { - Mark mark; - mark.mArenaMark = mpArena->mark(); - mark.mSymbolHead = mStack.size(); - mLevelStack.push_back(mark); - } - - void popLevel() { - // Undo any shadowing that was done: - Mark mark = mLevelStack.back(); - mLevelStack.pop_back(); - while (mStack.size() > mark.mSymbolHead) { - VariableInfo* pV = mStack.back(); - mStack.pop_back(); - if (pV->isStructTag) { - (*mpTokenTable)[pV->tok].mpStructInfo = pV->pOldDefinition; - } else { - (*mpTokenTable)[pV->tok].mpVariableInfo = pV->pOldDefinition; - } - } - mpArena->freeToMark(mark.mArenaMark); - } - - bool isDefinedAtCurrentLevel(tokenid_t tok) { - VariableInfo* pV = (*mpTokenTable)[tok].mpVariableInfo; - return pV && pV->level == level(); - } - - bool isStructTagDefinedAtCurrentLevel(tokenid_t tok) { - VariableInfo* pV = (*mpTokenTable)[tok].mpStructInfo; - return pV && pV->level == level(); - } - - VariableInfo* add(tokenid_t tok) { - Token& token = (*mpTokenTable)[tok]; - VariableInfo* pOldV = token.mpVariableInfo; - VariableInfo* pNewV = - (VariableInfo*) mpArena->alloc(sizeof(VariableInfo)); - memset(pNewV, 0, sizeof(VariableInfo)); - pNewV->tok = tok; - pNewV->level = level(); - pNewV->pOldDefinition = pOldV; - token.mpVariableInfo = pNewV; - mStack.push_back(pNewV); - return pNewV; - } - - VariableInfo* addStructTag(tokenid_t tok) { - Token& token = (*mpTokenTable)[tok]; - VariableInfo* pOldS = token.mpStructInfo; - VariableInfo* pNewS = - (VariableInfo*) mpArena->alloc(sizeof(VariableInfo)); - memset(pNewS, 0, sizeof(VariableInfo)); - pNewS->tok = tok; - pNewS->level = level(); - pNewS->isStructTag = true; - pNewS->pOldDefinition = pOldS; - token.mpStructInfo = pNewS; - mStack.push_back(pNewS); - return pNewS; - } - - VariableInfo* add(Type* pType) { - VariableInfo* pVI = add(pType->id); - pVI->pType = pType; - return pVI; - } - - void forEach(bool (*fn)(VariableInfo*, void*), void* context) { - for (size_t i = 0; i < mStack.size(); i++) { - if (! fn(mStack[i], context)) { - break; - } - } - } - - private: - inline size_t level() { - return mLevelStack.size(); - } - - struct Mark { - Arena::Mark mArenaMark; - size_t mSymbolHead; - }; - - Arena* mpArena; - TokenTable* mpTokenTable; - Vector<VariableInfo*> mStack; - Vector<Mark> mLevelStack; - }; - - struct MacroState { - tokenid_t name; // Name of the current macro we are expanding - char* dptr; // point to macro text during macro playback - int dch; // Saves old value of ch during a macro playback - }; - -#define MACRO_NESTING_MAX 32 - MacroState macroState[MACRO_NESTING_MAX]; - int macroLevel; // -1 means not playing any macro. - - int ch; // Current input character, or EOF - tokenid_t tok; // token - intptr_t tokc; // token extra info - double tokd; // floating point constant value - int tokl; // token operator level - intptr_t rsym; // return symbol - Type* pReturnType; // type of the current function's return. - intptr_t loc; // local variable index - char* glo; // global variable index - String mTokenString; - bool mbSuppressMacroExpansion; - char* pGlobalBase; - ACCSymbolLookupFn mpSymbolLookupFn; - void* mpSymbolLookupContext; - - // Arena for the duration of the compile - Arena mGlobalArena; - // Arena for data that's only needed when compiling a single function - Arena mLocalArena; - - Arena* mpCurrentArena; - - TokenTable mTokenTable; - SymbolStack mGlobals; - SymbolStack mLocals; - - SymbolStack* mpCurrentSymbolStack; - - // Prebuilt types, makes things slightly faster. - Type* mkpInt; // int - Type* mkpShort; // short - Type* mkpChar; // char - Type* mkpVoid; // void - Type* mkpFloat; - Type* mkpDouble; - Type* mkpIntFn; - Type* mkpIntPtr; - Type* mkpCharPtr; - Type* mkpFloatPtr; - Type* mkpDoublePtr; - Type* mkpPtrIntFn; - - InputStream* file; - int mLineNumber; - bool mbBumpLine; - - ICodeBuf* pCodeBuf; - CodeGenerator* pGen; - - String mErrorBuf; - - String mPragmas; - int mPragmaStringCount; - int mCompileResult; - - static const int ALLOC_SIZE = 99999; - - static const int TOK_DUMMY = 1; - static const int TOK_NUM = 2; - static const int TOK_NUM_FLOAT = 3; - static const int TOK_NUM_DOUBLE = 4; - static const int TOK_OP_ASSIGNMENT = 5; - static const int TOK_OP_ARROW = 6; - - // 3..255 are character and/or operators - - // Keywords start at 0x100 and increase by 1 - // Order has to match string list in "internKeywords". - enum { - TOK_KEYWORD = TokenTable::TOKEN_BASE, - TOK_INT = TOK_KEYWORD, - TOK_CHAR, - TOK_VOID, - TOK_IF, - TOK_ELSE, - TOK_WHILE, - TOK_BREAK, - TOK_RETURN, - TOK_FOR, - TOK_AUTO, - TOK_CASE, - TOK_CONST, - TOK_CONTINUE, - TOK_DEFAULT, - TOK_DO, - TOK_DOUBLE, - TOK_ENUM, - TOK_EXTERN, - TOK_FLOAT, - TOK_GOTO, - TOK_LONG, - TOK_REGISTER, - TOK_SHORT, - TOK_SIGNED, - TOK_SIZEOF, - TOK_STATIC, - TOK_STRUCT, - TOK_SWITCH, - TOK_TYPEDEF, - TOK_UNION, - TOK_UNSIGNED, - TOK_VOLATILE, - TOK__BOOL, - TOK__COMPLEX, - TOK__IMAGINARY, - TOK_INLINE, - TOK_RESTRICT, - - // Symbols start after keywords - - TOK_SYMBOL, - TOK_PRAGMA = TOK_SYMBOL, - TOK_DEFINE, - TOK_LINE - }; - - static const int LOCAL = 0x200; - - /* tokens in string heap */ - static const int TAG_TOK = ' '; - - static const int OP_INCREMENT = 0; - static const int OP_DECREMENT = 1; - static const int OP_MUL = 2; - static const int OP_DIV = 3; - static const int OP_MOD = 4; - static const int OP_PLUS = 5; - static const int OP_MINUS = 6; - static const int OP_SHIFT_LEFT = 7; - static const int OP_SHIFT_RIGHT = 8; - static const int OP_LESS_EQUAL = 9; - static const int OP_GREATER_EQUAL = 10; - static const int OP_LESS = 11; - static const int OP_GREATER = 12; - static const int OP_EQUALS = 13; - static const int OP_NOT_EQUALS = 14; - static const int OP_LOGICAL_AND = 15; - static const int OP_LOGICAL_OR = 16; - static const int OP_BIT_AND = 17; - static const int OP_BIT_XOR = 18; - static const int OP_BIT_OR = 19; - static const int OP_BIT_NOT = 20; - static const int OP_LOGICAL_NOT = 21; - static const int OP_COUNT = 22; - - /* Operators are searched from front, the two-character operators appear - * before the single-character operators with the same first character. - * @ is used to pad out single-character operators. - */ - static const char* operatorChars; - static const char operatorLevel[]; - - /* Called when we detect an internal problem. Does nothing in production. - * - */ - void internalError() { - * (char*) 0 = 0; - } - - void assertImpl(bool isTrue, int line) { - if (!isTrue) { - LOGD("%d: assertion failed at line %s:%d.", mLineNumber, __FILE__, line); - internalError(); - } - } - - bool isSymbol(tokenid_t t) { - return t >= TOK_SYMBOL && - ((size_t) (t-TOK_SYMBOL)) < mTokenTable.size(); - } - - bool isSymbolOrKeyword(tokenid_t t) { - return t >= TOK_KEYWORD && - ((size_t) (t-TOK_KEYWORD)) < mTokenTable.size(); - } - - VariableInfo* VI(tokenid_t t) { - assert(isSymbol(t)); - VariableInfo* pV = mTokenTable[t].mpVariableInfo; - if (pV && pV->tok != t) { - internalError(); - } - return pV; - } - - inline bool isDefined(tokenid_t t) { - return t >= TOK_SYMBOL && VI(t) != 0; - } - - const char* nameof(tokenid_t t) { - assert(isSymbolOrKeyword(t)); - return mTokenTable[t].pText; - } - - void pdef(int t) { - mTokenString.append(t); - } - - void inp() { - // Close any totally empty macros. We leave them on the stack until now - // so that we know which macros are being expanded when checking if the - // last token in the macro is a macro that's already being expanded. - while (macroLevel >= 0 && macroState[macroLevel].dptr == NULL) { - macroLevel--; - } - if (macroLevel >= 0) { - ch = *macroState[macroLevel].dptr++; - if (ch == 0) { - ch = macroState[macroLevel].dch; - macroState[macroLevel].dptr = NULL; // This macro's done - } - } else { - if (mbBumpLine) { - mLineNumber++; - mbBumpLine = false; - } - ch = file->getChar(); - if (ch == '\n') { - mbBumpLine = true; - } - } -#if 0 - printf("ch='%c' 0x%x\n", ch, ch); -#endif - } - - int isid() { - return isalnum(ch) | (ch == '_'); - } - - int decodeHex(int c) { - if (isdigit(c)) { - c -= '0'; - } else if (c <= 'F') { - c = c - 'A' + 10; - } else { - c =c - 'a' + 10; - } - return c; - } - - /* read a character constant, advances ch to after end of constant */ - int getq() { - int val = ch; - if (ch == '\\') { - inp(); - if (isoctal(ch)) { - // 1 to 3 octal characters. - val = 0; - for(int i = 0; i < 3; i++) { - if (isoctal(ch)) { - val = (val << 3) + ch - '0'; - inp(); - } - } - return val; - } else if (ch == 'x' || ch == 'X') { - // N hex chars - inp(); - if (! isxdigit(ch)) { - error("'x' character escape requires at least one digit."); - } else { - val = 0; - while (isxdigit(ch)) { - val = (val << 4) + decodeHex(ch); - inp(); - } - } - } else { - int val = ch; - switch (ch) { - case 'a': - val = '\a'; - break; - case 'b': - val = '\b'; - break; - case 'f': - val = '\f'; - break; - case 'n': - val = '\n'; - break; - case 'r': - val = '\r'; - break; - case 't': - val = '\t'; - break; - case 'v': - val = '\v'; - break; - case '\\': - val = '\\'; - break; - case '\'': - val = '\''; - break; - case '"': - val = '"'; - break; - case '?': - val = '?'; - break; - default: - error("Undefined character escape %c", ch); - break; - } - inp(); - return val; - } - } else { - inp(); - } - return val; - } - - static bool isoctal(int ch) { - return ch >= '0' && ch <= '7'; - } - - bool acceptCh(int c) { - bool result = c == ch; - if (result) { - pdef(ch); - inp(); - } - return result; - } - - bool acceptDigitsCh() { - bool result = false; - while (isdigit(ch)) { - result = true; - pdef(ch); - inp(); - } - return result; - } - - void parseFloat() { - tok = TOK_NUM_DOUBLE; - // mTokenString already has the integral part of the number. - if(mTokenString.len() == 0) { - mTokenString.append('0'); - } - acceptCh('.'); - acceptDigitsCh(); - if (acceptCh('e') || acceptCh('E')) { - acceptCh('-') || acceptCh('+'); - acceptDigitsCh(); - } - if (ch == 'f' || ch == 'F') { - tok = TOK_NUM_FLOAT; - inp(); - } else if (ch == 'l' || ch == 'L') { - inp(); - error("Long floating point constants not supported."); - } - char* pText = mTokenString.getUnwrapped(); - char* pEnd = pText + strlen(pText); - char* pEndPtr = 0; - errno = 0; - if (tok == TOK_NUM_FLOAT) { - tokd = strtof(pText, &pEndPtr); - } else { - tokd = strtod(pText, &pEndPtr); - } - if (errno || pEndPtr != pEnd) { - error("Can't parse constant: %s", pText); - } - // fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd); - } - - bool currentlyBeingExpanded(tokenid_t id) { - for (int i = 0; i <= macroLevel; i++) { - if (macroState[macroLevel].name == id) { - return true; - } - } - return false; - } - - void next() { - int l, a; - - while (isspace(ch) | (ch == '#')) { - if (ch == '#') { - inp(); - next(); - if (tok == TOK_DEFINE) { - doDefine(); - } else if (tok == TOK_PRAGMA) { - doPragma(); - } else if (tok == TOK_LINE) { - doLine(); - } else { - error("Unsupported preprocessor directive \"%s\"", - mTokenString.getUnwrapped()); - } - } - inp(); - } - tokl = 0; - tok = ch; - /* encode identifiers & numbers */ - if (isdigit(ch) || ch == '.') { - // Start of a numeric constant. Could be integer, float, or - // double, won't know until we look further. - mTokenString.clear(); - pdef(ch); - inp(); - if (tok == '.' && !isdigit(ch)) { - goto done; - } - int base = 10; - if (tok == '0') { - if (ch == 'x' || ch == 'X') { - base = 16; - tok = TOK_NUM; - tokc = 0; - inp(); - while ( isxdigit(ch) ) { - tokc = (tokc << 4) + decodeHex(ch); - inp(); - } - } else if (isoctal(ch)){ - base = 8; - tok = TOK_NUM; - tokc = 0; - while ( isoctal(ch) ) { - tokc = (tokc << 3) + (ch - '0'); - inp(); - } - } - } else if (isdigit(tok)){ - acceptDigitsCh(); - } - if (base == 10) { - if (tok == '.' || ch == '.' || ch == 'e' || ch == 'E') { - parseFloat(); - } else { - // It's an integer constant - char* pText = mTokenString.getUnwrapped(); - char* pEnd = pText + strlen(pText); - char* pEndPtr = 0; - errno = 0; - tokc = strtol(pText, &pEndPtr, base); - if (errno || pEndPtr != pEnd) { - error("Can't parse constant: %s %d %d", pText, base, errno); - } - tok = TOK_NUM; - } - } - } else if (isid()) { - mTokenString.clear(); - while (isid()) { - pdef(ch); - inp(); - } - tok = mTokenTable.intern(mTokenString.getUnwrapped(), mTokenString.len()); - if (! mbSuppressMacroExpansion) { - // Is this a macro? - char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition; - if (pMacroDefinition && !currentlyBeingExpanded(tok)) { - // Yes, it is a macro -#if 0 - printf("Expanding macro %s -> %s", - mTokenString.getUnwrapped(), pMacroDefinition); -#endif - if (macroLevel >= MACRO_NESTING_MAX-1) { - error("Too many levels of macro recursion."); - } else { - macroLevel++; - macroState[macroLevel].name = tok; - macroState[macroLevel].dptr = pMacroDefinition; - macroState[macroLevel].dch = ch; - inp(); - next(); - } - } - } - } else { - inp(); - if (tok == '\'') { - tok = TOK_NUM; - tokc = getq(); - if (ch != '\'') { - error("Expected a ' character, got %c", ch); - } else { - inp(); - } - } else if ((tok == '/') & (ch == '*')) { - inp(); - while (ch && ch != EOF) { - while (ch != '*' && ch != EOF) - inp(); - inp(); - if (ch == '/') - ch = 0; - } - if (ch == EOF) { - error("End of file inside comment."); - } - inp(); - next(); - } else if ((tok == '/') & (ch == '/')) { - inp(); - while (ch && (ch != '\n') && (ch != EOF)) { - inp(); - } - inp(); - next(); - } else if ((tok == '-') & (ch == '>')) { - inp(); - tok = TOK_OP_ARROW; - } else { - const char* t = operatorChars; - int opIndex = 0; - while ((l = *t++) != 0) { - a = *t++; - tokl = operatorLevel[opIndex]; - tokc = opIndex; - if ((l == tok) & ((a == ch) | (a == '@'))) { -#if 0 - printf("%c%c -> tokl=%d tokc=0x%x\n", - l, a, tokl, tokc); -#endif - if (a == ch) { - inp(); - tok = TOK_DUMMY; /* dummy token for double tokens */ - } - /* check for op=, valid for * / % + - << >> & ^ | */ - if (ch == '=' && - ((tokl >= 1 && tokl <= 3) - || (tokl >=6 && tokl <= 8)) ) { - inp(); - tok = TOK_OP_ASSIGNMENT; - } - break; - } - opIndex++; - } - if (l == 0) { - tokl = 0; - tokc = 0; - } - } - } - - done: ; -#if 0 - { - String buf; - decodeToken(buf, tok, true); - fprintf(stderr, "%s\n", buf.getUnwrapped()); - } -#endif - } - - void doDefine() { - mbSuppressMacroExpansion = true; - next(); - mbSuppressMacroExpansion = false; - tokenid_t name = tok; - if (ch == '(') { - error("Defines with arguments not supported"); - return; - } - while (isspace(ch)) { - inp(); - } - String value; - bool appendToValue = true; - while (ch != '\n' && ch != EOF) { - // Check for '//' comments. - if (appendToValue && ch == '/') { - inp(); - if (ch == '/') { - appendToValue = false; - } else { - value.append('/'); - } - } - if (appendToValue && ch != EOF) { - value.append(ch); - } - inp(); - } - char* pDefn = (char*)mGlobalArena.alloc(value.len() + 1); - memcpy(pDefn, value.getUnwrapped(), value.len()); - pDefn[value.len()] = 0; - mTokenTable[name].mpMacroDefinition = pDefn; -#if 0 - { - String buf; - decodeToken(buf, name, true); - fprintf(stderr, "define %s = \"%s\"\n", buf.getUnwrapped(), pDefn); - } -#endif - } - - void doPragma() { - // # pragma name(val) - int state = 0; - while(ch != EOF && ch != '\n' && state < 10) { - switch(state) { - case 0: - if (isspace(ch)) { - inp(); - } else { - state++; - } - break; - case 1: - if (isalnum(ch)) { - mPragmas.append(ch); - inp(); - } else if (ch == '(') { - mPragmas.append(0); - inp(); - state++; - } else { - state = 11; - } - break; - case 2: - if (isalnum(ch)) { - mPragmas.append(ch); - inp(); - } else if (ch == ')') { - mPragmas.append(0); - inp(); - state = 10; - } else { - state = 11; - } - break; - } - } - if(state != 10) { - error("Unexpected pragma syntax"); - } - mPragmaStringCount += 2; - } - - void doLine() { - // # line number { "filename "} - next(); - if (tok != TOK_NUM) { - error("Expected a line-number"); - } else { - mLineNumber = tokc-1; // The end-of-line will increment it. - } - while(ch != EOF && ch != '\n') { - inp(); - } - } - - virtual void verror(const char* fmt, va_list ap) { - mErrorBuf.printf("%ld: ", mLineNumber); - mErrorBuf.vprintf(fmt, ap); - mErrorBuf.printf("\n"); - } - - void skip(intptr_t c) { - if (!accept(c)) { - error("'%c' expected", c); - } - } - - bool accept(intptr_t c) { - if (tok == c) { - next(); - return true; - } - return false; - } - - bool acceptStringLiteral() { - if (tok == '"') { - pGen->leaR0((int) glo, mkpCharPtr, ET_RVALUE); - // This while loop merges multiple adjacent string constants. - while (tok == '"') { - while (ch != '"' && ch != EOF) { - *allocGlobalSpace(1,1) = getq(); - } - if (ch != '"') { - error("Unterminated string constant."); - } - inp(); - next(); - } - /* Null terminate */ - *glo = 0; - /* align heap */ - allocGlobalSpace(1,(char*) (((intptr_t) glo + 4) & -4) - glo); - - return true; - } - return false; - } - - void linkGlobal(tokenid_t t, bool isFunction) { - VariableInfo* pVI = VI(t); - void* n = NULL; - if (mpSymbolLookupFn) { - n = mpSymbolLookupFn(mpSymbolLookupContext, nameof(t)); - } - if (pVI->pType == NULL) { - if (isFunction) { - pVI->pType = mkpIntFn; - } else { - pVI->pType = mkpInt; - } - } - pVI->pAddress = n; - } - - void unaryOrAssignment() { - unary(); - if (accept('=')) { - checkLVal(); - pGen->pushR0(); - expr(); - pGen->forceR0RVal(); - pGen->storeR0ToTOS(); - } else if (tok == TOK_OP_ASSIGNMENT) { - int t = tokc; - next(); - checkLVal(); - pGen->pushR0(); - pGen->forceR0RVal(); - pGen->pushR0(); - expr(); - pGen->forceR0RVal(); - pGen->genOp(t); - pGen->storeR0ToTOS(); - } - } - - /* Parse and evaluate a unary expression. - */ - void unary() { - tokenid_t t; - intptr_t a; - t = 0; - if (acceptStringLiteral()) { - // Nothing else to do. - } else { - int c = tokl; - a = tokc; - double ad = tokd; - t = tok; - next(); - if (t == TOK_NUM) { - pGen->li(a); - } else if (t == TOK_NUM_FLOAT) { - // Align to 4-byte boundary - glo = (char*) (((intptr_t) glo + 3) & -4); - * (float*) glo = (float) ad; - pGen->loadFloat((int) glo, mkpFloat); - glo += 4; - } else if (t == TOK_NUM_DOUBLE) { - // Align to 8-byte boundary - glo = (char*) (((intptr_t) glo + 7) & -8); - * (double*) glo = ad; - pGen->loadFloat((int) glo, mkpDouble); - glo += 8; - } else if (c == 2) { - /* -, +, !, ~ */ - unary(); - pGen->forceR0RVal(); - if (t == '!') - pGen->gUnaryCmp(a); - else if (t == '+') { - // ignore unary plus. - } else { - pGen->genUnaryOp(a); - } - } else if (c == 11) { - // pre increment / pre decrement - unary(); - doIncDec(a == OP_INCREMENT, 0); - } - else if (t == '(') { - // It's either a cast or an expression - Type* pCast = acceptCastTypeDeclaration(); - if (pCast) { - skip(')'); - unary(); - pGen->forceR0RVal(); - pGen->castR0(pCast); - } else { - commaExpr(); - skip(')'); - } - } else if (t == '*') { - /* This is a pointer dereference. - */ - unary(); - doPointer(); - } else if (t == '&') { - unary(); - doAddressOf(); - } else if (t == EOF ) { - error("Unexpected EOF."); - } else if (t == ';') { - error("Unexpected ';'"); - } else if (!checkSymbol(t)) { - // Don't have to do anything special here, the error - // message was printed by checkSymbol() above. - } else { - if (!isDefined(t)) { - mGlobals.add(t); - // printf("Adding new global function %s\n", nameof(t)); - } - VariableInfo* pVI = VI(t); - int n = (intptr_t) pVI->pAddress; - /* forward reference: try our lookup function */ - if (!n) { - linkGlobal(t, tok == '('); - n = (intptr_t) pVI->pAddress; - if (!n && tok != '(') { - error("Undeclared variable %s", nameof(t)); - } - } - if (tok != '(') { - /* variable or function name */ - if (!n) { - linkGlobal(t, false); - n = (intptr_t) pVI->pAddress; - if (!n) { - error("Undeclared variable %s", nameof(t)); - } - } - } - // load a variable - Type* pVal; - ExpressionType et; - if (pVI->pType->tag == TY_ARRAY) { - pVal = pVI->pType; - et = ET_RVALUE; - } else { - pVal = createPtrType(pVI->pType); - et = ET_LVALUE; - } - if (n) { - int tag = pVal->pHead->tag; - if (tag == TY_FUNC) { - et = ET_RVALUE; - } - pGen->leaR0(n, pVal, et); - } else { - pVI->pForward = (void*) pGen->leaForward( - (int) pVI->pForward, pVal); - } - } - } - - /* Now handle postfix operators */ - for(;;) { - if (tokl == 11) { - // post inc / post dec - doIncDec(tokc == OP_INCREMENT, true); - next(); - } else if (accept('[')) { - // Array reference - pGen->forceR0RVal(); - pGen->pushR0(); - commaExpr(); - pGen->forceR0RVal(); - pGen->genOp(OP_PLUS); - doPointer(); - skip(']'); - } else if (accept('.')) { - // struct element - pGen->forceR0RVal(); - Type* pStruct = pGen->getR0Type(); - if (pStruct->tag == TY_STRUCT) { - doStructMember(pStruct, true); - } else { - error("expected a struct value to the left of '.'"); - } - } else if (accept(TOK_OP_ARROW)) { - pGen->forceR0RVal(); - Type* pPtr = pGen->getR0Type(); - if (pPtr->tag == TY_POINTER && pPtr->pHead->tag == TY_STRUCT) { - pGen->loadR0FromR0(); - doStructMember(pPtr->pHead, false); - } else { - error("Expected a pointer to a struct to the left of '->'"); - } - } else if (accept('(')) { - /* function call */ - Type* pDecl = NULL; - VariableInfo* pVI = NULL; - Type* pFn = pGen->getR0Type(); - if (pFn->tag == TY_POINTER && pFn->pHead->tag == TY_FUNC) { - pDecl = pFn->pHead; - pGen->pushR0(); - Type* pArgList = pDecl->pTail; - bool varArgs = pArgList == NULL; - /* push args and invert order */ - a = pGen->beginFunctionCallArguments(); - int l = 0; - int argCount = 0; - while (tok != ')' && tok != EOF) { - if (! varArgs && !pArgList) { - error("Unexpected argument."); - } - expr(); - pGen->forceR0RVal(); - Type* pTargetType; - if (pArgList) { - pTargetType = pArgList->pHead; - pArgList = pArgList->pTail; - } else { - // This is a ... function, just pass arguments in their - // natural type. - pTargetType = pGen->getR0Type(); - if (pTargetType->tag == TY_FLOAT) { - pTargetType = mkpDouble; - } else if (pTargetType->tag == TY_ARRAY) { - // Pass arrays by pointer. - pTargetType = pTargetType->pTail; - } - } - if (pTargetType->tag == TY_VOID) { - error("Can't pass void value for argument %d", - argCount + 1); - } else { - l += pGen->storeR0ToArg(l, pTargetType); - } - if (accept(',')) { - // fine - } else if ( tok != ')') { - error("Expected ',' or ')'"); - } - argCount += 1; - } - if (! varArgs && pArgList) { - error("Expected more argument(s). Saw %d", argCount); - } - pGen->endFunctionCallArguments(pDecl, a, l); - skip(')'); - pGen->callIndirect(l, pDecl); - pGen->adjustStackAfterCall(pDecl, l, true); - } else { - error("Expected a function value to left of '('."); - } - } else { - break; - } - } - } - - void doStructMember(Type* pStruct, bool isDot) { - Type* pStructElement = lookupStructMember(pStruct, tok); - if (pStructElement) { - next(); - pGen->addStructOffsetR0(pStructElement->length, createPtrType(pStructElement->pHead)); - } else { - String buf; - decodeToken(buf, tok, true); - error("Expected a struct member to the right of '%s', got %s", - isDot ? "." : "->", buf.getUnwrapped()); - } - } - - void doIncDec(int isInc, int isPost) { - // R0 already has the lval - checkLVal(); - int lit = isInc ? 1 : -1; - pGen->pushR0(); - pGen->loadR0FromR0(); - int tag = pGen->getR0Type()->tag; - if (!(tag == TY_INT || tag == TY_SHORT || tag == TY_CHAR || - tag == TY_POINTER)) { - error("++/-- illegal for this type. %d", tag); - } - if (isPost) { - pGen->over(); - pGen->pushR0(); - pGen->li(lit); - pGen->genOp(OP_PLUS); - pGen->storeR0ToTOS(); - pGen->popR0(); - } else { - pGen->pushR0(); - pGen->li(lit); - pGen->genOp(OP_PLUS); - pGen->over(); - pGen->storeR0ToTOS(); - pGen->popR0(); - } - } - - void doPointer() { - pGen->forceR0RVal(); - Type* pR0Type = pGen->getR0Type(); - if (pR0Type->tag != TY_POINTER) { - error("Expected a pointer type."); - } else { - if (pR0Type->pHead->tag != TY_FUNC) { - pGen->setR0ExpressionType(ET_LVALUE); - } - } - } - - void doAddressOf() { - Type* pR0 = pGen->getR0Type(); - bool isFuncPtr = pR0->tag == TY_POINTER && pR0->pHead->tag == TY_FUNC; - if ((! isFuncPtr) && pGen->getR0ExpressionType() != ET_LVALUE) { - error("Expected an lvalue"); - } - Type* pR0Type = pGen->getR0Type(); - pGen->setR0ExpressionType(ET_RVALUE); - } - - /* Recursive descent parser for binary operations. - */ - void binaryOp(int level) { - intptr_t t, a; - t = 0; - if (level-- == 1) - unaryOrAssignment(); - else { - binaryOp(level); - a = 0; - while (level == tokl) { - t = tokc; - next(); - pGen->forceR0RVal(); - if (level > 8) { - a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */ - binaryOp(level); - } else { - pGen->pushR0(); - binaryOp(level); - // Check for syntax error. - if (pGen->getR0Type() == NULL) { - // We failed to parse a right-hand argument. - // Push a dummy value so we don't fail - pGen->li(0); - } - pGen->forceR0RVal(); - if ((level == 4) | (level == 5)) { - pGen->gcmp(t); - } else { - pGen->genOp(t); - } - } - } - /* && and || output code generation */ - if (a && level > 8) { - pGen->forceR0RVal(); - a = pGen->gtst(t == OP_LOGICAL_OR, a); - pGen->li(t != OP_LOGICAL_OR); - int b = pGen->gjmp(0); - pGen->gsym(a); - pGen->li(t == OP_LOGICAL_OR); - pGen->gsym(b); - } - } - } - - void commaExpr() { - for(;;) { - expr(); - if (!accept(',')) { - break; - } - } - } - - void expr() { - binaryOp(11); - } - - int test_expr() { - commaExpr(); - pGen->forceR0RVal(); - return pGen->gtst(0, 0); - } - - void block(intptr_t* breakLabel, intptr_t continueAddress, bool outermostFunctionBlock) { - intptr_t a, n, t; - - Type* pBaseType; - if ((pBaseType = acceptPrimitiveType(true))) { - /* declarations */ - localDeclarations(pBaseType); - } else if (tok == TOK_IF) { - next(); - skip('('); - a = test_expr(); - skip(')'); - block(breakLabel, continueAddress, false); - if (tok == TOK_ELSE) { - next(); - n = pGen->gjmp(0); /* jmp */ - pGen->gsym(a); - block(breakLabel, continueAddress, false); - pGen->gsym(n); /* patch else jmp */ - } else { - pGen->gsym(a); /* patch if test */ - } - } else if ((tok == TOK_WHILE) | (tok == TOK_FOR)) { - t = tok; - next(); - skip('('); - if (t == TOK_WHILE) { - n = pCodeBuf->getPC(); // top of loop, target of "next" iteration - a = test_expr(); - } else { - if (tok != ';') - commaExpr(); - skip(';'); - n = pCodeBuf->getPC(); - a = 0; - if (tok != ';') - a = test_expr(); - skip(';'); - if (tok != ')') { - t = pGen->gjmp(0); - commaExpr(); - pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); - pGen->gsym(t); - n = t + 4; - } - } - skip(')'); - block(&a, n, false); - pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); /* jmp */ - pGen->gsym(a); - } else if (tok == '{') { - if (! outermostFunctionBlock) { - mLocals.pushLevel(); - } - next(); - while (tok != '}' && tok != EOF) - block(breakLabel, continueAddress, false); - skip('}'); - if (! outermostFunctionBlock) { - mLocals.popLevel(); - } - } else { - if (accept(TOK_RETURN)) { - if (tok != ';') { - commaExpr(); - pGen->forceR0RVal(); - if (pReturnType->tag == TY_VOID) { - error("Must not return a value from a void function"); - } else { - pGen->convertR0(pReturnType); - } - } else { - if (pReturnType->tag != TY_VOID) { - error("Must specify a value here"); - } - } - rsym = pGen->gjmp(rsym); /* jmp */ - } else if (accept(TOK_BREAK)) { - if (breakLabel) { - *breakLabel = pGen->gjmp(*breakLabel); - } else { - error("break statement must be within a for, do, while, or switch statement"); - } - } else if (accept(TOK_CONTINUE)) { - if (continueAddress) { - pGen->gjmp(continueAddress - pCodeBuf->getPC() - pGen->jumpOffset()); - } else { - error("continue statement must be within a for, do, or while statement"); - } - } else if (tok != ';') - commaExpr(); - skip(';'); - } - } - - static bool typeEqual(Type* a, Type* b) { - if (a == b) { - return true; - } - if (a == NULL || b == NULL) { - return false; - } - TypeTag at = a->tag; - if (at != b->tag) { - return false; - } - if (at == TY_POINTER) { - return typeEqual(a->pHead, b->pHead); - } else if (at == TY_ARRAY) { - return a->length == b->length && typeEqual(a->pHead, b->pHead); - } else if (at == TY_FUNC || at == TY_PARAM) { - return typeEqual(a->pHead, b->pHead) - && typeEqual(a->pTail, b->pTail); - } else if (at == TY_STRUCT) { - return a->pHead == b->pHead; - } - return true; - } - - Type* createType(TypeTag tag, Type* pHead, Type* pTail) { - assert(tag >= TY_UNKNOWN && tag <= TY_PARAM); - Type* pType = (Type*) mpCurrentArena->alloc(sizeof(Type)); - memset(pType, 0, sizeof(*pType)); - pType->storageClass = SC_DEFAULT; - pType->tag = tag; - pType->pHead = pHead; - pType->pTail = pTail; - return pType; - } - - Type* createPtrType(Type* pType) { - return createType(TY_POINTER, pType, NULL); - } - - /** - * Try to print a type in declaration order - */ - void decodeType(String& buffer, Type* pType) { - buffer.clear(); - if (pType == NULL) { - buffer.appendCStr("null"); - return; - } - decodeTypeImp(buffer, pType); - } - - void decodeTypeImp(String& buffer, Type* pType) { - decodeTypeImpPrefix(buffer, pType); - decodeId(buffer, pType->id); - decodeTypeImpPostfix(buffer, pType); - } - - void decodeId(String& buffer, tokenid_t id) { - if (id) { - String temp; - decodeToken(temp, id, false); - buffer.append(temp); - } - } - - void decodeTypeImpPrefix(String& buffer, Type* pType) { - TypeTag tag = pType->tag; - - if ((tag >= TY_INT && tag <= TY_DOUBLE) || tag == TY_STRUCT) { - switch (tag) { - case TY_INT: - buffer.appendCStr("int"); - break; - case TY_SHORT: - buffer.appendCStr("short"); - break; - case TY_CHAR: - buffer.appendCStr("char"); - break; - case TY_VOID: - buffer.appendCStr("void"); - break; - case TY_FLOAT: - buffer.appendCStr("float"); - break; - case TY_DOUBLE: - buffer.appendCStr("double"); - break; - case TY_STRUCT: - { - bool isStruct = (pType->pHead->alignment & 0x80000000) != 0; - buffer.appendCStr(isStruct ? "struct" : "union"); - if (pType->pHead && pType->pHead->structTag) { - buffer.append(' '); - decodeId(buffer, pType->pHead->structTag); - } - } - break; - default: - break; - } - buffer.append(' '); - } - - switch (tag) { - case TY_INT: - break; - case TY_SHORT: - break; - case TY_CHAR: - break; - case TY_VOID: - break; - case TY_FLOAT: - break; - case TY_DOUBLE: - break; - case TY_POINTER: - decodeTypeImpPrefix(buffer, pType->pHead); - if(pType->pHead && pType->pHead->tag == TY_FUNC) { - buffer.append('('); - } - buffer.append('*'); - break; - case TY_ARRAY: - decodeTypeImpPrefix(buffer, pType->pHead); - break; - case TY_STRUCT: - break; - case TY_FUNC: - decodeTypeImp(buffer, pType->pHead); - break; - case TY_PARAM: - decodeTypeImp(buffer, pType->pHead); - break; - default: - String temp; - temp.printf("Unknown tag %d", pType->tag); - buffer.append(temp); - break; - } - } - - void decodeTypeImpPostfix(String& buffer, Type* pType) { - TypeTag tag = pType->tag; - - switch(tag) { - case TY_POINTER: - if(pType->pHead && pType->pHead->tag == TY_FUNC) { - buffer.append(')'); - } - decodeTypeImpPostfix(buffer, pType->pHead); - break; - case TY_ARRAY: - { - String temp; - temp.printf("[%d]", pType->length); - buffer.append(temp); - } - break; - case TY_STRUCT: - if (pType->pHead->length >= 0) { - buffer.appendCStr(" {"); - for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) { - decodeTypeImp(buffer, pArg->pHead); - buffer.appendCStr(";"); - } - buffer.append('}'); - } - break; - case TY_FUNC: - buffer.append('('); - for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) { - decodeTypeImp(buffer, pArg); - if (pArg->pTail) { - buffer.appendCStr(", "); - } - } - buffer.append(')'); - break; - default: - break; - } - } - - void printType(Type* pType) { - String buffer; - decodeType(buffer, pType); - fprintf(stderr, "%s\n", buffer.getUnwrapped()); - } - - void insertTypeSpecifier(Type** ppType, TypeTag tag) { - if (! *ppType) { - *ppType = createType(tag, NULL, NULL); - } else { - if ((*ppType)->tag != TY_UNKNOWN) { - error("Only one type specifier allowed."); - } else { - (*ppType)->tag = tag; - } - } - } - - void insertStorageClass(Type** ppType, StorageClass storageClass) { - if (! *ppType) { - *ppType = createType(TY_UNKNOWN, NULL, NULL); - } - if ((*ppType)->storageClass != SC_DEFAULT) { - error("Only one storage class allowed."); - } else { - (*ppType)->storageClass = storageClass; - } - } - - Type* acceptPrimitiveType(bool allowStorageClass) { - Type* pType = NULL; - for (bool keepGoing = true; keepGoing;) { - switch(tok) { - case TOK_AUTO: - insertStorageClass(&pType, SC_AUTO); - break; - case TOK_REGISTER: - insertStorageClass(&pType, SC_REGISTER); - break; - case TOK_STATIC: - insertStorageClass(&pType, SC_STATIC); - break; - case TOK_EXTERN: - insertStorageClass(&pType, SC_EXTERN); - break; - case TOK_TYPEDEF: - insertStorageClass(&pType, SC_TYPEDEF); - break; - case TOK_INT: - insertTypeSpecifier(&pType, TY_INT); - break; - case TOK_SHORT: - insertTypeSpecifier(&pType, TY_SHORT); - break; - case TOK_CHAR: - insertTypeSpecifier(&pType, TY_CHAR); - break; - case TOK_VOID: - insertTypeSpecifier(&pType, TY_VOID); - break; - case TOK_FLOAT: - insertTypeSpecifier(&pType, TY_FLOAT); - break; - case TOK_DOUBLE: - insertTypeSpecifier(&pType, TY_DOUBLE); - break; - case TOK_STRUCT: - case TOK_UNION: - { - insertTypeSpecifier(&pType, TY_STRUCT); - bool isStruct = (tok == TOK_STRUCT); - next(); - pType = acceptStruct(pType, isStruct); - keepGoing = false; - } - break; - default: - // Is it a typedef? - if (isSymbol(tok)) { - VariableInfo* pV = VI(tok); - if (pV && pV->pType->storageClass == SC_TYPEDEF) { - if (! pType) { - pType = createType(TY_UNKNOWN, NULL, NULL); - } - StorageClass storageClass = pType->storageClass; - *pType = *pV->pType; - pType->storageClass = storageClass; - } else { - keepGoing = false; - } - } else { - keepGoing = false; - } - } - if (keepGoing) { - next(); - } - } - if (pType) { - if (pType->tag == TY_UNKNOWN) { - pType->tag = TY_INT; - } - if (allowStorageClass) { - switch(pType->storageClass) { - case SC_AUTO: error("auto not supported."); break; - case SC_REGISTER: error("register not supported."); break; - case SC_STATIC: error("static not supported."); break; - case SC_EXTERN: error("extern not supported."); break; - default: break; - } - } else { - if (pType->storageClass != SC_DEFAULT) { - error("An explicit storage class is not allowed in this type declaration"); - } - } - } - return pType; - } - - Type* acceptStruct(Type* pStructType, bool isStruct) { - tokenid_t structTag = acceptSymbol(); - bool isDeclaration = accept('{'); - bool fail = false; - - if (structTag) { - Token* pToken = &mTokenTable[structTag]; - VariableInfo* pStructInfo = pToken->mpStructInfo; - bool needToDeclare = !pStructInfo; - if (pStructInfo) { - if (isDeclaration) { - if (mpCurrentSymbolStack->isStructTagDefinedAtCurrentLevel(structTag)) { - if (pStructInfo->pType->pHead->length == -1) { - // we're filling in a forward declaration. - needToDeclare = false; - } else { - error("A struct with the same name is already defined at this level."); - fail = true; - } - } else { - needToDeclare = true; - } - } - if (!fail) { - assert(pStructInfo->isStructTag); - pStructType->pHead = pStructInfo->pType; - pStructType->pTail = pStructType->pHead->pTail; - } - } - - if (needToDeclare) { - // This is a new struct name - pToken->mpStructInfo = mpCurrentSymbolStack->addStructTag(structTag); - StorageClass storageClass = pStructType->storageClass; - pStructType = createType(TY_STRUCT, NULL, NULL); - pStructType->structTag = structTag; - pStructType->pHead = pStructType; - pStructType->storageClass = storageClass; - if (! isDeclaration) { - // A forward declaration - pStructType->length = -1; - } - pToken->mpStructInfo->pType = pStructType; - } - } else { - // An anonymous struct - pStructType->pHead = pStructType; - } - - if (isDeclaration) { - size_t offset = 0; - size_t structSize = 0; - size_t structAlignment = 0; - Type** pParamHolder = & pStructType->pHead->pTail; - while (tok != '}' && tok != EOF) { - Type* pPrimitiveType = expectPrimitiveType(false); - if (pPrimitiveType) { - while (tok != ';' && tok != EOF) { - Type* pItem = acceptDeclaration(pPrimitiveType, true, false); - if (!pItem) { - break; - } - if (lookupStructMember(pStructType, pItem->id)) { - String buf; - decodeToken(buf, pItem->id, false); - error("Duplicate struct member %s", buf.getUnwrapped()); - } - Type* pStructElement = createType(TY_PARAM, pItem, NULL); - size_t alignment = pGen->alignmentOf(pItem); - if (alignment > structAlignment) { - structAlignment = alignment; - } - size_t alignmentMask = alignment - 1; - offset = (offset + alignmentMask) & ~alignmentMask; - pStructElement->length = offset; - size_t size = pGen->sizeOf(pItem); - if (isStruct) { - offset += size; - structSize = offset; - } else { - if (size >= structSize) { - structSize = size; - } - } - *pParamHolder = pStructElement; - pParamHolder = &pStructElement->pTail; - accept(','); - } - skip(';'); - } else { - // Some sort of syntax error, skip token and keep trying - next(); - } - } - if (!fail) { - pStructType->pHead->length = structSize; - pStructType->pHead->alignment = structAlignment | (isStruct << 31); - } - skip('}'); - } - if (fail) { - pStructType = NULL; - } - return pStructType; - } - - Type* lookupStructMember(Type* pStruct, tokenid_t memberId) { - for(Type* pStructElement = pStruct->pHead->pTail; pStructElement; pStructElement = pStructElement->pTail) { - if (pStructElement->pHead->id == memberId) { - return pStructElement; - } - } - return NULL; - } - - Type* acceptDeclaration(Type* pType, bool nameAllowed, bool nameRequired) { - tokenid_t declName = 0; - bool reportFailure = false; - StorageClass storageClass = pType->storageClass; - pType = acceptDecl2(pType, declName, nameAllowed, - nameRequired, reportFailure); - if (declName) { - // Clone the parent type so we can set a unique ID - Type* pOldType = pType; - pType = createType(pType->tag, pType->pHead, pType->pTail); - *pType = *pOldType; - pType->id = declName; - pType->storageClass = storageClass; - } else if (nameRequired) { - error("Expected a variable name"); - } -#if 0 - fprintf(stderr, "Parsed a declaration: "); - printType(pType); -#endif - if (reportFailure) { - return NULL; - } - return pType; - } - - Type* expectDeclaration(Type* pBaseType) { - bool nameRequired = pBaseType->tag != TY_STRUCT; - Type* pType = acceptDeclaration(pBaseType, true, nameRequired); - if (! pType) { - error("Expected a declaration"); - } - return pType; - } - - /* Used for accepting types that appear in casts */ - Type* acceptCastTypeDeclaration() { - Type* pType = acceptPrimitiveType(false); - if (pType) { - pType = acceptDeclaration(pType, false, false); - } - return pType; - } - - Type* expectCastTypeDeclaration() { - Type* pType = acceptCastTypeDeclaration(); - if (! pType) { - error("Expected a declaration"); - } - return pType; - } - - Type* acceptDecl2(Type* pType, tokenid_t& declName, - bool nameAllowed, bool nameRequired, - bool& reportFailure) { - while (accept('*')) { - pType = createType(TY_POINTER, pType, NULL); - } - pType = acceptDecl3(pType, declName, nameAllowed, nameRequired, - reportFailure); - return pType; - } - - Type* acceptDecl3(Type* pType, tokenid_t& declName, - bool nameAllowed, bool nameRequired, - bool& reportFailure) { - // direct-dcl : - // name - // (dcl) - // direct-dcl() - // direct-dcl[] - Type* pNewHead = NULL; - if (accept('(')) { - pNewHead = acceptDecl2(pNewHead, declName, nameAllowed, - nameRequired, reportFailure); - skip(')'); - } else if ((declName = acceptSymbol()) != 0) { - if (nameAllowed == false && declName) { - error("Symbol %s not allowed here", nameof(declName)); - reportFailure = true; - } - } else if (nameRequired && ! declName) { - String temp; - decodeToken(temp, tok, true); - error("Expected name. Got %s", temp.getUnwrapped()); - reportFailure = true; - } - for(;;) { - if (accept('(')) { - // Function declaration - Type* pTail = acceptArgs(nameAllowed); - pType = createType(TY_FUNC, pType, pTail); - skip(')'); - } if (accept('[')) { - if (tok != ']') { - if (tok != TOK_NUM || tokc <= 0) { - error("Expected positive integer constant"); - } else { - Type* pDecayType = createPtrType(pType); - pType = createType(TY_ARRAY, pType, pDecayType); - pType->length = tokc; - } - next(); - } - skip(']'); - } else { - break; - } - } - - if (pNewHead) { - Type* pA = pNewHead; - while (pA->pHead) { - pA = pA->pHead; - } - pA->pHead = pType; - pType = pNewHead; - } - return pType; - } - - Type* acceptArgs(bool nameAllowed) { - Type* pHead = NULL; - Type* pTail = NULL; - for(;;) { - Type* pBaseArg = acceptPrimitiveType(false); - if (pBaseArg) { - Type* pArg = acceptDeclaration(pBaseArg, nameAllowed, false); - if (pArg) { - Type* pParam = createType(TY_PARAM, pArg, NULL); - if (!pHead) { - pHead = pParam; - pTail = pParam; - } else { - pTail->pTail = pParam; - pTail = pParam; - } - } - } - if (! accept(',')) { - break; - } - } - return pHead; - } - - Type* expectPrimitiveType(bool allowStorageClass) { - Type* pType = acceptPrimitiveType(allowStorageClass); - if (!pType) { - String buf; - decodeToken(buf, tok, true); - error("Expected a type, got %s", buf.getUnwrapped()); - } - return pType; - } - - void checkLVal() { - if (pGen->getR0ExpressionType() != ET_LVALUE) { - error("Expected an lvalue"); - } - } - - void addGlobalSymbol(Type* pDecl) { - tokenid_t t = pDecl->id; - VariableInfo* pVI = VI(t); - if(pVI && pVI->pAddress) { - reportDuplicate(t); - } - mGlobals.add(pDecl); - } - - void reportDuplicate(tokenid_t t) { - error("Duplicate definition of %s", nameof(t)); - } - - void addLocalSymbol(Type* pDecl) { - tokenid_t t = pDecl->id; - if (mLocals.isDefinedAtCurrentLevel(t)) { - reportDuplicate(t); - } - mLocals.add(pDecl); - } - - bool checkUndeclaredStruct(Type* pBaseType) { - if (pBaseType->tag == TY_STRUCT && pBaseType->length < 0) { - String temp; - decodeToken(temp, pBaseType->structTag, false); - error("Undeclared struct %s", temp.getUnwrapped()); - return true; - } - return false; - } - - void localDeclarations(Type* pBaseType) { - intptr_t a; - - while (pBaseType) { - while (tok != ';' && tok != EOF) { - Type* pDecl = expectDeclaration(pBaseType); - if (!pDecl) { - break; - } - if (!pDecl->id) { - break; - } - if (checkUndeclaredStruct(pDecl)) { - break; - } - addLocalSymbol(pDecl); - if (pDecl->tag == TY_FUNC) { - if (tok == '{') { - error("Nested functions are not allowed. Did you forget a '}' ?"); - break; - } - // Else it's a forward declaration of a function. - } else if (pDecl->storageClass != SC_TYPEDEF) { - int variableAddress = 0; - size_t alignment = pGen->alignmentOf(pDecl); - assert(alignment > 0); - size_t alignmentMask = ~ (alignment - 1); - size_t sizeOf = pGen->sizeOf(pDecl); - assert(sizeOf > 0); - loc = (loc + alignment - 1) & alignmentMask; - size_t alignedSize = (sizeOf + alignment - 1) & alignmentMask; - loc = loc + alignedSize; - variableAddress = -loc; - VI(pDecl->id)->pAddress = (void*) variableAddress; - if (accept('=')) { - /* assignment */ - pGen->leaR0(variableAddress, createPtrType(pDecl), ET_LVALUE); - pGen->pushR0(); - expr(); - pGen->forceR0RVal(); - pGen->storeR0ToTOS(); - } - } - if (tok == ',') - next(); - } - skip(';'); - pBaseType = acceptPrimitiveType(true); - } - } - - bool checkSymbol() { - return checkSymbol(tok); - } - - void decodeToken(String& buffer, tokenid_t token, bool quote) { - if (token == EOF ) { - buffer.printf("EOF"); - } else if (token == TOK_NUM) { - buffer.printf("numeric constant %d(0x%x)", tokc, tokc); - } else if (token == TOK_NUM_FLOAT) { - buffer.printf("numeric constant float %g", tokd); - } else if (token == TOK_NUM_DOUBLE) { - buffer.printf("numeric constant double %g", tokd); - } else if (token >= 0 && token < 256) { - if (token < 32) { - buffer.printf("'\\x%02x'", token); - } else { - buffer.printf("'%c'", token); - } - } else { - if (quote) { - if (token >= TOK_KEYWORD && token < TOK_SYMBOL) { - buffer.printf("keyword \"%s\"", nameof(token)); - } else { - buffer.printf("symbol \"%s\"", nameof(token)); - } - } else { - buffer.printf("%s", nameof(token)); - } - } - } - - void printToken(tokenid_t token) { - String buffer; - decodeToken(buffer, token, true); - fprintf(stderr, "%s\n", buffer.getUnwrapped()); - } - - bool checkSymbol(tokenid_t token) { - bool result = token >= TOK_SYMBOL; - if (!result) { - String temp; - decodeToken(temp, token, true); - error("Expected symbol. Got %s", temp.getUnwrapped()); - } - return result; - } - - tokenid_t acceptSymbol() { - tokenid_t result = 0; - if (tok >= TOK_SYMBOL) { - result = tok; - next(); - } - return result; - } - - void globalDeclarations() { - mpCurrentSymbolStack = &mGlobals; - while (tok != EOF) { - Type* pBaseType = expectPrimitiveType(true); - if (!pBaseType) { - break; - } - Type* pDecl = expectDeclaration(pBaseType); - if (!pDecl) { - break; - } - if (!pDecl->id) { - skip(';'); - continue; - } - - if (checkUndeclaredStruct(pDecl)) { - skip(';'); - continue; - } - if (! isDefined(pDecl->id)) { - addGlobalSymbol(pDecl); - } - VariableInfo* name = VI(pDecl->id); - if (name && name->pAddress) { - error("Already defined global %s", nameof(pDecl->id)); - } - if (pDecl->tag < TY_FUNC) { - // it's a variable declaration - for(;;) { - if (pDecl->storageClass == SC_TYPEDEF) { - // Do not allocate storage. - } else { - if (name && !name->pAddress) { - name->pAddress = (int*) allocGlobalSpace( - pGen->alignmentOf(name->pType), - pGen->sizeOf(name->pType)); - } - if (accept('=')) { - if (tok == TOK_NUM) { - if (name) { - * (int*) name->pAddress = tokc; - } - next(); - } else { - error("Expected an integer constant"); - } - } - } - if (!accept(',')) { - break; - } - pDecl = expectDeclaration(pBaseType); - if (!pDecl) { - break; - } - if (! isDefined(pDecl->id)) { - addGlobalSymbol(pDecl); - } - name = VI(pDecl->id); - } - skip(';'); - } else { - // Function declaration - if (accept(';')) { - // forward declaration. - } else if (tok != '{') { - error("expected '{'"); - } else { - mpCurrentArena = &mLocalArena; - mpCurrentSymbolStack = &mLocals; - if (name) { - /* patch forward references */ - pGen->resolveForward((int) name->pForward); - /* put function address */ - name->pAddress = (void*) pCodeBuf->getPC(); - } - // Calculate stack offsets for parameters - mLocals.pushLevel(); - intptr_t a = 8; - int argCount = 0; - for (Type* pP = pDecl->pTail; pP; pP = pP->pTail) { - Type* pArg = pP->pHead; - if (pArg->id) { - addLocalSymbol(pArg); - } - /* read param name and compute offset */ - Type* pPassingType = passingType(pArg); - size_t alignment = pGen->alignmentOf(pPassingType); - a = (a + alignment - 1) & ~ (alignment-1); - if (pArg->id) { - VI(pArg->id)->pAddress = (void*) a; - } - a = a + pGen->sizeOf(pPassingType); - argCount++; - } - rsym = loc = 0; - pReturnType = pDecl->pHead; - a = pGen->functionEntry(pDecl); - block(0, 0, true); - pGen->gsym(rsym); - pGen->functionExit(pDecl, a, loc); - mLocals.popLevel(); - mpCurrentArena = &mGlobalArena; - mpCurrentSymbolStack = &mGlobals; - } - } - } - } - - Type* passingType(Type* pType) { - switch (pType->tag) { - case TY_CHAR: - case TY_SHORT: - return mkpInt; - default: - return pType; - } - } - - char* allocGlobalSpace(size_t alignment, size_t bytes) { - size_t base = (((size_t) glo) + alignment - 1) & ~(alignment-1); - size_t end = base + bytes; - if ((end - (size_t) pGlobalBase) > (size_t) ALLOC_SIZE) { - error("Global space exhausted"); - assert(false); - return NULL; - } - char* result = (char*) base; - glo = (char*) end; - return result; - } - - void cleanup() { - if (pGlobalBase != 0) { - free(pGlobalBase); - pGlobalBase = 0; - } - if (pGen) { - delete pGen; - pGen = 0; - } - if (pCodeBuf) { - delete pCodeBuf; - pCodeBuf = 0; - } - if (file) { - delete file; - file = 0; - } - } - - // One-time initialization, when class is constructed. - void init() { - mpSymbolLookupFn = 0; - mpSymbolLookupContext = 0; - } - - void clear() { - tok = 0; - tokc = 0; - tokl = 0; - ch = 0; - rsym = 0; - loc = 0; - glo = 0; - macroLevel = -1; - file = 0; - pGlobalBase = 0; - pCodeBuf = 0; - pGen = 0; - mPragmaStringCount = 0; - mCompileResult = 0; - mLineNumber = 1; - mbBumpLine = false; - mbSuppressMacroExpansion = false; - } - - void setArchitecture(const char* architecture) { - delete pGen; - pGen = 0; - - delete pCodeBuf; - pCodeBuf = new CodeBuf(); - - if (architecture != NULL) { -#ifdef PROVIDE_ARM_CODEGEN - if (! pGen && strcmp(architecture, "arm") == 0) { - pGen = new ARMCodeGenerator(); - pCodeBuf = new ARMCodeBuf(pCodeBuf); - } -#endif -#ifdef PROVIDE_X86_CODEGEN - if (! pGen && strcmp(architecture, "x86") == 0) { - pGen = new X86CodeGenerator(); - } -#endif - if (!pGen ) { - error("Unknown architecture %s\n", architecture); - } - } - - if (pGen == NULL) { -#if defined(DEFAULT_ARM_CODEGEN) - pGen = new ARMCodeGenerator(); - pCodeBuf = new ARMCodeBuf(pCodeBuf); -#elif defined(DEFAULT_X86_CODEGEN) - pGen = new X86CodeGenerator(); -#endif - } - if (pGen == NULL) { - error("No code generator defined."); - } else { - pGen->setErrorSink(this); - pGen->setTypes(mkpInt); - } - } - -public: - struct args { - args() { - architecture = 0; - } - const char* architecture; - }; - - Compiler() { - init(); - clear(); - } - - ~Compiler() { - cleanup(); - } - - void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) { - mpSymbolLookupFn = pFn; - mpSymbolLookupContext = pContext; - } - - int compile(const char* text, size_t textLength) { - int result; - - mpCurrentArena = &mGlobalArena; - createPrimitiveTypes(); - cleanup(); - clear(); - mTokenTable.setArena(&mGlobalArena); - mGlobals.setArena(&mGlobalArena); - mGlobals.setTokenTable(&mTokenTable); - mLocals.setArena(&mLocalArena); - mLocals.setTokenTable(&mTokenTable); - - internKeywords(); - setArchitecture(NULL); - if (!pGen) { - return -1; - } -#ifdef PROVIDE_TRACE_CODEGEN - pGen = new TraceCodeGenerator(pGen); -#endif - pGen->setErrorSink(this); - - if (pCodeBuf) { - pCodeBuf->init(ALLOC_SIZE); - } - pGen->init(pCodeBuf); - file = new TextInputStream(text, textLength); - pGlobalBase = (char*) calloc(1, ALLOC_SIZE); - glo = pGlobalBase; - inp(); - next(); - globalDeclarations(); - checkForUndefinedForwardReferences(); - result = pGen->finishCompile(); - if (result == 0) { - if (mErrorBuf.len()) { - result = -2; - } - } - mCompileResult = result; - return result; - } - - void createPrimitiveTypes() { - mkpInt = createType(TY_INT, NULL, NULL); - mkpShort = createType(TY_SHORT, NULL, NULL); - mkpChar = createType(TY_CHAR, NULL, NULL); - mkpVoid = createType(TY_VOID, NULL, NULL); - mkpFloat = createType(TY_FLOAT, NULL, NULL); - mkpDouble = createType(TY_DOUBLE, NULL, NULL); - mkpIntFn = createType(TY_FUNC, mkpInt, NULL); - mkpIntPtr = createPtrType(mkpInt); - mkpCharPtr = createPtrType(mkpChar); - mkpFloatPtr = createPtrType(mkpFloat); - mkpDoublePtr = createPtrType(mkpDouble); - mkpPtrIntFn = createPtrType(mkpIntFn); - } - - void checkForUndefinedForwardReferences() { - mGlobals.forEach(static_ufrcFn, this); - } - - static bool static_ufrcFn(VariableInfo* value, void* context) { - Compiler* pCompiler = (Compiler*) context; - return pCompiler->undefinedForwardReferenceCheck(value); - } - - bool undefinedForwardReferenceCheck(VariableInfo* value) { - if (!value->pAddress && value->pForward) { - error("Undefined forward reference: %s", - mTokenTable[value->tok].pText); - } - return true; - } - - /* Look through the symbol table to find a symbol. - * If found, return its value. - */ - void* lookup(const char* name) { - if (mCompileResult == 0) { - tokenid_t tok = mTokenTable.intern(name, strlen(name)); - VariableInfo* pVariableInfo = VI(tok); - if (pVariableInfo) { - return pVariableInfo->pAddress; - } - } - return NULL; - } - - void getPragmas(ACCsizei* actualStringCount, - ACCsizei maxStringCount, ACCchar** strings) { - int stringCount = mPragmaStringCount; - if (actualStringCount) { - *actualStringCount = stringCount; - } - if (stringCount > maxStringCount) { - stringCount = maxStringCount; - } - if (strings) { - char* pPragmas = mPragmas.getUnwrapped(); - while (stringCount-- > 0) { - *strings++ = pPragmas; - pPragmas += strlen(pPragmas) + 1; - } - } - } - - void getProgramBinary(ACCvoid** base, ACCsizei* length) { - *base = pCodeBuf->getBase(); - *length = (ACCsizei) pCodeBuf->getSize(); - } - - char* getErrorMessage() { - return mErrorBuf.getUnwrapped(); - } -}; - -const char* Compiler::operatorChars = - "++--*@/@%@+@-@<<>><=>=<@>@==!=&&||&@^@|@~@!@"; - -const char Compiler::operatorLevel[] = - {11, 11, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, - 5, 5, /* ==, != */ - 9, 10, /* &&, || */ - 6, 7, 8, /* & ^ | */ - 2, 2 /* ~ ! */ - }; - -#ifdef PROVIDE_X86_CODEGEN -const int Compiler::X86CodeGenerator::operatorHelper[] = { - 0x1, // ++ - 0xff, // -- - 0xc1af0f, // * - 0xf9f79991, // / - 0xf9f79991, // % (With manual assist to swap results) - 0xc801, // + - 0xd8f7c829, // - - 0xe0d391, // << - 0xf8d391, // >> - 0xe, // <= - 0xd, // >= - 0xc, // < - 0xf, // > - 0x4, // == - 0x5, // != - 0x0, // && - 0x1, // || - 0xc821, // & - 0xc831, // ^ - 0xc809, // | - 0xd0f7, // ~ - 0x4 // ! -}; -#endif - -struct ACCscript { - ACCscript() { - text = 0; - textLength = 0; - accError = ACC_NO_ERROR; - } - - ~ACCscript() { - delete text; - } - - void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) { - compiler.registerSymbolCallback(pFn, pContext); - } - - void setError(ACCenum error) { - if (accError == ACC_NO_ERROR && error != ACC_NO_ERROR) { - accError = error; - } - } - - ACCenum getError() { - ACCenum result = accError; - accError = ACC_NO_ERROR; - return result; - } - - Compiler compiler; - char* text; - int textLength; - ACCenum accError; -}; - - -extern "C" -ACCscript* accCreateScript() { - return new ACCscript(); -} - -extern "C" -ACCenum accGetError( ACCscript* script ) { - return script->getError(); -} - -extern "C" -void accDeleteScript(ACCscript* script) { - delete script; -} - -extern "C" -void accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn, - ACCvoid* pContext) { - script->registerSymbolCallback(pFn, pContext); -} - -extern "C" -void accScriptSource(ACCscript* script, - ACCsizei count, - const ACCchar ** string, - const ACCint * length) { - int totalLength = 0; - for(int i = 0; i < count; i++) { - int len = -1; - const ACCchar* s = string[i]; - if (length) { - len = length[i]; - } - if (len < 0) { - len = strlen(s); - } - totalLength += len; - } - delete script->text; - char* text = new char[totalLength + 1]; - script->text = text; - script->textLength = totalLength; - char* dest = text; - for(int i = 0; i < count; i++) { - int len = -1; - const ACCchar* s = string[i]; - if (length) { - len = length[i]; - } - if (len < 0) { - len = strlen(s); - } - memcpy(dest, s, len); - dest += len; - } - text[totalLength] = '\0'; - -#ifdef DEBUG_SAVE_INPUT_TO_FILE - LOGD("Saving input to file..."); - int counter; - char path[PATH_MAX]; - for (counter = 0; counter < 4096; counter++) { - sprintf(path, DEBUG_DUMP_PATTERN, counter); - if(access(path, F_OK) != 0) { - break; - } - } - if (counter < 4096) { - LOGD("Saving input to file %s", path); - FILE* fd = fopen(path, "w"); - if (fd) { - fwrite(text, totalLength, 1, fd); - fclose(fd); - LOGD("Saved input to file %s", path); - } else { - LOGD("Could not save. errno: %d", errno); - } - } -#endif -} - -extern "C" -void accCompileScript(ACCscript* script) { - int result = script->compiler.compile(script->text, script->textLength); - if (result) { - script->setError(ACC_INVALID_OPERATION); - } -} - -extern "C" -void accGetScriptiv(ACCscript* script, - ACCenum pname, - ACCint * params) { - switch (pname) { - case ACC_INFO_LOG_LENGTH: - *params = 0; - break; - } -} - -extern "C" -void accGetScriptInfoLog(ACCscript* script, - ACCsizei maxLength, - ACCsizei * length, - ACCchar * infoLog) { - char* message = script->compiler.getErrorMessage(); - int messageLength = strlen(message) + 1; - if (length) { - *length = messageLength; - } - if (infoLog && maxLength > 0) { - int trimmedLength = maxLength < messageLength ? - maxLength : messageLength; - memcpy(infoLog, message, trimmedLength); - infoLog[trimmedLength] = 0; - } -} - -extern "C" -void accGetScriptLabel(ACCscript* script, const ACCchar * name, - ACCvoid ** address) { - void* value = script->compiler.lookup(name); - if (value) { - *address = value; - } else { - script->setError(ACC_INVALID_VALUE); - } -} - -extern "C" -void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount, - ACCsizei maxStringCount, ACCchar** strings){ - script->compiler.getPragmas(actualStringCount, maxStringCount, strings); -} - -extern "C" -void accGetProgramBinary(ACCscript* script, - ACCvoid** base, ACCsizei* length) { - script->compiler.getProgramBinary(base, length); -} - - -} // namespace acc - diff --git a/libacc/tests/.gitignore b/libacc/tests/.gitignore deleted file mode 100644 index a26b298..0000000 --- a/libacc/tests/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -test-acc -*.out diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk deleted file mode 100644 index 6ddfa74..0000000 --- a/libacc/tests/Android.mk +++ /dev/null @@ -1,75 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -# Executable for host -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE:= acc - -LOCAL_SRC_FILES:= \ - main.cpp - -LOCAL_STATIC_LIBRARIES := \ - libacc \ - libcutils - -LOCAL_LDLIBS := -ldl - - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_HOST_EXECUTABLE) - -# Executable for target -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE:= acc - -LOCAL_SRC_FILES:= \ - main.cpp \ - disassem.cpp - -LOCAL_SHARED_LIBRARIES := \ - libacc \ - libdl - -LOCAL_CFLAGS := -O0 -g - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_EXECUTABLE) - -# Runtime tests for host -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE:= accRuntimeTest - -LOCAL_SRC_FILES:= \ - runtimeTest.cpp - -LOCAL_STATIC_LIBRARIES := \ - libacc \ - libcutils - -LOCAL_LDLIBS := -ldl - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_HOST_EXECUTABLE) - -# Runtime tests for target -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE:= accRuntimeTest - -LOCAL_SRC_FILES:= \ - runtimeTest.cpp - -LOCAL_SHARED_LIBRARIES := \ - libacc \ - libdl - -LOCAL_CFLAGS := -O0 -g - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_EXECUTABLE) diff --git a/libacc/tests/accarm b/libacc/tests/accarm deleted file mode 100755 index 6b1bf66..0000000 --- a/libacc/tests/accarm +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/python -# -# Run a test on the ARM version of acc. - -import unittest -import subprocess -import os -import sys - -def compile(args): - proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE) - result = proc.communicate() - return result - -def runCmd(args): - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - result = proc.communicate() - return result[0].strip() - -def uname(): - return runCmd(["uname"]) - -def unameM(): - return runCmd(["uname", "-m"]) - -def which(item): - return runCmd(["which", item]) - -def adb(args): - return runCmd(["adb"] + args) - -def setupArm(file): - print "Setting up arm" - adb(["remount"]) - adb(["shell", "rm", "/system/bin/acc"]) - adb(["shell", "mkdir", "/system/bin/accdata"]) - adb(["shell", "mkdir", "/system/bin/accdata/data"]) - - remoteFileName = os.path.join("/system/bin/accdata", file) - adb(["push", file, remoteFileName]) - - # Copy over compiler - adb(["sync"]) - return remoteFileName - -def compileArm(args): - remoteArgs = [] - fileName = "" - for arg in sys.argv[1:]: - if arg.startswith('-'): - remoteArgs.append(arg) - else: - fileName = arg - - remoteFileName = setupArm(fileName) - remoteArgs.append(remoteFileName) - remoteCmdLine = ["adb", "shell", "/system/bin/acc"] + remoteArgs - proc = subprocess.Popen(remoteCmdLine, stdout=subprocess.PIPE) - result = proc.communicate() - return result[0].replace("\r","") - - -def main(): - print compileArm(sys.argv[1:]) - -if __name__ == '__main__': - main() - - diff --git a/libacc/tests/armreg.h b/libacc/tests/armreg.h deleted file mode 100644 index fde81ba..0000000 --- a/libacc/tests/armreg.h +++ /dev/null @@ -1,300 +0,0 @@ -/* $NetBSD: armreg.h,v 1.28 2003/10/31 16:30:15 scw Exp $ */ - -/*- - * Copyright (c) 1998, 2001 Ben Harris - * Copyright (c) 1994-1996 Mark Brinicombe. - * Copyright (c) 1994 Brini. - * All rights reserved. - * - * This code is derived from software written for Brini by Mark Brinicombe - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Brini. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: /repoman/r/ncvs/src/sys/arm/include/armreg.h,v 1.3 2005/11/21 19:06:25 cognet Exp $ - */ - -#ifndef MACHINE_ARMREG_H -#define MACHINE_ARMREG_H -#define INSN_SIZE 4 -#define INSN_COND_MASK 0xf0000000 /* Condition mask */ -#define PSR_MODE 0x0000001f /* mode mask */ -#define PSR_USR26_MODE 0x00000000 -#define PSR_FIQ26_MODE 0x00000001 -#define PSR_IRQ26_MODE 0x00000002 -#define PSR_SVC26_MODE 0x00000003 -#define PSR_USR32_MODE 0x00000010 -#define PSR_FIQ32_MODE 0x00000011 -#define PSR_IRQ32_MODE 0x00000012 -#define PSR_SVC32_MODE 0x00000013 -#define PSR_ABT32_MODE 0x00000017 -#define PSR_UND32_MODE 0x0000001b -#define PSR_SYS32_MODE 0x0000001f -#define PSR_32_MODE 0x00000010 -#define PSR_FLAGS 0xf0000000 /* flags */ - -#define PSR_C_bit (1 << 29) /* carry */ - -/* The high-order byte is always the implementor */ -#define CPU_ID_IMPLEMENTOR_MASK 0xff000000 -#define CPU_ID_ARM_LTD 0x41000000 /* 'A' */ -#define CPU_ID_DEC 0x44000000 /* 'D' */ -#define CPU_ID_INTEL 0x69000000 /* 'i' */ -#define CPU_ID_TI 0x54000000 /* 'T' */ - -/* How to decide what format the CPUID is in. */ -#define CPU_ID_ISOLD(x) (((x) & 0x0000f000) == 0x00000000) -#define CPU_ID_IS7(x) (((x) & 0x0000f000) == 0x00007000) -#define CPU_ID_ISNEW(x) (!CPU_ID_ISOLD(x) && !CPU_ID_IS7(x)) - -/* On ARM3 and ARM6, this byte holds the foundry ID. */ -#define CPU_ID_FOUNDRY_MASK 0x00ff0000 -#define CPU_ID_FOUNDRY_VLSI 0x00560000 - -/* On ARM7 it holds the architecture and variant (sub-model) */ -#define CPU_ID_7ARCH_MASK 0x00800000 -#define CPU_ID_7ARCH_V3 0x00000000 -#define CPU_ID_7ARCH_V4T 0x00800000 -#define CPU_ID_7VARIANT_MASK 0x007f0000 - -/* On more recent ARMs, it does the same, but in a different format */ -#define CPU_ID_ARCH_MASK 0x000f0000 -#define CPU_ID_ARCH_V3 0x00000000 -#define CPU_ID_ARCH_V4 0x00010000 -#define CPU_ID_ARCH_V4T 0x00020000 -#define CPU_ID_ARCH_V5 0x00030000 -#define CPU_ID_ARCH_V5T 0x00040000 -#define CPU_ID_ARCH_V5TE 0x00050000 -#define CPU_ID_VARIANT_MASK 0x00f00000 - -/* Next three nybbles are part number */ -#define CPU_ID_PARTNO_MASK 0x0000fff0 - -/* Intel XScale has sub fields in part number */ -#define CPU_ID_XSCALE_COREGEN_MASK 0x0000e000 /* core generation */ -#define CPU_ID_XSCALE_COREREV_MASK 0x00001c00 /* core revision */ -#define CPU_ID_XSCALE_PRODUCT_MASK 0x000003f0 /* product number */ - -/* And finally, the revision number. */ -#define CPU_ID_REVISION_MASK 0x0000000f - -/* Individual CPUs are probably best IDed by everything but the revision. */ -#define CPU_ID_CPU_MASK 0xfffffff0 - -/* Fake CPU IDs for ARMs without CP15 */ -#define CPU_ID_ARM2 0x41560200 -#define CPU_ID_ARM250 0x41560250 - -/* Pre-ARM7 CPUs -- [15:12] == 0 */ -#define CPU_ID_ARM3 0x41560300 -#define CPU_ID_ARM600 0x41560600 -#define CPU_ID_ARM610 0x41560610 -#define CPU_ID_ARM620 0x41560620 - -/* ARM7 CPUs -- [15:12] == 7 */ -#define CPU_ID_ARM700 0x41007000 /* XXX This is a guess. */ -#define CPU_ID_ARM710 0x41007100 -#define CPU_ID_ARM7500 0x41027100 /* XXX This is a guess. */ -#define CPU_ID_ARM710A 0x41047100 /* inc ARM7100 */ -#define CPU_ID_ARM7500FE 0x41077100 -#define CPU_ID_ARM710T 0x41807100 -#define CPU_ID_ARM720T 0x41807200 -#define CPU_ID_ARM740T8K 0x41807400 /* XXX no MMU, 8KB cache */ -#define CPU_ID_ARM740T4K 0x41817400 /* XXX no MMU, 4KB cache */ - -/* Post-ARM7 CPUs */ -#define CPU_ID_ARM810 0x41018100 -#define CPU_ID_ARM920T 0x41129200 -#define CPU_ID_ARM920T_ALT 0x41009200 -#define CPU_ID_ARM922T 0x41029220 -#define CPU_ID_ARM940T 0x41029400 /* XXX no MMU */ -#define CPU_ID_ARM946ES 0x41049460 /* XXX no MMU */ -#define CPU_ID_ARM966ES 0x41049660 /* XXX no MMU */ -#define CPU_ID_ARM966ESR1 0x41059660 /* XXX no MMU */ -#define CPU_ID_ARM1020E 0x4115a200 /* (AKA arm10 rev 1) */ -#define CPU_ID_ARM1022ES 0x4105a220 -#define CPU_ID_SA110 0x4401a100 -#define CPU_ID_SA1100 0x4401a110 -#define CPU_ID_TI925T 0x54029250 -#define CPU_ID_SA1110 0x6901b110 -#define CPU_ID_IXP1200 0x6901c120 -#define CPU_ID_80200 0x69052000 -#define CPU_ID_PXA250 0x69052100 /* sans core revision */ -#define CPU_ID_PXA210 0x69052120 -#define CPU_ID_PXA250A 0x69052100 /* 1st version Core */ -#define CPU_ID_PXA210A 0x69052120 /* 1st version Core */ -#define CPU_ID_PXA250B 0x69052900 /* 3rd version Core */ -#define CPU_ID_PXA210B 0x69052920 /* 3rd version Core */ -#define CPU_ID_PXA250C 0x69052d00 /* 4th version Core */ -#define CPU_ID_PXA210C 0x69052d20 /* 4th version Core */ -#define CPU_ID_80321_400 0x69052420 -#define CPU_ID_80321_600 0x69052430 -#define CPU_ID_80321_400_B0 0x69052c20 -#define CPU_ID_80321_600_B0 0x69052c30 -#define CPU_ID_IXP425_533 0x690541c0 -#define CPU_ID_IXP425_400 0x690541d0 -#define CPU_ID_IXP425_266 0x690541f0 - -/* ARM3-specific coprocessor 15 registers */ -#define ARM3_CP15_FLUSH 1 -#define ARM3_CP15_CONTROL 2 -#define ARM3_CP15_CACHEABLE 3 -#define ARM3_CP15_UPDATEABLE 4 -#define ARM3_CP15_DISRUPTIVE 5 - -/* ARM3 Control register bits */ -#define ARM3_CTL_CACHE_ON 0x00000001 -#define ARM3_CTL_SHARED 0x00000002 -#define ARM3_CTL_MONITOR 0x00000004 - -/* - * Post-ARM3 CP15 registers: - * - * 1 Control register - * - * 2 Translation Table Base - * - * 3 Domain Access Control - * - * 4 Reserved - * - * 5 Fault Status - * - * 6 Fault Address - * - * 7 Cache/write-buffer Control - * - * 8 TLB Control - * - * 9 Cache Lockdown - * - * 10 TLB Lockdown - * - * 11 Reserved - * - * 12 Reserved - * - * 13 Process ID (for FCSE) - * - * 14 Reserved - * - * 15 Implementation Dependent - */ - -/* Some of the definitions below need cleaning up for V3/V4 architectures */ - -/* CPU control register (CP15 register 1) */ -#define CPU_CONTROL_MMU_ENABLE 0x00000001 /* M: MMU/Protection unit enable */ -#define CPU_CONTROL_AFLT_ENABLE 0x00000002 /* A: Alignment fault enable */ -#define CPU_CONTROL_DC_ENABLE 0x00000004 /* C: IDC/DC enable */ -#define CPU_CONTROL_WBUF_ENABLE 0x00000008 /* W: Write buffer enable */ -#define CPU_CONTROL_32BP_ENABLE 0x00000010 /* P: 32-bit exception handlers */ -#define CPU_CONTROL_32BD_ENABLE 0x00000020 /* D: 32-bit addressing */ -#define CPU_CONTROL_LABT_ENABLE 0x00000040 /* L: Late abort enable */ -#define CPU_CONTROL_BEND_ENABLE 0x00000080 /* B: Big-endian mode */ -#define CPU_CONTROL_SYST_ENABLE 0x00000100 /* S: System protection bit */ -#define CPU_CONTROL_ROM_ENABLE 0x00000200 /* R: ROM protection bit */ -#define CPU_CONTROL_CPCLK 0x00000400 /* F: Implementation defined */ -#define CPU_CONTROL_BPRD_ENABLE 0x00000800 /* Z: Branch prediction enable */ -#define CPU_CONTROL_IC_ENABLE 0x00001000 /* I: IC enable */ -#define CPU_CONTROL_VECRELOC 0x00002000 /* V: Vector relocation */ -#define CPU_CONTROL_ROUNDROBIN 0x00004000 /* RR: Predictable replacement */ -#define CPU_CONTROL_V4COMPAT 0x00008000 /* L4: ARMv4 compat LDR R15 etc */ - -#define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE - -/* XScale Auxillary Control Register (CP15 register 1, opcode2 1) */ -#define XSCALE_AUXCTL_K 0x00000001 /* dis. write buffer coalescing */ -#define XSCALE_AUXCTL_P 0x00000002 /* ECC protect page table access */ -#define XSCALE_AUXCTL_MD_WB_RA 0x00000000 /* mini-D$ wb, read-allocate */ -#define XSCALE_AUXCTL_MD_WB_RWA 0x00000010 /* mini-D$ wb, read/write-allocate */ -#define XSCALE_AUXCTL_MD_WT 0x00000020 /* mini-D$ wt, read-allocate */ -#define XSCALE_AUXCTL_MD_MASK 0x00000030 - -/* Cache type register definitions */ -#define CPU_CT_ISIZE(x) ((x) & 0xfff) /* I$ info */ -#define CPU_CT_DSIZE(x) (((x) >> 12) & 0xfff) /* D$ info */ -#define CPU_CT_S (1U << 24) /* split cache */ -#define CPU_CT_CTYPE(x) (((x) >> 25) & 0xf) /* cache type */ - -#define CPU_CT_CTYPE_WT 0 /* write-through */ -#define CPU_CT_CTYPE_WB1 1 /* write-back, clean w/ read */ -#define CPU_CT_CTYPE_WB2 2 /* w/b, clean w/ cp15,7 */ -#define CPU_CT_CTYPE_WB6 6 /* w/b, cp15,7, lockdown fmt A */ -#define CPU_CT_CTYPE_WB7 7 /* w/b, cp15,7, lockdown fmt B */ - -#define CPU_CT_xSIZE_LEN(x) ((x) & 0x3) /* line size */ -#define CPU_CT_xSIZE_M (1U << 2) /* multiplier */ -#define CPU_CT_xSIZE_ASSOC(x) (((x) >> 3) & 0x7) /* associativity */ -#define CPU_CT_xSIZE_SIZE(x) (((x) >> 6) & 0x7) /* size */ - -/* Fault status register definitions */ - -#define FAULT_TYPE_MASK 0x0f -#define FAULT_USER 0x10 - -#define FAULT_WRTBUF_0 0x00 /* Vector Exception */ -#define FAULT_WRTBUF_1 0x02 /* Terminal Exception */ -#define FAULT_BUSERR_0 0x04 /* External Abort on Linefetch -- Section */ -#define FAULT_BUSERR_1 0x06 /* External Abort on Linefetch -- Page */ -#define FAULT_BUSERR_2 0x08 /* External Abort on Non-linefetch -- Section */ -#define FAULT_BUSERR_3 0x0a /* External Abort on Non-linefetch -- Page */ -#define FAULT_BUSTRNL1 0x0c /* External abort on Translation -- Level 1 */ -#define FAULT_BUSTRNL2 0x0e /* External abort on Translation -- Level 2 */ -#define FAULT_ALIGN_0 0x01 /* Alignment */ -#define FAULT_ALIGN_1 0x03 /* Alignment */ -#define FAULT_TRANS_S 0x05 /* Translation -- Section */ -#define FAULT_TRANS_P 0x07 /* Translation -- Page */ -#define FAULT_DOMAIN_S 0x09 /* Domain -- Section */ -#define FAULT_DOMAIN_P 0x0b /* Domain -- Page */ -#define FAULT_PERM_S 0x0d /* Permission -- Section */ -#define FAULT_PERM_P 0x0f /* Permission -- Page */ - -#define FAULT_IMPRECISE 0x400 /* Imprecise exception (XSCALE) */ - -/* - * Address of the vector page, low and high versions. - */ -#define ARM_VECTORS_LOW 0x00000000U -#define ARM_VECTORS_HIGH 0xffff0000U - -/* - * ARM Instructions - * - * 3 3 2 2 2 - * 1 0 9 8 7 0 - * +-------+-------------------------------------------------------+ - * | cond | instruction dependant | - * |c c c c| | - * +-------+-------------------------------------------------------+ - */ - -#define INSN_SIZE 4 /* Always 4 bytes */ -#define INSN_COND_MASK 0xf0000000 /* Condition mask */ -#define INSN_COND_AL 0xe0000000 /* Always condition */ - -#endif /* !MACHINE_ARMREG_H */ diff --git a/libacc/tests/data/addressOf.c b/libacc/tests/data/addressOf.c deleted file mode 100644 index e7acde5..0000000 --- a/libacc/tests/data/addressOf.c +++ /dev/null @@ -1,31 +0,0 @@ -void testStruct() { - struct str { - float x; - float y; - }; - - struct str base; - int index = 0; - - base.x = 10.0; - struct str *s = &base; - - float *v = &(*s).x; - float *v2 = &s[index].x; - printf("testStruct: %g %g %g\n",base.x, *v, *v2); -} - -void testArray() { - int a[2]; - a[0] = 1; - a[1] = 2; - int* p = &a[0]; - int* p2 = a; - printf("testArray: %d %d %d\n", a[0], *p, *p2); -} - -int main() { - testStruct(); - testArray(); - return 0; -} diff --git a/libacc/tests/data/array.c b/libacc/tests/data/array.c deleted file mode 100644 index ca4a728..0000000 --- a/libacc/tests/data/array.c +++ /dev/null @@ -1,107 +0,0 @@ -// Array allocation tests - -void testLocalInt() -{ - int a[3]; - a[0] = 1; - a[1] = 2; - a[2] = a[0] + a[1]; - printf("localInt: %d\n", a[2]); -} - -char a[3]; -double d[3]; - -void testGlobalChar() -{ - a[0] = 1; - a[1] = 2; - a[2] = a[0] + a[1]; - printf("globalChar: %d\n", a[2]); -} - -void testGlobalDouble() -{ - d[0] = 1; - d[1] = 2; - d[2] = d[0] + d[1]; - printf("globalDouble: %g\n", d[2]); -} - -void testLocalDouble() -{ - double d[3]; - float m[12]; - m[0] = 1.0f; - m[1] = 2.0f; - d[0] = 1.0; - d[1] = 2.0; - d[2] = d[0] + d[1]; - m[2] = m[0] + m[1]; - printf("localDouble: %g %g\n", d[2], m[2]); -} - -void vectorAdd(int* a, int* b, float* c, int len) { - int i; - for(i = 0; i < len; i++) { - c[i] = a[i] + b[i]; - } -} - -void testArgs() { - int a[3], b[3]; - float c[3]; - int i; - int len = 3; - for(i = 0; i < len; i++) { - a[i] = i; - b[i] = i; - c[i] = 0; - } - vectorAdd(a,b,c, len); - printf("testArgs:"); - for(i = 0; i < len; i++) { - printf(" %g", c[i]); - } - printf("\n"); -} - -void testDecay() { - char c[4]; - c[0] = 'H'; - c[1] = 'i'; - c[2] = '!'; - c[3] = 0; - printf("testDecay: %s\n", c); -} - -void test2D() { - char c[10][20]; - int x; - int y; - printf("test2D:\n"); - for(y = 0; y < 10; y++) { - for(x = 0; x < 20; x++) { - c[y][x] = 'a' + (15 & (y * 19 + x)); - } - } - for(y = 0; y < 10; y++) { - for(x = 0; x < 20; x++) { - printf("%c", c[y][x]); - } - printf("\n"); - } - -} - -int main() -{ - testLocalInt(); - testLocalDouble(); - testGlobalChar(); - testGlobalDouble(); - testArgs(); - testDecay(); - test2D(); - return 0; -} diff --git a/libacc/tests/data/assignment.c b/libacc/tests/data/assignment.c deleted file mode 100644 index 4fc7801..0000000 --- a/libacc/tests/data/assignment.c +++ /dev/null @@ -1,9 +0,0 @@ -int main() { - int a = 0; - int b = 1; - a = b = 2; // Test that "b = 2" generates an rvalue. - if (a = 7) { // Test that a = 7 generates an rvalue. - b = 3; - } - return a; -} diff --git a/libacc/tests/data/assignmentop.c b/libacc/tests/data/assignmentop.c deleted file mode 100644 index 649edf9..0000000 --- a/libacc/tests/data/assignmentop.c +++ /dev/null @@ -1,62 +0,0 @@ -// Test assignment operations - -void testAssignment() { - int a = 2; - a *= 5; - printf("2 *= 5 %d\n", a); - a = 20; - a /= 5; - printf("20 /= 5 %d\n", a); - a = 17; - a %= 5; - printf("17 %%= 5 %d\n", a); - a = 17; - a += 5; - printf("17 += 5 %d\n", a); - a = 17; - a-=5; - printf("17 -= 5 %d\n", a); - a = 17; - a<<=1; - printf("17<<= 1 %d\n", a); - a = 17; - a>>=1; - printf("17>>= 1 %d\n", a); - a = 17; - a&=1; - printf("17&= 1 %d\n", a); - a = 17; - a^=1; - printf("17^= 1 %d\n", a); - a = 16; - a^=1; - printf("16|= 1 %d\n", a); -} - -int a; - -int* f() { - printf("f()\n"); - return &a; -} - -void testEval() { - a = 0; - printf("*f() = *f() + 10;\n"); - *f() = *f() + 10; - printf("a = %d\n", a); -} - -void testOpEval() { - a = 0; - printf("*f() += 10;\n"); - *f() += 10; - printf("a = %d\n", a); -} - -int main() { - testAssignment(); - testEval(); - testOpEval(); - return 0; -} diff --git a/libacc/tests/data/b2071670.c b/libacc/tests/data/b2071670.c deleted file mode 100644 index 311bc4f..0000000 --- a/libacc/tests/data/b2071670.c +++ /dev/null @@ -1,9 +0,0 @@ -// See http://b/2071670 - -int main() { - float f = 10.0f; - float* floatPointer = &f; - // The following line used to incorrectly error: "Incompatible pointer or array types" - int* buffer = (int*) floatPointer; - return *buffer; -} diff --git a/libacc/tests/data/bellard.otccex.c b/libacc/tests/data/bellard.otccex.c deleted file mode 100644 index e8f0989..0000000 --- a/libacc/tests/data/bellard.otccex.c +++ /dev/null @@ -1,126 +0,0 @@ -/* #!/usr/local/bin/otcc */ -/* - * Sample OTCC C example. You can uncomment the first line and install - * otcc in /usr/local/bin to make otcc scripts ! - */ - -/* Any preprocessor directive except #define are ignored. We put this - include so that a standard C compiler can compile this code too. */ -#include <stdio.h> - -/* defines are handled, but macro arguments cannot be given. No - recursive defines are tolerated */ -#define DEFAULT_BASE 10 - -/* - * Only old style K&R prototypes are parsed. Only int arguments are - * allowed (implicit types). - * - * By benchmarking the execution time of this function (for example - * for fib(35)), you'll notice that OTCC is quite fast because it - * generates native i386 machine code. - */ -fib(n) -{ - if (n <= 2) - return 1; - else - return fib(n-1) + fib(n-2); -} - -/* Identifiers are parsed the same way as C: begins with letter or - '_', and then letters, '_' or digits */ -fact(n) -{ - /* local variables can be declared. Only 'int' type is supported */ - int i, r; - r = 1; - /* 'while' and 'for' loops are supported */ - for(i=2;i<=n;i++) - r = r * i; - return r; -} - -/* Well, we could use printf, but it would be too easy */ -print_num(n, b) -{ - int tab, p, c; - /* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and - octal ('0' prefix) */ - /* more complex programs use malloc */ - tab = malloc(0x100); - p = tab; - while (1) { - c = n % b; - /* Character constants can be used */ - if (c >= 10) - c = c + 'a' - 10; - else - c = c + '0'; - *(char *)p = c; - p++; - n = n / b; - /* 'break' is supported */ - if (n == 0) - break; - } - while (p != tab) { - p--; - printf("%c", *(char *)p); - } - free(tab); -} - -/* 'main' takes standard 'argc' and 'argv' parameters */ -main(argc, argv) -{ - /* no local name space is supported, but local variables ARE - supported. As long as you do not use a globally defined - variable name as local variable (which is a bad habbit), you - won't have any problem */ - int s, n, f, base; - - /* && and || operator have the same semantics as C (left to right - evaluation and early exit) */ - if (argc != 2 && argc != 3) { - /* '*' operator is supported with explicit casting to 'int *', - 'char *' or 'int (*)()' (function pointer). Of course, 'int' - are supposed to be used as pointers too. */ - s = *(int *)argv; - help(s); - return 1; - } - /* Any libc function can be used because OTCC uses dynamic linking */ - n = atoi(*(int *)(argv + 4)); - base = DEFAULT_BASE; - if (argc >= 3) { - base = atoi(*(int *)(argv + 8)); - if (base < 2 || base > 36) { - /* external variables can be used too (here: 'stderr') */ - fprintf(stderr, "Invalid base\n"); - return 1; - } - } - printf("fib(%d) = ", n); - print_num(fib(n), base); - printf("\n"); - - printf("fact(%d) = ", n); - if (n > 12) { - printf("Overflow"); - } else { - /* why not using a function pointer ? */ - f = &fact; - print_num((*(int (*)())f)(n), base); - } - printf("\n"); - return 0; -} - -/* functions can be used before being defined */ -help(name) -{ - printf("usage: %s n [base]\n", name); - printf("Compute fib(n) and fact(n) and output the result in base 'base'\n"); -} - diff --git a/libacc/tests/data/brackets.c b/libacc/tests/data/brackets.c deleted file mode 100644 index bab88a2..0000000 --- a/libacc/tests/data/brackets.c +++ /dev/null @@ -1,61 +0,0 @@ -void testBrackets(int* ar, int len) { - int i; - int errors = 0; - for (i = 0; i < len; i++) { - ar[i] = i; - } - for (i = 0; i < len; i++) { - if (ar[i] != i) { - printf("error: [%d] %d != %d\n", i, ar[i], i); - errors++; - } - } - printf("Errors: %d\n", errors); -} - -void testBrackets2D(int** ar2D, int lenX, int lenY) { - int x, y; - int errors = 0; - for (x = 0; x < lenX; x++) { - for (y = 0; y < lenY; y++) { - ar2D[x][y] = x * lenY + y; - } - } - for (x = 0; x < lenX; x++) { - for (y = 0; y < lenY; y++) { - int expected = x * lenY + y; - int val = ar2D[x][y]; - if (val != expected) { - printf("error: [%d][%d] %d != %d\n", x, y, val, expected); - errors++; - } - } - } - printf("2D Errors: %d\n", errors); -} - -void testHeap() { - int* ar = (int*) malloc(100); - testBrackets(ar, 25); - free(ar); -} - -void testHeap2D() { - int lenX = 10; - int lenY = 5; - int* ar = (int*) malloc(lenX * lenY * 4); - int** ar2D = (int**) malloc(lenX * 4); - int i; - for(i = 0; i < lenX; i++) { - ar2D[i] = ar + lenY * i; - } - testBrackets2D(ar2D, lenX, lenY); - free(ar); - free(ar2D); -} - -int main() { - testHeap(); - testHeap2D(); - return 0; -} diff --git a/libacc/tests/data/casts.c b/libacc/tests/data/casts.c deleted file mode 100644 index d3a49b4..0000000 --- a/libacc/tests/data/casts.c +++ /dev/null @@ -1,85 +0,0 @@ -void test1() { - int a = 3; - int* pb = &a; - int c = *pb; - printf("Reading from a pointer: %d %d\n", a, c); - *pb = 4; - printf("Writing to a pointer: %d\n", a); - printf("Testing casts: %d %g %g %d\n", 3, (float) 3, 4.5, (int) 4.5); -} - -void test2() { - int x = 4; - int px = &x; - // int z = * px; // An error, expected a pointer type - int y = * (int*) px; - printf("Testing reading (int*): %d\n", y); -} - -void test3() { - int px = (int) malloc(120); - * (int*) px = 8; - * (int*) (px + 4) = 9; - printf("Testing writing (int*): %d %d\n", * (int*) px, * (int*) (px + 4)); - free((void*) px); -} - -void test4() { - int x = 0x12345678; - int px = &x; - int a = * (char*) px; - int b = * (char*) (px + 1); - int c = * (char*) (px + 2); - int d = * (char*) (px + 3); - printf("Testing reading (char*): 0x%02x 0x%02x 0x%02x 0x%02x\n", a, b, c, d); -} - -void test5() { - int x = 0xFFFFFFFF; - int px = &x; - * (char*) px = 0x21; - * (char*) (px + 1) = 0x43; - * (char*) (px + 2) = 0x65; - * (char*) (px + 3) = 0x87; - printf("Testing writing (char*): 0x%08x\n", x); -} - -int f(int b) { - printf("f(%d)\n", b); - return 7 * b; -} - -void test6() { - int fp = &f; - int x = (*(int(*)()) fp)(10); - printf("Function pointer result: %d\n", x); -} - -void test7() { - int px = (int) malloc(120); - * (float*) px = 8.8f; - * (float*) (px + 4) = 9.9f; - printf("Testing read/write (float*): %g %g\n", * (float*) px, * (float*) (px + 4)); - free((void*) px); -} - -void test8() { - int px = (int) malloc(120); - * (double*) px = 8.8; - * (double*) (px + 8) = 9.9; - printf("Testing read/write (double*): %g %g\n", * (double*) px, * (double*) (px + 8)); - free((void*) px); -} - - -int main() { - test1(); - test2(); - test3(); - test4(); - test5(); - test6(); - test7(); - test8(); - return 0; -} diff --git a/libacc/tests/data/char.c b/libacc/tests/data/char.c deleted file mode 100644 index 8c63ba2..0000000 --- a/libacc/tests/data/char.c +++ /dev/null @@ -1,13 +0,0 @@ -char ga; -char gb; - -int main() { - char a = 'c'; - char b = a * 3; - printf("a = %d, b = %d\n", a, b); - ga = 'd'; - gb = ga * 3; - printf("ga = %d, gb = %d\n", ga, gb); - return 0; -} - diff --git a/libacc/tests/data/comma.c b/libacc/tests/data/comma.c deleted file mode 100644 index 496944c..0000000 --- a/libacc/tests/data/comma.c +++ /dev/null @@ -1,35 +0,0 @@ -int testReturn() { - return 10, 20, 30; -} - -int testArg(int a) { - return a; -} - -void testComma() { - int a; - 0, a = 10,20; - printf("statement: %d\n", a); - a = 1; - if (a = 0, 1) { - printf("if: a = %d\n", a); - } - int b = 0; - a = 10; - while(b++,a--) {} - printf("while: b = %d\n", b); - b = 0; - for(b++,a = 0;b++, a < 10; b++, a++) {} - printf("for: b = %d\n", b); - b = testReturn(); - printf("return: %d\n", b); - b = testArg((a,12)); - printf("arg: %d\n", b); -} - - - -int main() { - testComma(); - return 0; -} diff --git a/libacc/tests/data/constants.c b/libacc/tests/data/constants.c deleted file mode 100644 index 230109a..0000000 --- a/libacc/tests/data/constants.c +++ /dev/null @@ -1,30 +0,0 @@ -#define FOO 0x10 - -int main() { - printf("0 = %d\n", 0); - printf("010 = %d\n", 010); - printf("0x10 = %d\n", FOO); - printf("'\\a' = %d\n", '\a'); - printf("'\\b' = %d\n", '\b'); - printf("'\\f' = %d\n", '\f'); - printf("'\\n' = %d\n", '\n'); - printf("'\\r' = %d\n", '\r'); - printf("'\\t' = %d\n", '\t'); - printf("'\\v' = %d\n", '\v'); - // Undefined - // printf("'\\z' = %d\n", '\z'); - printf("'\\\\' = %d\n", '\\'); - printf("'\\'' = %d\n", '\''); - printf("'\\\"' = %d\n", '\"'); - printf("'\\?' = %d\n", '\?'); - printf("'\\0' = %d\n", '\0'); - printf("'\\1' = %d\n", '\1'); - printf("'\\12' = %d\n", '\12'); - printf("'\\123' = %d\n", '\123'); - printf("'\\x0' = %d\n", '\x0'); - printf("'\\x1' = %d\n", '\x1'); - printf("'\\x12' = %d\n", '\x12'); - printf("'\\x123' = %d\n", '\x123'); - printf("'\\x1f' = %d\n", '\x1f'); - printf("'\\x1F' = %d\n", '\x1F'); -} diff --git a/libacc/tests/data/continue.c b/libacc/tests/data/continue.c deleted file mode 100644 index d8b8e36..0000000 --- a/libacc/tests/data/continue.c +++ /dev/null @@ -1,13 +0,0 @@ -int main() { - int i, j, sum; - sum = 0; - for (i = 0; i < 10; i++) { - if (i & 1) continue; - for (j = 0; j < 10; j++) { - if (j & 1) continue; - sum += i * j; - } - } - return sum; -} - diff --git a/libacc/tests/data/defines.c b/libacc/tests/data/defines.c deleted file mode 100644 index 6cb6f7e..0000000 --- a/libacc/tests/data/defines.c +++ /dev/null @@ -1,9 +0,0 @@ -// Simple tests of the C preprocessor - -#define A 1 -#define A (4 / 2) -#define B 1 // This is a comment. With a / in it. - -int main() { - return A + B; -} diff --git a/libacc/tests/data/double.c b/libacc/tests/data/double.c deleted file mode 100644 index 5bc20a3..0000000 --- a/libacc/tests/data/double.c +++ /dev/null @@ -1,7 +0,0 @@ -double atof(char *nptr); - -int main() { - printf("Value = %g\n", atof("10.42")); - return 0; -} - diff --git a/libacc/tests/data/error.c b/libacc/tests/data/error.c deleted file mode 100644 index 2e08dcc..0000000 --- a/libacc/tests/data/error.c +++ /dev/null @@ -1,2 +0,0 @@ -void foo; - diff --git a/libacc/tests/data/expr-ansi.c b/libacc/tests/data/expr-ansi.c deleted file mode 100644 index d463659..0000000 --- a/libacc/tests/data/expr-ansi.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Test operators */ - -void testInc() { int a, b; a = 3; b = a++; printf("3++ = %d %d\n", b, a); } -void testDec() { int a, b; a = 3; b = a--; printf("3-- = %d %d\n", b, a); } -void testTimes(){ printf("%d * %d = %d\n", 10, 4, 10 * 4); } -void testDiv(){ printf("%d / %d = %d\n", 11, 4, 11 / 4); } -void testMod(){ printf("%d %% %d = %d\n", 11, 4, 11 % 4); } -void testPlus(){ printf("%d + %d = %d\n", 10, 4, 10 + 4); } -void testMinus(){ printf("%d - %d = %d\n", 10, 4, 10 - 4); } -void testShiftLeft(){ printf("%d << %d = %d\n", 10, 4, 10 << 4); } -void testShiftRight(){ printf("%d >> %d = %d\n", 100, 4, 100 >> 4); } -void testLess(){ printf("%d < %d = %d\n", 10, 4, 10 < 4); } -void testLesEqual(){ printf("%d <= %d = %d\n", 10, 4, 10 <= 4); } -void testGreater(){ printf("%d > %d = %d\n", 10, 4, 10 > 4); } -void testGreaterEqual(){ printf("%d >= %d = %d\n", 10, 4, 10 >= 4); } -void testEqualTo(){ printf("%d == %d = %d\n", 10, 4, 10 == 4); } -void testNotEqualTo(){ printf("%d != %d = %d\n", 10, 4, 10 != 4); } -void testBitAnd(){ printf("%d & %d = %d\n", 10, 7, 10 & 7); } -void testBitXor(){ printf("%d ^ %d = %d\n", 10, 7, 10 ^ 7); } -void testBitOr(){ printf("%d | %d = %d\n", 10, 4, 10 | 4); } -void testAssignment(){ int a, b; a = 3; b = a; printf("b == %d\n", b); } -void testLogicalAnd(){ printf("%d && %d = %d\n", 10, 4, 10 && 4); } -void testLogicalOr(){ printf("%d || %d = %d\n", 10, 4, 10 || 4); } -void testAddressOf(){ int a; printf("&a is %d\n", &a); } -void testPointerIndirection(){ int a, b; a = &b; b = 17; printf("*%d = %d =?= %d\n", a, * (int*) a, b); } -void testNegation(){ printf("-%d = %d\n", 10, -10); } -void testUnaryPlus(){ printf("+%d = %d\n", 10, +10); } -void testUnaryNot(){ printf("!%d = %d\n", 10, !10); } -void testBitNot(){ printf("~%d = %d\n", 10, ~10); } - -int main(int a, char** b) { - testInc(); - testDec(); - testTimes(); - testDiv(); - testMod(); - testPlus(); - testMinus(); - testShiftLeft(); - testShiftRight(); - testLess(); - testLesEqual(); - testGreater(); - testGreaterEqual(); - testEqualTo(); - testNotEqualTo(); - testBitAnd(); - testBinXor(); - testBitOr(); - testAssignment(); - testLogicalAnd(); - testLogicalOr(); - testAddressOf(); - testPointerIndirection(); - testNegation(); - testUnaryPlus(); - testUnaryNot(); - testBitNot(); - return 0; -} diff --git a/libacc/tests/data/expr.c b/libacc/tests/data/expr.c deleted file mode 100644 index 4f2d2e7..0000000 --- a/libacc/tests/data/expr.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Test operators */ - -testInc() { int a, b; a = 3; b = a++; printf("3++ = %d %d\n", b, a); } -testDec() { int a, b; a = 3; b = a--; printf("3-- = %d %d\n", b, a); } -testTimes(){ printf("%d * %d = %d\n", 10, 4, 10 * 4); } -testDiv(){ printf("%d / %d = %d\n", 11, 4, 11 / 4); } -testMod(){ printf("%d %% %d = %d\n", 11, 4, 11 % 4); } -testPlus(){ printf("%d + %d = %d\n", 10, 4, 10 + 4); } -testMinus(){ printf("%d - %d = %d\n", 10, 4, 10 - 4); } -testShiftLeft(){ printf("%d << %d = %d\n", 10, 4, 10 << 4); } -testShiftRight(){ printf("%d >> %d = %d\n", 100, 4, 100 >> 4); } -testLess(){ printf("%d < %d = %d\n", 10, 4, 10 < 4); } -testLesEqual(){ printf("%d <= %d = %d\n", 10, 4, 10 <= 4); } -testGreater(){ printf("%d > %d = %d\n", 10, 4, 10 > 4); } -testGreaterEqual(){ printf("%d >= %d = %d\n", 10, 4, 10 >= 4); } -testEqualTo(){ printf("%d == %d = %d\n", 10, 4, 10 == 4); } -testNotEqualTo(){ printf("%d != %d = %d\n", 10, 4, 10 != 4); } -testBitAnd(){ printf("%d & %d = %d\n", 10, 7, 10 & 7); } -testBitXor(){ printf("%d ^ %d = %d\n", 10, 7, 10 ^ 7); } -testBitOr(){ printf("%d | %d = %d\n", 10, 4, 10 | 4); } -testAssignment(){ int a, b; a = 3; b = a; printf("b == %d\n", b); } -testLogicalAnd(){ printf("%d && %d = %d\n", 10, 4, 10 && 4); } -testLogicalOr(){ printf("%d || %d = %d\n", 10, 4, 10 || 4); } -testAddressOf(){ int a; printf("&a is %d\n", &a); } -testPointerIndirection(){ int a, b; a = &b; b = 17; printf("*%d = %d =?= %d\n", a, * (int*) a, b); } -testNegation(){ printf("-%d = %d\n", 10, -10); } -testUnaryPlus(){ printf("+%d = %d\n", 10, +10); } -testUnaryNot(){ printf("!%d = %d\n", 10, !10); } -testBitNot(){ printf("~%d = %d\n", 10, ~10); } - -main(a,b) { - testInc(); - testDec(); - testTimes(); - testDiv(); - testMod(); - testPlus(); - testMinus(); - testShiftLeft(); - testShiftRight(); - testLess(); - testLesEqual(); - testGreater(); - testGreaterEqual(); - testEqualTo(); - testNotEqualTo(); - testBitAnd(); - testBinXor(); - testBitOr(); - testAssignment(); - testLogicalAnd(); - testLogicalOr(); - testAddressOf(); - testPointerIndirection(); - testNegation(); - testUnaryPlus(); - testUnaryNot(); - testBitNot(); - return 0; -}
\ No newline at end of file diff --git a/libacc/tests/data/expr2.c b/libacc/tests/data/expr2.c deleted file mode 100644 index 04b6a38..0000000 --- a/libacc/tests/data/expr2.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Test operators */ - -main() { - int a; - a = a++; -} diff --git a/libacc/tests/data/film.c b/libacc/tests/data/film.c deleted file mode 100644 index 00c2d36..0000000 --- a/libacc/tests/data/film.c +++ /dev/null @@ -1,53 +0,0 @@ -// Test logical and bitwise AND and OR - -int test(int x, int y) { - int v = x || y; - return v; -} - -int test2(int x, int y) { - if(x | y) { - return 1; - } else { - return 0; - } -} - -int test3(int x, int y) { - int v = x && y; - return v; -} - -int test4(int x, int y) { - if(x & y) { - return 1; - } else { - return 0; - } -} - -int main(int index) -{ - int x,y; - printf("testing...\n"); - int totalBad = 0; - for(y = 0; y < 2; y++) { - for(x = 0; x < 2; x++) { - int a = test(x,y); - int b = test2(x,y); - if (a != b) { - printf("Results differ: OR x=%d y=%d a=%d b=%d\n", x, y, a, b); - totalBad++; - } - a = test3(x,y); - b = test4(x,y); - if (a != b) { - printf("Results differ: AND x=%d y=%d a=%d b=%d\n", x, y, a, b); - totalBad++; - } - } - } - printf("Total bad: %d\n", totalBad); - return 0; -} - diff --git a/libacc/tests/data/float.c b/libacc/tests/data/float.c deleted file mode 100644 index f48b3d1..0000000 --- a/libacc/tests/data/float.c +++ /dev/null @@ -1,57 +0,0 @@ -int ftoi(float f) { - return f; -} - -int dtoi(double d) { - return d; -} - -float itof(int i) { - return i; -} - -double itod(int i) { - return i; -} - -float f0, f1; -double d0, d1; - -void testParseConsts() { - printf("Constants: %g %g %g %g %g %g %g %g %g\n", 0e1, 0E1, 0.f, .01f, - .01e0f, 1.0e-1, 1.0e1, 1.0e+1, - .1f); -} -void testVars(float arg0, float arg1, double arg2, double arg3) { - float local0, local1; - double local2, local3; - f0 = arg0; - f1 = arg1; - d0 = arg2; - d1 = arg3; - local0 = arg0; - local1 = arg1; - local2 = arg2; - local3 = arg3; - printf("globals: %g %g %g %g\n", f0, f1, d0, d1); - printf("args: %g %g %g %g\n", arg0, arg1, arg2, arg3); - printf("locals: %g %g %g %g\n", local0, local1, local2, local3); - - - printf("cast rval: %g %g\n", * (float*) & f1, * (double*) & d1); - - * (float*) & f0 = 1.1f; - * (double*) & d0 = 3.3; - printf("cast lval: %g %g %g %g\n", f0, f1, d0, d1); -} - -int main() { - testParseConsts(); - printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3); - printf(" ftoi(1.4f)=%d\n", ftoi(1.4f)); - printf(" dtoi(2.4)=%d\n", dtoi(2.4)); - printf(" itof(3)=%g\n", itof(3)); - printf(" itod(4)=%g\n", itod(4)); - testVars(1.0f, 2.0f, 3.0, 4.0); - return 0; -} diff --git a/libacc/tests/data/floatdouble.c b/libacc/tests/data/floatdouble.c deleted file mode 100644 index 264c641..0000000 --- a/libacc/tests/data/floatdouble.c +++ /dev/null @@ -1,9 +0,0 @@ -int main() -{ - // Test coercing values when storing. - float a = 0.002; - double b = 0.1f; - int c = 10.002; - printf("%g %g %d\n", a, b, c); - return 0; -} diff --git a/libacc/tests/data/flops.c b/libacc/tests/data/flops.c deleted file mode 100644 index 40b1b28..0000000 --- a/libacc/tests/data/flops.c +++ /dev/null @@ -1,158 +0,0 @@ -// Test floating point operations. - -void unaryOps() { - // Unary ops - printf("-%g = %g\n", 1.1, -1.1); - printf("!%g = %d\n", 1.2, !1.2); - printf("!%g = %d\n", 0.0, !0.0); -} - -void binaryOps() { - printf("double op double:\n"); - printf("%g + %g = %g\n", 1.0, 2.0, 1.0 + 2.0); - printf("%g - %g = %g\n", 1.0, 2.0, 1.0 - 2.0); - printf("%g * %g = %g\n", 1.0, 2.0, 1.0 * 2.0); - printf("%g / %g = %g\n", 1.0, 2.0, 1.0 / 2.0); - - printf("float op float:\n"); - printf("%g + %g = %g\n", 1.0f, 2.0f, 1.0f + 2.0f); - printf("%g - %g = %g\n", 1.0f, 2.0f, 1.0f - 2.0f); - printf("%g * %g = %g\n", 1.0f, 2.0f, 1.0f * 2.0f); - printf("%g / %g = %g\n", 1.0f, 2.0f, 1.0f / 2.0f); - - printf("double op float:\n"); - printf("%g + %g = %g\n", 1.0, 2.0f, 1.0 + 2.0f); - printf("%g - %g = %g\n", 1.0, 2.0f, 1.0 - 2.0f); - printf("%g * %g = %g\n", 1.0, 2.0f, 1.0 * 2.0f); - printf("%g / %g = %g\n", 1.0, 2.0f, 1.0 / 2.0f); - - printf("double op int:\n"); - printf("%g + %d = %g\n", 1.0, 2, 1.0 + 2); - printf("%g - %d = %g\n", 1.0, 2, 1.0 - 2); - printf("%g * %d = %g\n", 1.0, 2, 1.0 * 2); - printf("%g / %d = %g\n", 1.0, 2, 1.0 / 2); - - printf("int op double:\n"); - printf("%d + %g = %g\n", 1, 2.0, 1 + 2.0); - printf("%d - %g = %g\n", 1, 2.0, 1 - 2.0); - printf("%d * %g = %g\n", 1, 2.0, 1 * 2.0); - printf("%d / %g = %g\n", 1, 2.0, 1 / 2.0); -} - -void comparisonTestdd(double a, double b) { - printf("%g op %g: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsdd() { - printf("double op double:\n"); - comparisonTestdd(1.0, 2.0); - comparisonTestdd(1.0, 1.0); - comparisonTestdd(2.0, 1.0); -} - - -void comparisonTestdf(double a, float b) { - printf("%g op %g: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsdf() { - printf("double op float:\n"); - comparisonTestdf(1.0, 2.0f); - comparisonTestdf(1.0, 1.0f); - comparisonTestdf(2.0, 1.0f); -} - -void comparisonTestff(float a, float b) { - printf("%g op %g: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsff() { - printf("float op float:\n"); - comparisonTestff(1.0f, 2.0f); - comparisonTestff(1.0f, 1.0f); - comparisonTestff(2.0f, 1.0f); -} - -void comparisonTestid(int a, double b) { - printf("%d op %g: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsid() { - printf("int op double:\n"); - comparisonTestid(1, 2.0); - comparisonTestid(1, 1.0); - comparisonTestid(2, 1.0); -} -void comparisonTestdi(double a, int b) { - printf("%g op %d: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsdi() { - printf("double op int:\n"); - comparisonTestdi(1.0f, 2); - comparisonTestdi(1.0f, 1); - comparisonTestdi(2.0f, 1); -} - -void comparisonOps() { - comparisonOpsdd(); - comparisonOpsdf(); - comparisonOpsff(); - comparisonOpsid(); - comparisonOpsdi(); -} - -int branch(double d) { - if (d) { - return 1; - } - return 0; -} - -void testBranching() { - printf("branching: %d %d %d\n", branch(-1.0), branch(0.0), branch(1.0)); -} - -void testpassi(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { - printf("testpassi: %d %d %d %d %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h, i, j, k, l); -} - -void testpassf(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l) { - printf("testpassf: %g %g %g %g %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h, i, j, k, l); -} - -void testpassd(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j, double k, double l) { - printf("testpassd: %g %g %g %g %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h, i, j, k, l); -} - -void testpassidf(int i, double d, float f) { - printf("testpassidf: %d %g %g\n", i, d, f); -} - -void testParameterPassing() { - float x; - testpassi(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); - testpassf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); - testpassd(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); - testpassi(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f); - testpassf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f); - testpassd(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f); - testpassi(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0); - testpassf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0); - testpassd(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0); - testpassidf(1, 2.0, 3.0f); -} - -int main() { - unaryOps(); - binaryOps(); - comparisonOps(); - testBranching(); - testParameterPassing(); - return 0; -} diff --git a/libacc/tests/data/funcargs.c b/libacc/tests/data/funcargs.c deleted file mode 100644 index 1dce226..0000000 --- a/libacc/tests/data/funcargs.c +++ /dev/null @@ -1,8 +0,0 @@ -int f(int a,int, int c) { - return a + c; -} - -int main() { - return f(1,2,3); -} - diff --git a/libacc/tests/data/hello.c b/libacc/tests/data/hello.c deleted file mode 100644 index 585ce6c..0000000 --- a/libacc/tests/data/hello.c +++ /dev/null @@ -1,3 +0,0 @@ -main(a,b) { - printf("Hello, world\n"); -} diff --git a/libacc/tests/data/inc.c b/libacc/tests/data/inc.c deleted file mode 100644 index 14c09d1..0000000 --- a/libacc/tests/data/inc.c +++ /dev/null @@ -1,14 +0,0 @@ -// Check integer operations - -int main() { - int a = 0; - printf("%d\n", a++); - printf("%d\n", a++); - printf("%d\n", a--); - printf("%d\n", a--); - printf("%d\n", ++a); - printf("%d\n", ++a); - printf("%d\n", --a); - printf("%d\n", --a); - return a; -} diff --git a/libacc/tests/data/iops.c b/libacc/tests/data/iops.c deleted file mode 100644 index 780e95d..0000000 --- a/libacc/tests/data/iops.c +++ /dev/null @@ -1,23 +0,0 @@ -// Check integer operations - -void loops() { - int y; - printf("++\n"); - for(y = 0; y < 10; y++) { - printf("%d\n", y); - } - printf("--\n"); - for(y = 10; y >= 0; y--) { - printf("%d\n", y); - } -} - -void checkLiterals() { - printf("Literals: %d %d\n", 1, -1); -} - -int main() { - checkLiterals(); - loops(); - return 0; -} diff --git a/libacc/tests/data/locals.c b/libacc/tests/data/locals.c deleted file mode 100644 index f1ef363..0000000 --- a/libacc/tests/data/locals.c +++ /dev/null @@ -1,71 +0,0 @@ -int a; - -int f() { - int a; - // Undefined variable b - // printf("f 0: a = %d b = %d\n", a, b); - printf("f 0: a = %d\n", a); - a = 2; - printf("f 1: a = %d\n", a); -} - -int g(int a) { - printf("g 0: a = %d\n", a); - a = 3; - printf("g 1: a = %d\n", a); -} - -int h(int a) { - // int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol - - printf("h 0: a = %d\n", a); - a = 4; - printf("h 1: a = %d\n", a); -} - -// Already defined global -// int h() {} -int globCheck() { - fprintf(stdout, "globCheck()\n"); -} - -int fwdCheck() { - b(); - // Undefined forward reference - // c(); -} - -int b() { - printf("b()\n"); -} - -int nested() { - int a; - printf("nested 0: a = %d\n", a); - a = 50; - printf("nested 1: a = %d\n", a); - { - int a; - printf("nested 2: a = %d\n", a); - a = 51; - printf("nested 3: a = %d\n", a); - } - printf("nested 4: a = %d\n", a); -} - -int main() { - globCheck(); - fwdCheck(); - printf("main 0: a = %d\n", a); - a = 5; - printf("main 1: a = %d\n", a); - f(); - printf("main 2: a = %d\n", a); - g(77); - printf("main 3: a = %d\n", a); - h(30); - printf("main 4: a = %d\n", a); - nested(); - printf("main 5: a = %d\n", a); - return 0; -} diff --git a/libacc/tests/data/macros.c b/libacc/tests/data/macros.c deleted file mode 100644 index 50e54dc..0000000 --- a/libacc/tests/data/macros.c +++ /dev/null @@ -1,10 +0,0 @@ -#define A B + B -#define B C - -int main() { - int C = 3; - printf("A = %d\n", A); -#define C 5 - printf("A = %d\n", A); - return 0; -} diff --git a/libacc/tests/data/missing-main.c b/libacc/tests/data/missing-main.c deleted file mode 100644 index e73eec4..0000000 --- a/libacc/tests/data/missing-main.c +++ /dev/null @@ -1,4 +0,0 @@ -/* No main. */ - -a() { -}
\ No newline at end of file diff --git a/libacc/tests/data/otcc-ansi.c b/libacc/tests/data/otcc-ansi.c deleted file mode 100644 index 72580e9..0000000 --- a/libacc/tests/data/otcc-ansi.c +++ /dev/null @@ -1,466 +0,0 @@ -// #include <stdio.h> -int d, z, C, h, P, K, ac, q, G, v, Q, R, D, L, W, M; - -void E(int e) { - *(char*) D++ = e; -} - -void o() { - if (L) { - h = *(char*) L++; - if (h == 2) { - L = 0; - h = W; - } - } else - h = fgetc(Q); -} - -int X() { - return isalnum(h) | h == 95; -} - -void Y() { - if (h == 92) { - o(); - if (h == 110) - h = 10; - } -} - -void ad() { - int e, j, m; - while (isspace(h) | h == 35) { - if (h == 35) { - o(); - ad(); - if (d == 536) { - ad(); - E(32); - *(int*) d = 1; - *(int*) (d + 4) = D; - } - while (h != 10) { - E(h); - o(); - } - E(h); - E(2); - } - o(); - } - C = 0; - d = h; - if (X()) { - E(32); - M = D; - while (X()) { - E(h); - o(); - } - if (isdigit(d)) { - z = strtol(M, 0, 0); - d = 2; - } else { - *(char*) D = 32; - d = strstr(R, M - 1) - R; - *(char*) D = 0; - d = d * 8 + 256; - if (d > 536) { - d = P + d; - if (*(int*) d == 1) { - L = *(int*) (d + 4); - W = h; - o(); - ad(); - } - } - } - } else { - o(); - if (d == 39) { - d = 2; - Y(); - z = h; - o(); - o(); - } else if (d == 47 & h == 42) { - o(); - while (h) { - while (h != 42) - o(); - o(); - if (h == 47) - h = 0; - } - o(); - ad(); - } else { - e - = "++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b"; - while (j = *(char*) e++) { - m = *(char*) e++; - z = 0; - while ((C = *(char*) e++ - 98) < 0) - z = z * 64 + C + 64; - if (j == d & (m == h | m == 64)) { - if (m == h) { - o(); - d = 1; - } - break; - } - } - } - } -} - -void ae(int g) { - while( g&&g!=-1) { - *(char*) q++=g; - g=g>>8; - } -} - -void A(int e) { - int g; - while( e) { - g=*(int*) e; - *(int*) e=q-e-4; - e=g; - } -} - -int s(int g, int e) { - ae(g); - *(int*) q = e; - e = q; - q = q + 4; - return e; -} - -void H(int e) { - s(184,e); -} - -int B(int e) { - return s(233,e); -} - -int S(int j, int e) { - ae(1032325); - return s(132 + j, e); -} - -void Z(int e) { - ae( 49465); - H(0); - ae( 15); - ae( e+144); - ae( 192); -} - -void N(int j, int e) { - ae(j + 131); - s((e > -512 && e < 512) << 7 | 5, e); -} - -void T (int j) { - int g,e,m,aa; - g=1; - if( d == 34) { - H(v); - while( h!=34) { - Y (); - *(char*) v++=h; - o (); - } - *(char*) v=0; - v=v +4&-4; - o (); - ad(); - } - else { - aa=C; - m= z; - e=d; - ad(); - if( e == 2) { - H(m); - } - else if( aa == 2) { - T(0); - s(185,0); - if( e == 33)Z(m); - else ae( m); - } - else if( e == 40) { - w (); - ad(); - } - else if( e == 42) { - ad(); - e=d; - ad(); - ad(); - if( d == 42) { - ad(); - ad(); - ad(); - ad(); - e=0; - } - ad(); - T(0); - if( d == 61) { - ad(); - ae( 80); - w (); - ae( 89); - ae( 392+(e == 256)); - } - else if( e) { - if( e == 256)ae( 139); - else ae( 48655); - q++; - } - } - else if( e == 38) { - N(10,*(int*) d); - ad(); - } - else { - g=*(int*) e; - if(!g)g=dlsym(0,M); - if( d == 61&j) { - ad(); - w (); - N(6,g); - } - else if( d!= 40) { - N(8,g); - if( C == 11) { - N(0,g); - ae( z); - ad(); - } - } - } - } - if( d == 40) { - if( g == 1)ae( 80); - m= s(60545,0); - ad(); - j=0; - while( d!= 41) { - w (); - s(2393225,j); - if( d == 44)ad(); - j=j +4; - } - *(int*) m= j; - ad(); - if(!g) { - e=e +4; - *(int*) e=s(232,*(int*) e); - } - else if( g == 1) { - s(2397439,j); - j=j +4; - } - else { - s(232,g-q-5); - } - if( j)s(50305,j); - } -} - -void O (int j) { - int e,g,m; - if( j--== 1)T(1); - else { - O (j); - m= 0; - while( j == C) { - g=d; - e=z; - ad(); - if( j>8) { - m= S(e,m); - O (j); - } - else { - ae( 80); - O (j); - ae( 89); - if( j == 4|j == 5) { - Z(e); - } - else { - ae( e); - if( g == 37)ae( 146); - } - } - } - if( m&&j>8) { - m= S(e,m); - H(e^1); - B(5); - A(m); - H(e); - } - } -} - -void w() { - O(11); -} - -int U() { - w(); - return S(0, 0); -} - -void I (int j) { - int m,g,e; - if( d == 288) { - ad(); - ad(); - m= U (); - ad(); - I (j); - if( d == 312) { - ad(); - g=B(0); - A(m); - I (j); - A(g); - } - else { - A(m); - } - } - else if( d == 352|d == 504) { - e=d; - ad(); - ad(); - if( e == 352) { - g=q; - m= U (); - } - else { - if( d!= 59)w (); - ad(); - g=q; - m= 0; - if( d!= 59)m= U (); - ad(); - if( d!= 41) { - e=B(0); - w (); - B(g-q-5); - A(e); - g=e +4; - } - } - ad(); - I(&m); - B(g-q-5); - A(m); - } - else if( d == 123) { - ad(); - ab(1); - while( d!= 125)I (j); - ad(); - } - else { - if( d == 448) { - ad(); - if( d!= 59)w (); - K=B(K); - } - else if( d == 400) { - ad(); - *(int*) j=B(*(int*) j); - } - else if( d!= 59)w (); - ad(); - } -} - -void ab (int j) { - int m; - while( d == 256|d!=-1&!j) { - if( d == 256) { - ad(); - while( d!= 59) { - if( j) { - G=G +4; - *(int*) d=-G; - } - else { - *(int*) d=v; - v=v +4; - } - ad(); - if( d == 44)ad() ; - } - ad(); - } - else { - A(*(int*)(d +4)); - *(int*) d=q; - ad(); - ad(); - m= 8; - while( d!= 41) { - *(int*) d=m; - m= m +4; - ad(); - if( d == 44)ad(); - } - ad(); - K=G=0; - ae( 15042901); - m= s(60545,0); - I(0); - A(K); - ae( 50121); - *(int*) m= G; - } - } -} - -int run(int g, int e) { - return (*(int(*)()) *(int*) (P + 592))(g, e); -} - -int main(int g, int e) { - int result; - Q = stdin; - if (g-- > 1) { - e = e + 4; - Q = fopen(*(int*) e, "r"); - if (!Q) { - fprintf(stderr, "otcc-ansi.c: could not open file %s\n", *(int*) e); - return -2; - } - } - D = strcpy(R = calloc(1, 99999), " int if else while break return for define main ") + 48; - v = calloc(1, 99999); - q = ac = calloc(1, 99999); - P = calloc(1, 99999); - o(); - ad(); - ab(0); - if (mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7)) { - printf("Mprotect failed. %d\n", errno); - return -1; - } - fprintf(stderr, "otcc-ansi.c: About to execute compiled code:\n"); - result = run(g, e); - fprintf(stderr, "atcc-ansi.c: result: %d\n", result); - return result; -} - diff --git a/libacc/tests/data/otcc-noinclude.c b/libacc/tests/data/otcc-noinclude.c deleted file mode 100644 index 530f9e2..0000000 --- a/libacc/tests/data/otcc-noinclude.c +++ /dev/null @@ -1,446 +0,0 @@ -// #include <stdio.h> -#define k *(int*) -#define a if( -#define c ad() -#define i else -#define p while( -#define x *(char*) -#define b == -#define V =calloc(1,99999) -#define f () -#define J return -#define l ae( -#define n e) -#define u d!= -#define F int -#define y (j) -#define r m= -#define t +4 -F d,z,C,h,P,K,ac,q,G,v,Q,R,D,L,W,M; -E(n{ -x D++=e; -} -o f{ -a L){ -h=x L++; -a h b 2){ -L=0; -h=W; -} -} -i h=fgetc(Q); -} -X f{ -J isalnum(h)|h b 95; -} -Y f{ -a h b 92){ -o f; -a h b 110)h=10; -} -} -c{ -F e,j,m; -p isspace(h)|h b 35){ -a h b 35){ -o f; -c; -a d b 536){ -c; -E(32); -k d=1; -k(d t)=D; -} -p h!=10){ -E(h); -o f; -} -E(h); -E(2); -} -o f; -} -C=0; -d=h; -a X f){ -E(32); -M=D; -p X f){ -E(h); -o f; -} -a isdigit(d)){ -z=strtol(M,0,0); -d=2; -} -i{ -x D=32; -d=strstr(R,M-1)-R; -x D=0; -d=d*8+256; -a d>536){ -d=P+d; -a k d b 1){ -L=k(d t); -W=h; -o f; -c; -} -} -} -} -i{ -o f; -a d b 39){ -d=2; -Y f; -z=h; -o f; -o f; -} -i a d b 47&h b 42){ -o f; -p h){ -p h!=42)o f; -o f; -a h b 47)h=0; -} -o f; -c; -} -i{ -e="++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b"; -p j=x e++){ -r x e++; -z=0; -p(C=x e++-98)<0)z=z*64+C+64; -a j b d&(m b h|m b 64)){ -a m b h){ -o f; -d=1; -} -break; -} -} -} -} -} -l g){ -p g&&g!=-1){ -x q++=g; -g=g>>8; -} -} -A(n{ -F g; -p n{ -g=k e; -k e=q-e-4; -e=g; -} -} -s(g,n{ -l g); -k q=e; -e=q; -q=q t; -J e; -} -H(n{ -s(184,n; -} -B(n{ -J s(233,n; -} -S(j,n{ -l 1032325); -J s(132+j,n; -} -Z(n{ -l 49465); -H(0); -l 15); -l e+144); -l 192); -} -N(j,n{ -l j+131); -s((e<512)<<7|5,n; -} -T y{ -F g,e,m,aa; -g=1; -a d b 34){ -H(v); -p h!=34){ -Y f; -x v++=h; -o f; -} -x v=0; -v=v t&-4; -o f; -c; -} -i{ -aa=C; -r z; -e=d; -c; -a e b 2){ -H(m); -} -i a aa b 2){ -T(0); -s(185,0); -a e b 33)Z(m); -i l m); -} -i a e b 40){ -w f; -c; -} -i a e b 42){ -c; -e=d; -c; -c; -a d b 42){ -c; -c; -c; -c; -e=0; -} -c; -T(0); -a d b 61){ -c; -l 80); -w f; -l 89); -l 392+(e b 256)); -} -i a n{ -a e b 256)l 139); -i l 48655); -q++; -} -} -i a e b 38){ -N(10,k d); -c; -} -i{ -g=k e; -a!g)g=dlsym(0,M); -a d b 61&j){ -c; -w f; -N(6,g); -} -i a u 40){ -N(8,g); -a C b 11){ -N(0,g); -l z); -c; -} -} -} -} -a d b 40){ -a g b 1)l 80); -r s(60545,0); -c; -j=0; -p u 41){ -w f; -s(2393225,j); -a d b 44)c; -j=j t; -} -k r j; -c; -a!g){ -e=e t; -k e=s(232,k n; -} -i a g b 1){ -s(2397439,j); -j=j t; -} -i{ -s(232,g-q-5); -} -a j)s(50305,j); -} -} -O y{ -F e,g,m; -a j--b 1)T(1); -i{ -O y; -r 0; -p j b C){ -g=d; -e=z; -c; -a j>8){ -r S(e,m); -O y; -} -i{ -l 80); -O y; -l 89); -a j b 4|j b 5){ -Z(n; -} -i{ -l n; -a g b 37)l 146); -} -} -} -a m&&j>8){ -r S(e,m); -H(e^1); -B(5); -A(m); -H(n; -} -} -} -w f{ -O(11); -} -U f{ -w f; -J S(0,0); -} -I y{ -F m,g,e; -a d b 288){ -c; -c; -r U f; -c; -I y; -a d b 312){ -c; -g=B(0); -A(m); -I y; -A(g); -} -i{ -A(m); -} -} -i a d b 352|d b 504){ -e=d; -c; -c; -a e b 352){ -g=q; -r U f; -} -i{ -a u 59)w f; -c; -g=q; -r 0; -a u 59)r U f; -c; -a u 41){ -e=B(0); -w f; -B(g-q-5); -A(n; -g=e t; -} -} -c; -I(&m); -B(g-q-5); -A(m); -} -i a d b 123){ -c; -ab(1); -p u 125)I y; -c; -} -i{ -a d b 448){ -c; -a u 59)w f; -K=B(K); -} -i a d b 400){ -c; -k j=B(k j); -} -i a u 59)w f; -c; -} -} -ab y{ -F m; -p d b 256|u-1&!j){ -a d b 256){ -c; -p u 59){ -a j){ -G=G t; -k d=-G; -} -i{ -k d=v; -v=v t; -} -c; -a d b 44)c; -} -c; -} -i{ -A(k(d t)); -k d=q; -c; -c; -r 8; -p u 41){ -k d=m; -r m t; -c; -a d b 44)c; -} -c; -K=G=0; -l 15042901); -r s(60545,0); -I(0); -A(K); -l 50121); -k r G; -} -} -} -main(g,n{ -Q=stdin; -a g-->1){ -e=e t; -Q=fopen(k e,"r"); -} -D=strcpy(R V," int if else while break return for define main ")+48; -v V; -q=ac V; -P V; -o f; -c; -ab(0); -J(*(int(*)f)k(P+592))(g,n; -} - diff --git a/libacc/tests/data/otcc.c b/libacc/tests/data/otcc.c deleted file mode 100644 index 433ae2e..0000000 --- a/libacc/tests/data/otcc.c +++ /dev/null @@ -1,448 +0,0 @@ -#include <stdio.h> -#define k *(int*) -#define a if( -#define c ad() -#define i else -#define p while( -#define x *(char*) -#define b == -#define V =calloc(1,99999) -#define f () -#define J return -#define l ae( -#define n e) -#define u d!= -#define F int -#define y (j) -#define r m= -#define t +4 -F d,z,C,h,P,K,ac,q,G,v,Q,R,D,L,W,M; -E(n{ -x D++=e; -} -o f{ -a L){ -h=x L++; -a h b 2){ -L=0; -h=W; -} -} -i h=fgetc(Q); -} -X f{ -J isalnum(h)|h b 95; -} -Y f{ -a h b 92){ -o f; -a h b 110)h=10; -} -} -c{ -F e,j,m; -p isspace(h)|h b 35){ -a h b 35){ -o f; -c; -a d b 536){ -c; -E(32); -k d=1; -k(d t)=D; -} -p h!=10){ -E(h); -o f; -} -E(h); -E(2); -} -o f; -} -C=0; -d=h; -a X f){ -E(32); -M=D; -p X f){ -E(h); -o f; -} -a isdigit(d)){ -z=strtol(M,0,0); -d=2; -} -i{ -x D=32; -d=strstr(R,M-1)-R; -x D=0; -d=d*8+256; -a d>536){ -d=P+d; -a k d b 1){ -L=k(d t); -W=h; -o f; -c; -} -} -} -} -i{ -o f; -a d b 39){ -d=2; -Y f; -z=h; -o f; -o f; -} -i a d b 47&h b 42){ -o f; -p h){ -p h!=42)o f; -o f; -a h b 47)h=0; -} -o f; -c; -} -i{ -e="++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b"; -p j=x e++){ -r x e++; -z=0; -p(C=x e++-98)<0)z=z*64+C+64; -a j b d&(m b h|m b 64)){ -a m b h){ -o f; -d=1; -} -break; -} -} -} -} -} -l g){ -p g&&g!=-1){ -x q++=g; -g=g>>8; -} -} -A(n{ -F g; -p n{ -g=k e; -k e=q-e-4; -e=g; -} -} -s(g,n{ -l g); -k q=e; -e=q; -q=q t; -J e; -} -H(n{ -s(184,n; -} -B(n{ -J s(233,n; -} -S(j,n{ -l 1032325); -J s(132+j,n; -} -Z(n{ -l 49465); -H(0); -l 15); -l e+144); -l 192); -} -N(j,n{ -l j+131); -s((e<512)<<7|5,n; -} -T y{ -F g,e,m,aa; -g=1; -a d b 34){ -H(v); -p h!=34){ -Y f; -x v++=h; -o f; -} -x v=0; -v=v t&-4; -o f; -c; -} -i{ -aa=C; -r z; -e=d; -c; -a e b 2){ -H(m); -} -i a aa b 2){ -T(0); -s(185,0); -a e b 33)Z(m); -i l m); -} -i a e b 40){ -w f; -c; -} -i a e b 42){ -c; -e=d; -c; -c; -a d b 42){ -c; -c; -c; -c; -e=0; -} -c; -T(0); -a d b 61){ -c; -l 80); -w f; -l 89); -l 392+(e b 256)); -} -i a n{ -a e b 256)l 139); -i l 48655); -q++; -} -} -i a e b 38){ -N(10,k d); -c; -} -i{ -g=k e; -a!g)g=dlsym(0,M); -a d b 61&j){ -c; -w f; -N(6,g); -} -i a u 40){ -N(8,g); -a C b 11){ -N(0,g); -l z); -c; -} -} -} -} -a d b 40){ -a g b 1)l 80); -r s(60545,0); -c; -j=0; -p u 41){ -w f; -s(2393225,j); -a d b 44)c; -j=j t; -} -k r j; -c; -a!g){ -e=e t; -k e=s(232,k n; -} -i a g b 1){ -s(2397439,j); -j=j t; -} -i{ -s(232,g-q-5); -} -a j)s(50305,j); -} -} -O y{ -F e,g,m; -a j--b 1)T(1); -i{ -O y; -r 0; -p j b C){ -g=d; -e=z; -c; -a j>8){ -r S(e,m); -O y; -} -i{ -l 80); -O y; -l 89); -a j b 4|j b 5){ -Z(n; -} -i{ -l n; -a g b 37)l 146); -} -} -} -a m&&j>8){ -r S(e,m); -H(e^1); -B(5); -A(m); -H(n; -} -} -} -w f{ -O(11); -} -U f{ -w f; -J S(0,0); -} -I y{ -F m,g,e; -a d b 288){ -c; -c; -r U f; -c; -I y; -a d b 312){ -c; -g=B(0); -A(m); -I y; -A(g); -} -i{ -A(m); -} -} -i a d b 352|d b 504){ -e=d; -c; -c; -a e b 352){ -g=q; -r U f; -} -i{ -a u 59)w f; -c; -g=q; -r 0; -a u 59)r U f; -c; -a u 41){ -e=B(0); -w f; -B(g-q-5); -A(n; -g=e t; -} -} -c; -I(&m); -B(g-q-5); -A(m); -} -i a d b 123){ -c; -ab(1); -p u 125)I y; -c; -} -i{ -a d b 448){ -c; -a u 59)w f; -K=B(K); -} -i a d b 400){ -c; -k j=B(k j); -} -i a u 59)w f; -c; -} -} -ab y{ -F m; -p d b 256|u-1&!j){ -a d b 256){ -c; -p u 59){ -a j){ -G=G t; -k d=-G; -} -i{ -k d=v; -v=v t; -} -c; -a d b 44)c; -} -c; -} -i{ -A(k(d t)); -k d=q; -c; -c; -r 8; -p u 41){ -k d=m; -r m t; -c; -a d b 44)c; -} -c; -K=G=0; -l 15042901); -r s(60545,0); -I(0); -A(K); -l 50121); -k r G; -} -} -} -main(g,n{ -Q=stdin; -a g-->1){ -e=e t; -Q=fopen(k e,"r"); -} -D=strcpy(R V," int if else while break return for define main ")+48; -v V; -q=ac V; -P V; -o f; -c; -ab(0); -mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7); -fprintf(stderr, "otcc.c: about to execute compiled code.\n"); -J(*(int(*)f)k(P+592))(g,n; -} - diff --git a/libacc/tests/data/pointers.c b/libacc/tests/data/pointers.c deleted file mode 100644 index 461ebeb..0000000 --- a/libacc/tests/data/pointers.c +++ /dev/null @@ -1,15 +0,0 @@ -int main() { - int* pa = (int*) malloc(100); - int* pb = pa + 1; - int* pc = (int*) 0; - *pa = 1; - *pb = 2; - printf("Pointer difference: %d %d\n", pb - pa, ((int) pb) - ((int) pa)); - int c = * (pa + 1); - printf("Pointer addition: %d\n", c); - printf("Pointer comparison to zero: %d %d %d\n", pa == 0, pb == 0, pc == 0); - printf("Pointer comparison: %d %d %d %d %d\n", pa < pb, pa == pb, pa > pb, ! pb, ! pc); - free(pa); - return 0; -} - diff --git a/libacc/tests/data/pointers2.c b/libacc/tests/data/pointers2.c deleted file mode 100644 index 69e402f..0000000 --- a/libacc/tests/data/pointers2.c +++ /dev/null @@ -1,35 +0,0 @@ -// Test multiple levels of indirection - -void testsingle() { - int a = 0; - int* pa = &a; - printf("a = %d, *pa = %d\n", a, *pa); - *pa = 2; - printf("a = %d, *pa = %d\n", a, *pa); -} - -void testdouble() { - int a = 0; - int* pa = &a; - int** ppa = &pa; - printf("a = %d, *pa = %d **ppa = %d\n", a, *pa, **ppa); - **ppa = 2; - printf("a = %d, *pa = %d **ppa = %d\n", a, *pa, **ppa); -} - -void testtripple() { - int a = 0; - int* pa = &a; - int** ppa = &pa; - int*** pppa = &ppa; - printf("a = %d, *pa = %d **ppa = %d\n ***pppa = %d", a, *pa, **ppa, ***pppa); - ***pppa = 2; - printf("a = %d, *pa = %d **ppa = %d\n ***pppa = %d", a, *pa, **ppa, ***pppa); -} - -int main() { - testsingle(); - testdouble(); - testdouble(); - return 0; -} diff --git a/libacc/tests/data/returnval-ansi.c b/libacc/tests/data/returnval-ansi.c deleted file mode 100644 index 6b53fd5..0000000 --- a/libacc/tests/data/returnval-ansi.c +++ /dev/null @@ -1,8 +0,0 @@ - -int main(int argc, char** argv) { - return f(); -} - -int f() { - return 42; -} diff --git a/libacc/tests/data/returnval.c b/libacc/tests/data/returnval.c deleted file mode 100644 index 1cf5bae..0000000 --- a/libacc/tests/data/returnval.c +++ /dev/null @@ -1,4 +0,0 @@ -main() { - return 42; -} - diff --git a/libacc/tests/data/rollo3.c b/libacc/tests/data/rollo3.c deleted file mode 100644 index b21c12f..0000000 --- a/libacc/tests/data/rollo3.c +++ /dev/null @@ -1,9 +0,0 @@ - -float fabsf(float); - -int main(void* con, int ft, int launchID) -{ - float f = fabsf(-10.0f); - return f; -} - diff --git a/libacc/tests/data/short.c b/libacc/tests/data/short.c deleted file mode 100644 index 5e222f3..0000000 --- a/libacc/tests/data/short.c +++ /dev/null @@ -1,6 +0,0 @@ -short a = 3; -int main() { - short* b = &a; - *b = *b - 5; - return a; -} diff --git a/libacc/tests/data/simplest.c b/libacc/tests/data/simplest.c deleted file mode 100644 index bae895a..0000000 --- a/libacc/tests/data/simplest.c +++ /dev/null @@ -1 +0,0 @@ -main() {} diff --git a/libacc/tests/data/structs.c b/libacc/tests/data/structs.c deleted file mode 100644 index dd81af3..0000000 --- a/libacc/tests/data/structs.c +++ /dev/null @@ -1,95 +0,0 @@ -// struct definition and declaration -struct a { - int a; - int b; -} c; - -// Useless, but legal struct declaration -struct { - int x; -}; - -// Useful anonymous struct declaration -struct { - int y; -} anon1, anon2; - -// forward declarations -struct a; -struct b; -struct c; - -struct b {int a; int b; }; - -// struct c {b g; }; // syntax error. - -// struct s {float c,a,b,c;} s; // duplicate struct member - -struct c {struct b g; }; - -// struct a { int w; }; // error - -void testCopying() { - struct a {int a[10]; char c;} a, b; - a.c = 37; - b.c = 38; - b = a; - printf("testCopying: %d == %d\n", a.c, b.c); -} - -void testUnion() { - union u; - union u {float f;int i;} u; - u.f = 1.0f; - printf("testUnion: %g == 0x%08x\n", u.f, u.i); -} - -struct v {float x, y, z, w; }; - -void add(struct v* result, struct v* a, struct v* b) { - result->x = a->x + b->x; - result->y = a->y + b->y; - result->z = a->z + b->z; - result->w = a->w + b->w; -} - -void set(struct v* v, float x, float y, float z, float w) { - v->x = x; - v->y = y; - v->z = z; - v->w = w; -} - -void print(struct v* v) { - printf("(%g, %g, %g, %g)\n", v->x, v->y, v->z, v->w); -} - -void testArgs() { - struct v a, b, c; - set(&a, 1.0f, 2.0f, 3.0f, 4.0f); - set(&b, 5.0f, 6.0f, 7.0f, 8.0f); - add(&c, &a, &b); - printf("testArgs: "); - print(&c); -} - -int main() { - anon1.y = 3; - anon2.y = anon1.y; - - testCopying(); - testUnion(); - testArgs(); - - struct c cc; - cc.g.a = 3; - c.a = 1; - c.b = 3; - struct a {int x, y; } z; - // struct a {int x, y; } z2; - z.x = c.a; - struct a *pA; - pA = &z; - pA->x += 5; - return pA->x; -} diff --git a/libacc/tests/data/testStringConcat.c b/libacc/tests/data/testStringConcat.c deleted file mode 100644 index bf06ae1..0000000 --- a/libacc/tests/data/testStringConcat.c +++ /dev/null @@ -1,4 +0,0 @@ -int main() { - return printf("Hello" "," " world\n"); -} - diff --git a/libacc/tests/data/typedef.c b/libacc/tests/data/typedef.c deleted file mode 100644 index c392f6a..0000000 --- a/libacc/tests/data/typedef.c +++ /dev/null @@ -1,40 +0,0 @@ -typedef short COORD; -typedef struct Point { - COORD x; - COORD y; -} Point; - -void add(Point* result, Point* a, Point* b) { - result->x = a->x + b->x; - result->y = a->y + b->y; -} - -void print(Point* p) { - printf("(%d, %d)", p->x, p->y); -} - -void set(Point* p, int x, int y) { - p->x = x; - p->y = y; -} - -int main() { - typedef char* String; - String s = "x = %d\n"; - { - typedef int item; - item x = 3; - printf(s, x); - } - Point a, b, c; - set(&a, 1,2); - set(&b, 3,4); - add(&c, &a, &b); - print(&c); - printf(" = "); - print(&a); - printf(" + "); - print(&b); - printf("\n"); - return 0; -} diff --git a/libacc/tests/disassem.cpp b/libacc/tests/disassem.cpp deleted file mode 100644 index ac35342..0000000 --- a/libacc/tests/disassem.cpp +++ /dev/null @@ -1,711 +0,0 @@ -/* $NetBSD: disassem.c,v 1.14 2003/03/27 16:58:36 mycroft Exp $ */ - -/*- - * Copyright (c) 1996 Mark Brinicombe. - * Copyright (c) 1996 Brini. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Brini. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * RiscBSD kernel project - * - * db_disasm.c - * - * Kernel disassembler - * - * Created : 10/02/96 - * - * Structured after the sparc/sparc/db_disasm.c by David S. Miller & - * Paul Kranenburg - * - * This code is not complete. Not all instructions are disassembled. - */ - -#include <sys/cdefs.h> -//__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/arm/arm/disassem.c,v 1.2 2005/01/05 21:58:47 imp Exp $"); -#include <sys/param.h> -#include <stdio.h> -#include <stdarg.h> - -#include "disassem.h" -#include "armreg.h" -//#include <ddb/ddb.h> - -/* - * General instruction format - * - * insn[cc][mod] [operands] - * - * Those fields with an uppercase format code indicate that the field - * follows directly after the instruction before the separator i.e. - * they modify the instruction rather than just being an operand to - * the instruction. The only exception is the writeback flag which - * follows a operand. - * - * - * 2 - print Operand 2 of a data processing instruction - * d - destination register (bits 12-15) - * n - n register (bits 16-19) - * s - s register (bits 8-11) - * o - indirect register rn (bits 16-19) (used by swap) - * m - m register (bits 0-3) - * a - address operand of ldr/str instruction - * e - address operand of ldrh/strh instruction - * l - register list for ldm/stm instruction - * f - 1st fp operand (register) (bits 12-14) - * g - 2nd fp operand (register) (bits 16-18) - * h - 3rd fp operand (register/immediate) (bits 0-4) - * b - branch address - * t - thumb branch address (bits 24, 0-23) - * k - breakpoint comment (bits 0-3, 8-19) - * X - block transfer type - * Y - block transfer type (r13 base) - * c - comment field bits(0-23) - * p - saved or current status register - * F - PSR transfer fields - * D - destination-is-r15 (P) flag on TST, TEQ, CMP, CMN - * L - co-processor transfer size - * S - set status flag - * P - fp precision - * Q - fp precision (for ldf/stf) - * R - fp rounding - * v - co-processor data transfer registers + addressing mode - * W - writeback flag - * x - instruction in hex - * # - co-processor number - * y - co-processor data processing registers - * z - co-processor register transfer registers - */ - -struct arm32_insn { - u_int mask; - u_int pattern; - const char* name; - const char* format; -}; - -static const struct arm32_insn arm32_i[] = { - { 0x0fffffff, 0x0ff00000, "imb", "c" }, /* Before swi */ - { 0x0fffffff, 0x0ff00001, "imbrange", "c" }, /* Before swi */ - { 0x0f000000, 0x0f000000, "swi", "c" }, - { 0xfe000000, 0xfa000000, "blx", "t" }, /* Before b and bl */ - { 0x0f000000, 0x0a000000, "b", "b" }, - { 0x0f000000, 0x0b000000, "bl", "b" }, - { 0x0fe000f0, 0x00000090, "mul", "Snms" }, - { 0x0fe000f0, 0x00200090, "mla", "Snmsd" }, - { 0x0fe000f0, 0x00800090, "umull", "Sdnms" }, - { 0x0fe000f0, 0x00c00090, "smull", "Sdnms" }, - { 0x0fe000f0, 0x00a00090, "umlal", "Sdnms" }, - { 0x0fe000f0, 0x00e00090, "smlal", "Sdnms" }, - { 0x0d700000, 0x04200000, "strt", "daW" }, - { 0x0d700000, 0x04300000, "ldrt", "daW" }, - { 0x0d700000, 0x04600000, "strbt", "daW" }, - { 0x0d700000, 0x04700000, "ldrbt", "daW" }, - { 0x0c500000, 0x04000000, "str", "daW" }, - { 0x0c500000, 0x04100000, "ldr", "daW" }, - { 0x0c500000, 0x04400000, "strb", "daW" }, - { 0x0c500000, 0x04500000, "ldrb", "daW" }, - { 0x0e1f0000, 0x080d0000, "stm", "YnWl" },/* separate out r13 base */ - { 0x0e1f0000, 0x081d0000, "ldm", "YnWl" },/* separate out r13 base */ - { 0x0e100000, 0x08000000, "stm", "XnWl" }, - { 0x0e100000, 0x08100000, "ldm", "XnWl" }, - { 0x0e1000f0, 0x00100090, "ldrb", "deW" }, - { 0x0e1000f0, 0x00000090, "strb", "deW" }, - { 0x0e1000f0, 0x001000d0, "ldrsb", "deW" }, - { 0x0e1000f0, 0x001000b0, "ldrh", "deW" }, - { 0x0e1000f0, 0x000000b0, "strh", "deW" }, - { 0x0e1000f0, 0x001000f0, "ldrsh", "deW" }, - { 0x0f200090, 0x00200090, "und", "x" }, /* Before data processing */ - { 0x0e1000d0, 0x000000d0, "und", "x" }, /* Before data processing */ - { 0x0ff00ff0, 0x01000090, "swp", "dmo" }, - { 0x0ff00ff0, 0x01400090, "swpb", "dmo" }, - { 0x0fbf0fff, 0x010f0000, "mrs", "dp" }, /* Before data processing */ - { 0x0fb0fff0, 0x0120f000, "msr", "pFm" },/* Before data processing */ - { 0x0fb0f000, 0x0320f000, "msr", "pF2" },/* Before data processing */ - { 0x0ffffff0, 0x012fff10, "bx", "m" }, - { 0x0fff0ff0, 0x016f0f10, "clz", "dm" }, - { 0x0ffffff0, 0x012fff30, "blx", "m" }, - { 0xfff000f0, 0xe1200070, "bkpt", "k" }, - { 0x0de00000, 0x00000000, "and", "Sdn2" }, - { 0x0de00000, 0x00200000, "eor", "Sdn2" }, - { 0x0de00000, 0x00400000, "sub", "Sdn2" }, - { 0x0de00000, 0x00600000, "rsb", "Sdn2" }, - { 0x0de00000, 0x00800000, "add", "Sdn2" }, - { 0x0de00000, 0x00a00000, "adc", "Sdn2" }, - { 0x0de00000, 0x00c00000, "sbc", "Sdn2" }, - { 0x0de00000, 0x00e00000, "rsc", "Sdn2" }, - { 0x0df00000, 0x01100000, "tst", "Dn2" }, - { 0x0df00000, 0x01300000, "teq", "Dn2" }, - { 0x0df00000, 0x01500000, "cmp", "Dn2" }, - { 0x0df00000, 0x01700000, "cmn", "Dn2" }, - { 0x0de00000, 0x01800000, "orr", "Sdn2" }, - { 0x0de00000, 0x01a00000, "mov", "Sd2" }, - { 0x0de00000, 0x01c00000, "bic", "Sdn2" }, - { 0x0de00000, 0x01e00000, "mvn", "Sd2" }, - { 0x0ff08f10, 0x0e000100, "adf", "PRfgh" }, - { 0x0ff08f10, 0x0e100100, "muf", "PRfgh" }, - { 0x0ff08f10, 0x0e200100, "suf", "PRfgh" }, - { 0x0ff08f10, 0x0e300100, "rsf", "PRfgh" }, - { 0x0ff08f10, 0x0e400100, "dvf", "PRfgh" }, - { 0x0ff08f10, 0x0e500100, "rdf", "PRfgh" }, - { 0x0ff08f10, 0x0e600100, "pow", "PRfgh" }, - { 0x0ff08f10, 0x0e700100, "rpw", "PRfgh" }, - { 0x0ff08f10, 0x0e800100, "rmf", "PRfgh" }, - { 0x0ff08f10, 0x0e900100, "fml", "PRfgh" }, - { 0x0ff08f10, 0x0ea00100, "fdv", "PRfgh" }, - { 0x0ff08f10, 0x0eb00100, "frd", "PRfgh" }, - { 0x0ff08f10, 0x0ec00100, "pol", "PRfgh" }, - { 0x0f008f10, 0x0e000100, "fpbop", "PRfgh" }, - { 0x0ff08f10, 0x0e008100, "mvf", "PRfh" }, - { 0x0ff08f10, 0x0e108100, "mnf", "PRfh" }, - { 0x0ff08f10, 0x0e208100, "abs", "PRfh" }, - { 0x0ff08f10, 0x0e308100, "rnd", "PRfh" }, - { 0x0ff08f10, 0x0e408100, "sqt", "PRfh" }, - { 0x0ff08f10, 0x0e508100, "log", "PRfh" }, - { 0x0ff08f10, 0x0e608100, "lgn", "PRfh" }, - { 0x0ff08f10, 0x0e708100, "exp", "PRfh" }, - { 0x0ff08f10, 0x0e808100, "sin", "PRfh" }, - { 0x0ff08f10, 0x0e908100, "cos", "PRfh" }, - { 0x0ff08f10, 0x0ea08100, "tan", "PRfh" }, - { 0x0ff08f10, 0x0eb08100, "asn", "PRfh" }, - { 0x0ff08f10, 0x0ec08100, "acs", "PRfh" }, - { 0x0ff08f10, 0x0ed08100, "atn", "PRfh" }, - { 0x0f008f10, 0x0e008100, "fpuop", "PRfh" }, - { 0x0e100f00, 0x0c000100, "stf", "QLv" }, - { 0x0e100f00, 0x0c100100, "ldf", "QLv" }, - { 0x0ff00f10, 0x0e000110, "flt", "PRgd" }, - { 0x0ff00f10, 0x0e100110, "fix", "PRdh" }, - { 0x0ff00f10, 0x0e200110, "wfs", "d" }, - { 0x0ff00f10, 0x0e300110, "rfs", "d" }, - { 0x0ff00f10, 0x0e400110, "wfc", "d" }, - { 0x0ff00f10, 0x0e500110, "rfc", "d" }, - { 0x0ff0ff10, 0x0e90f110, "cmf", "PRgh" }, - { 0x0ff0ff10, 0x0eb0f110, "cnf", "PRgh" }, - { 0x0ff0ff10, 0x0ed0f110, "cmfe", "PRgh" }, - { 0x0ff0ff10, 0x0ef0f110, "cnfe", "PRgh" }, - { 0xff100010, 0xfe000010, "mcr2", "#z" }, - { 0x0f100010, 0x0e000010, "mcr", "#z" }, - { 0xff100010, 0xfe100010, "mrc2", "#z" }, - { 0x0f100010, 0x0e100010, "mrc", "#z" }, - { 0xff000010, 0xfe000000, "cdp2", "#y" }, - { 0x0f000010, 0x0e000000, "cdp", "#y" }, - { 0xfe100090, 0xfc100000, "ldc2", "L#v" }, - { 0x0e100090, 0x0c100000, "ldc", "L#v" }, - { 0xfe100090, 0xfc000000, "stc2", "L#v" }, - { 0x0e100090, 0x0c000000, "stc", "L#v" }, - { 0xf550f000, 0xf550f000, "pld", "ne" }, - { 0x0ff00ff0, 0x01000050, "qaad", "dmn" }, - { 0x0ff00ff0, 0x01400050, "qdaad", "dmn" }, - { 0x0ff00ff0, 0x01600050, "qdsub", "dmn" }, - { 0x0ff00ff0, 0x01200050, "dsub", "dmn" }, - { 0x0ff000f0, 0x01000080, "smlabb", "nmsd" }, // d & n inverted!! - { 0x0ff000f0, 0x010000a0, "smlatb", "nmsd" }, // d & n inverted!! - { 0x0ff000f0, 0x010000c0, "smlabt", "nmsd" }, // d & n inverted!! - { 0x0ff000f0, 0x010000e0, "smlatt", "nmsd" }, // d & n inverted!! - { 0x0ff000f0, 0x01400080, "smlalbb","ndms" }, // d & n inverted!! - { 0x0ff000f0, 0x014000a0, "smlaltb","ndms" }, // d & n inverted!! - { 0x0ff000f0, 0x014000c0, "smlalbt","ndms" }, // d & n inverted!! - { 0x0ff000f0, 0x014000e0, "smlaltt","ndms" }, // d & n inverted!! - { 0x0ff000f0, 0x01200080, "smlawb", "nmsd" }, // d & n inverted!! - { 0x0ff0f0f0, 0x012000a0, "smulwb","nms" }, // d & n inverted!! - { 0x0ff000f0, 0x012000c0, "smlawt", "nmsd" }, // d & n inverted!! - { 0x0ff0f0f0, 0x012000e0, "smulwt","nms" }, // d & n inverted!! - { 0x0ff0f0f0, 0x01600080, "smulbb","nms" }, // d & n inverted!! - { 0x0ff0f0f0, 0x016000a0, "smultb","nms" }, // d & n inverted!! - { 0x0ff0f0f0, 0x016000c0, "smulbt","nms" }, // d & n inverted!! - { 0x0ff0f0f0, 0x016000e0, "smultt","nms" }, // d & n inverted!! - { 0x00000000, 0x00000000, NULL, NULL } -}; - -static char const arm32_insn_conditions[][4] = { - "eq", "ne", "cs", "cc", - "mi", "pl", "vs", "vc", - "hi", "ls", "ge", "lt", - "gt", "le", "", "nv" -}; - -static char const insn_block_transfers[][4] = { - "da", "ia", "db", "ib" -}; - -static char const insn_stack_block_transfers[][4] = { - "ed", "ea", "fd", "fa" -}; - -static char const op_shifts[][4] = { - "lsl", "lsr", "asr", "ror" -}; - -static char const insn_fpa_rounding[][2] = { - "", "p", "m", "z" -}; - -static char const insn_fpa_precision[][2] = { - "s", "d", "e", "p" -}; - -static char const insn_fpaconstants[][8] = { - "0.0", "1.0", "2.0", "3.0", - "4.0", "5.0", "0.5", "10.0" -}; - -#define insn_condition(x) arm32_insn_conditions[(x >> 28) & 0x0f] -#define insn_blktrans(x) insn_block_transfers[(x >> 23) & 3] -#define insn_stkblktrans(x) insn_stack_block_transfers[(x >> 23) & 3] -#define op2_shift(x) op_shifts[(x >> 5) & 3] -#define insn_fparnd(x) insn_fpa_rounding[(x >> 5) & 0x03] -#define insn_fpaprec(x) insn_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 1] -#define insn_fpaprect(x) insn_fpa_precision[(((x >> 21) & 2)|(x >> 15)) & 1] -#define insn_fpaimm(x) insn_fpaconstants[x & 0x07] - -/* Local prototypes */ -static void disasm_register_shift(const disasm_interface_t *di, u_int insn); -static void disasm_print_reglist(const disasm_interface_t *di, u_int insn); -static void disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn, - u_int loc); -static void disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn, - u_int loc); -static void disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, - u_int loc); -static u_int disassemble_readword(u_int address); -static void disassemble_printaddr(u_int address); - -u_int -disasm(const disasm_interface_t *di, u_int loc, int altfmt) -{ - const struct arm32_insn *i_ptr = &arm32_i[0]; - - u_int insn; - int matchp; - int branch; - const char* f_ptr; - int fmt; - - fmt = 0; - matchp = 0; - insn = di->di_readword(loc); - -/* di->di_printf("loc=%08x insn=%08x : ", loc, insn);*/ - - while (i_ptr->name) { - if ((insn & i_ptr->mask) == i_ptr->pattern) { - matchp = 1; - break; - } - i_ptr++; - } - - if (!matchp) { - di->di_printf("und%s\t%08x\n", insn_condition(insn), insn); - return(loc + INSN_SIZE); - } - - /* If instruction forces condition code, don't print it. */ - if ((i_ptr->mask & 0xf0000000) == 0xf0000000) - di->di_printf("%s", i_ptr->name); - else - di->di_printf("%s%s", i_ptr->name, insn_condition(insn)); - - f_ptr = i_ptr->format; - - /* Insert tab if there are no instruction modifiers */ - - if (*(f_ptr) < 'A' || *(f_ptr) > 'Z') { - ++fmt; - di->di_printf("\t"); - } - - while (*f_ptr) { - switch (*f_ptr) { - /* 2 - print Operand 2 of a data processing instruction */ - case '2': - if (insn & 0x02000000) { - int rotate= ((insn >> 7) & 0x1e); - - di->di_printf("#0x%08x", - (insn & 0xff) << (32 - rotate) | - (insn & 0xff) >> rotate); - } else { - disasm_register_shift(di, insn); - } - break; - /* d - destination register (bits 12-15) */ - case 'd': - di->di_printf("r%d", ((insn >> 12) & 0x0f)); - break; - /* D - insert 'p' if Rd is R15 */ - case 'D': - if (((insn >> 12) & 0x0f) == 15) - di->di_printf("p"); - break; - /* n - n register (bits 16-19) */ - case 'n': - di->di_printf("r%d", ((insn >> 16) & 0x0f)); - break; - /* s - s register (bits 8-11) */ - case 's': - di->di_printf("r%d", ((insn >> 8) & 0x0f)); - break; - /* o - indirect register rn (bits 16-19) (used by swap) */ - case 'o': - di->di_printf("[r%d]", ((insn >> 16) & 0x0f)); - break; - /* m - m register (bits 0-4) */ - case 'm': - di->di_printf("r%d", ((insn >> 0) & 0x0f)); - break; - /* a - address operand of ldr/str instruction */ - case 'a': - disasm_insn_ldrstr(di, insn, loc); - break; - /* e - address operand of ldrh/strh instruction */ - case 'e': - disasm_insn_ldrhstrh(di, insn, loc); - break; - /* l - register list for ldm/stm instruction */ - case 'l': - disasm_print_reglist(di, insn); - break; - /* f - 1st fp operand (register) (bits 12-14) */ - case 'f': - di->di_printf("f%d", (insn >> 12) & 7); - break; - /* g - 2nd fp operand (register) (bits 16-18) */ - case 'g': - di->di_printf("f%d", (insn >> 16) & 7); - break; - /* h - 3rd fp operand (register/immediate) (bits 0-4) */ - case 'h': - if (insn & (1 << 3)) - di->di_printf("#%s", insn_fpaimm(insn)); - else - di->di_printf("f%d", insn & 7); - break; - /* b - branch address */ - case 'b': - branch = ((insn << 2) & 0x03ffffff); - if (branch & 0x02000000) - branch |= 0xfc000000; - di->di_printaddr(loc + 8 + branch); - break; - /* t - blx address */ - case 't': - branch = ((insn << 2) & 0x03ffffff) | - (insn >> 23 & 0x00000002); - if (branch & 0x02000000) - branch |= 0xfc000000; - di->di_printaddr(loc + 8 + branch); - break; - /* X - block transfer type */ - case 'X': - di->di_printf("%s", insn_blktrans(insn)); - break; - /* Y - block transfer type (r13 base) */ - case 'Y': - di->di_printf("%s", insn_stkblktrans(insn)); - break; - /* c - comment field bits(0-23) */ - case 'c': - di->di_printf("0x%08x", (insn & 0x00ffffff)); - break; - /* k - breakpoint comment (bits 0-3, 8-19) */ - case 'k': - di->di_printf("0x%04x", - (insn & 0x000fff00) >> 4 | (insn & 0x0000000f)); - break; - /* p - saved or current status register */ - case 'p': - if (insn & 0x00400000) - di->di_printf("spsr"); - else - di->di_printf("cpsr"); - break; - /* F - PSR transfer fields */ - case 'F': - di->di_printf("_"); - if (insn & (1 << 16)) - di->di_printf("c"); - if (insn & (1 << 17)) - di->di_printf("x"); - if (insn & (1 << 18)) - di->di_printf("s"); - if (insn & (1 << 19)) - di->di_printf("f"); - break; - /* B - byte transfer flag */ - case 'B': - if (insn & 0x00400000) - di->di_printf("b"); - break; - /* L - co-processor transfer size */ - case 'L': - if (insn & (1 << 22)) - di->di_printf("l"); - break; - /* S - set status flag */ - case 'S': - if (insn & 0x00100000) - di->di_printf("s"); - break; - /* P - fp precision */ - case 'P': - di->di_printf("%s", insn_fpaprec(insn)); - break; - /* Q - fp precision (for ldf/stf) */ - case 'Q': - break; - /* R - fp rounding */ - case 'R': - di->di_printf("%s", insn_fparnd(insn)); - break; - /* W - writeback flag */ - case 'W': - if (insn & (1 << 21)) - di->di_printf("!"); - break; - /* # - co-processor number */ - case '#': - di->di_printf("p%d", (insn >> 8) & 0x0f); - break; - /* v - co-processor data transfer registers+addressing mode */ - case 'v': - disasm_insn_ldcstc(di, insn, loc); - break; - /* x - instruction in hex */ - case 'x': - di->di_printf("0x%08x", insn); - break; - /* y - co-processor data processing registers */ - case 'y': - di->di_printf("%d, ", (insn >> 20) & 0x0f); - - di->di_printf("c%d, c%d, c%d", (insn >> 12) & 0x0f, - (insn >> 16) & 0x0f, insn & 0x0f); - - di->di_printf(", %d", (insn >> 5) & 0x07); - break; - /* z - co-processor register transfer registers */ - case 'z': - di->di_printf("%d, ", (insn >> 21) & 0x07); - di->di_printf("r%d, c%d, c%d, %d", - (insn >> 12) & 0x0f, (insn >> 16) & 0x0f, - insn & 0x0f, (insn >> 5) & 0x07); - -/* if (((insn >> 5) & 0x07) != 0) - di->di_printf(", %d", (insn >> 5) & 0x07);*/ - break; - default: - di->di_printf("[%c - unknown]", *f_ptr); - break; - } - if (*(f_ptr+1) >= 'A' && *(f_ptr+1) <= 'Z') - ++f_ptr; - else if (*(++f_ptr)) { - ++fmt; - if (fmt == 1) - di->di_printf("\t"); - else - di->di_printf(", "); - } - }; - - di->di_printf("\n"); - - return(loc + INSN_SIZE); -} - - -static void -disasm_register_shift(const disasm_interface_t *di, u_int insn) -{ - di->di_printf("r%d", (insn & 0x0f)); - if ((insn & 0x00000ff0) == 0) - ; - else if ((insn & 0x00000ff0) == 0x00000060) - di->di_printf(", rrx"); - else { - if (insn & 0x10) - di->di_printf(", %s r%d", op2_shift(insn), - (insn >> 8) & 0x0f); - else - di->di_printf(", %s #%d", op2_shift(insn), - (insn >> 7) & 0x1f); - } -} - - -static void -disasm_print_reglist(const disasm_interface_t *di, u_int insn) -{ - int loop; - int start; - int comma; - - di->di_printf("{"); - start = -1; - comma = 0; - - for (loop = 0; loop < 17; ++loop) { - if (start != -1) { - if (loop == 16 || !(insn & (1 << loop))) { - if (comma) - di->di_printf(", "); - else - comma = 1; - if (start == loop - 1) - di->di_printf("r%d", start); - else - di->di_printf("r%d-r%d", start, loop - 1); - start = -1; - } - } else { - if (insn & (1 << loop)) - start = loop; - } - } - di->di_printf("}"); - - if (insn & (1 << 22)) - di->di_printf("^"); -} - -static void -disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn, u_int loc) -{ - int offset; - - offset = insn & 0xfff; - if ((insn & 0x032f0000) == 0x010f0000) { - /* rA = pc, immediate index */ - if (insn & 0x00800000) - loc += offset; - else - loc -= offset; - di->di_printaddr(loc + 8); - } else { - di->di_printf("[r%d", (insn >> 16) & 0x0f); - if ((insn & 0x03000fff) != 0x01000000) { - di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]"); - if (!(insn & 0x00800000)) - di->di_printf("-"); - if (insn & (1 << 25)) - disasm_register_shift(di, insn); - else - di->di_printf("#0x%03x", offset); - } - if (insn & (1 << 24)) - di->di_printf("]"); - } -} - -static void -disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn, u_int loc) -{ - int offset; - - offset = ((insn & 0xf00) >> 4) | (insn & 0xf); - if ((insn & 0x004f0000) == 0x004f0000) { - /* rA = pc, immediate index */ - if (insn & 0x00800000) - loc += offset; - else - loc -= offset; - di->di_printaddr(loc + 8); - } else { - di->di_printf("[r%d", (insn >> 16) & 0x0f); - if ((insn & 0x01400f0f) != 0x01400000) { - di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]"); - if (!(insn & 0x00800000)) - di->di_printf("-"); - if (insn & (1 << 22)) - di->di_printf("#0x%02x", offset); - else - di->di_printf("r%d", (insn & 0x0f)); - } - if (insn & (1 << 24)) - di->di_printf("]"); - } -} - -static void -disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, u_int loc) -{ - if (((insn >> 8) & 0xf) == 1) - di->di_printf("f%d, ", (insn >> 12) & 0x07); - else - di->di_printf("c%d, ", (insn >> 12) & 0x0f); - - di->di_printf("[r%d", (insn >> 16) & 0x0f); - - di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]"); - - if (!(insn & (1 << 23))) - di->di_printf("-"); - - di->di_printf("#0x%03x", (insn & 0xff) << 2); - - if (insn & (1 << 24)) - di->di_printf("]"); - - if (insn & (1 << 21)) - di->di_printf("!"); -} - -static u_int -disassemble_readword(u_int address) -{ - return(*((u_int *)address)); -} - -static void -disassemble_printaddr(u_int address) -{ - printf("0x%08x", address); -} - -static void -disassemble_printf(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); -} - -static const disasm_interface_t disassemble_di = { - disassemble_readword, disassemble_printaddr, disassemble_printf -}; - -void -disassemble(u_int address) -{ - - (void)disasm(&disassemble_di, address, 0); -} - -/* End of disassem.c */ diff --git a/libacc/tests/disassem.h b/libacc/tests/disassem.h deleted file mode 100644 index 02747cd..0000000 --- a/libacc/tests/disassem.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $NetBSD: disassem.h,v 1.4 2001/03/04 04:15:58 matt Exp $ */ - -/*- - * Copyright (c) 1997 Mark Brinicombe. - * Copyright (c) 1997 Causality Limited. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Mark Brinicombe. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Define the interface structure required by the disassembler. - * - * $FreeBSD: /repoman/r/ncvs/src/sys/arm/include/disassem.h,v 1.2 2005/01/05 21:58:48 imp Exp $ - */ - -#ifndef ANDROID_MACHINE_DISASSEM_H -#define ANDROID_MACHINE_DISASSEM_H - -#include <sys/types.h> - -#if __cplusplus -extern "C" { -#endif - -typedef struct { - u_int (*di_readword)(u_int); - void (*di_printaddr)(u_int); - void (*di_printf)(const char *, ...); -} disasm_interface_t; - -/* Prototypes for callable functions */ - -u_int disasm(const disasm_interface_t *, u_int, int); -void disassemble(u_int); - -#if __cplusplus -} -#endif - -#endif /* !ANDROID_MACHINE_DISASSEM_H */ diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp deleted file mode 100644 index e4e386f..0000000 --- a/libacc/tests/main.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Android "Almost" C Compiler. - * This is a compiler for a small subset of the C language, intended for use - * in scripting environments where speed and memory footprint are important. - * - * This code is based upon the "unobfuscated" version of the - * Obfuscated Tiny C compiler, see the file LICENSE for details. - * - */ - -#include <ctype.h> -#include <dlfcn.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#if defined(__arm__) -#include <unistd.h> -#endif - -#if defined(__arm__) -#define PROVIDE_ARM_DISASSEMBLY -#endif - -#ifdef PROVIDE_ARM_DISASSEMBLY -#include "disassem.h" -#endif - -#include <acc/acc.h> - - -typedef int (*MainPtr)(int, char**); -// This is a separate function so it can easily be set by breakpoint in gdb. -int run(MainPtr mainFunc, int argc, char** argv) { - return mainFunc(argc, argv); -} - -ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) { - return (ACCvoid*) dlsym(RTLD_DEFAULT, name); -} - -#ifdef PROVIDE_ARM_DISASSEMBLY - -static FILE* disasmOut; - -static u_int -disassemble_readword(u_int address) -{ - return(*((u_int *)address)); -} - -static void -disassemble_printaddr(u_int address) -{ - fprintf(disasmOut, "0x%08x", address); -} - -static void -disassemble_printf(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - vfprintf(disasmOut, fmt, ap); - va_end(ap); -} - -static int disassemble(ACCscript* script, FILE* out) { - disasmOut = out; - disasm_interface_t di; - di.di_readword = disassemble_readword; - di.di_printaddr = disassemble_printaddr; - di.di_printf = disassemble_printf; - - ACCvoid* base; - ACCsizei length; - - accGetProgramBinary(script, &base, &length); - unsigned long* pBase = (unsigned long*) base; - unsigned long* pEnd = (unsigned long*) (((unsigned char*) base) + length); - - for(unsigned long* pInstruction = pBase; pInstruction < pEnd; pInstruction++) { - fprintf(out, "%08x: %08x ", (int) pInstruction, (int) *pInstruction); - ::disasm(&di, (uint) pInstruction, 0); - } - return 0; -} - -#endif // PROVIDE_ARM_DISASSEMBLY - -int main(int argc, char** argv) { - const char* inFile = NULL; - bool printListing; - bool runResults = false; - FILE* in = stdin; - int i; - for (i = 1; i < argc; i++) { - char* arg = argv[i]; - if (arg[0] == '-') { - switch (arg[1]) { - case 'S': - printListing = true; - break; - case 'R': - runResults = true; - break; - default: - fprintf(stderr, "Unrecognized flag %s\n", arg); - return 3; - } - } else if (inFile == NULL) { - inFile = arg; - } else { - break; - } - } - - if (! inFile) { - fprintf(stderr, "input file required\n"); - return 2; - } - - if (inFile) { - in = fopen(inFile, "r"); - if (!in) { - fprintf(stderr, "Could not open input file %s\n", inFile); - return 1; - } - } - - fseek(in, 0, SEEK_END); - size_t fileSize = (size_t) ftell(in); - rewind(in); - ACCchar* text = new ACCchar[fileSize + 1]; - size_t bytesRead = fread(text, 1, fileSize, in); - if (bytesRead != fileSize) { - fprintf(stderr, "Could not read all of file %s\n", inFile); - } - - text[fileSize] = '\0'; - - ACCscript* script = accCreateScript(); - - const ACCchar* scriptSource[] = {text}; - accScriptSource(script, 1, scriptSource, NULL); - delete[] text; - - accRegisterSymbolCallback(script, symbolLookup, NULL); - - accCompileScript(script); - int result = accGetError(script); - MainPtr mainPointer = 0; - if (result != 0) { - ACCsizei bufferLength; - accGetScriptInfoLog(script, 0, &bufferLength, NULL); - char* buf = (char*) malloc(bufferLength + 1); - if (buf != NULL) { - accGetScriptInfoLog(script, bufferLength + 1, NULL, buf); - fprintf(stderr, "%s", buf); - free(buf); - } else { - fprintf(stderr, "Out of memory.\n"); - } - goto exit; - } - - { - ACCsizei numPragmaStrings; - accGetPragmas(script, &numPragmaStrings, 0, NULL); - if (numPragmaStrings) { - char** strings = new char*[numPragmaStrings]; - accGetPragmas(script, NULL, numPragmaStrings, strings); - for(ACCsizei i = 0; i < numPragmaStrings; i += 2) { - fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]); - } - delete[] strings; - } - } - - if (printListing) { -#ifdef PROVIDE_ARM_DISASSEMBLY - disassemble(script, stderr); -#endif - } - - if (runResults) { - accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); - - result = accGetError(script); - if (result != ACC_NO_ERROR) { - fprintf(stderr, "Could not find main: %d\n", result); - } else { - fprintf(stderr, "Executing compiled code:\n"); - int codeArgc = argc - i + 1; - char** codeArgv = argv + i - 1; - codeArgv[0] = (char*) (inFile ? inFile : "stdin"); - result = run(mainPointer, codeArgc, codeArgv); - fprintf(stderr, "result: %d\n", result); - } - } - -exit: - - accDeleteScript(script); - - return result; -} diff --git a/libacc/tests/runtimeTest.cpp b/libacc/tests/runtimeTest.cpp deleted file mode 100644 index 55bf877..0000000 --- a/libacc/tests/runtimeTest.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * RuntimeTest for ACC compiler. - * - */ - -#include <ctype.h> -#include <dlfcn.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#if defined(__arm__) -#include <unistd.h> -#endif - -#include <acc/acc.h> - - -typedef void (*ScriptPtr)(); - -// This is a separate function so it can easily be set by breakpoint in gdb. -void run(ScriptPtr scriptFn) { - scriptFn(); -} - -// Private API for development: - -extern "C" -void accDisassemble(ACCscript* script); - -int globalVar; - -void op_int(int a) { - printf("op_int(%d)\n", a); -} - -void op_float12(float a, float b, float c, float d, - float e, float f, float g, float h, - float i, float j, float k, float l) { - printf("op_float12(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g)\n", - a, b, c, d, e, f, g, h, i, j, k, l); -} - -const char* text = "void op_int(int a);\n" - "void op_float12(float a, float b, float c, float d,\n" - " float e, float f, float g, float h,\n" - " float i, float j, float k, float l);\n" - "void script() {\n" - " globalVar += 3;\n" - " op_int(123);\n" - " op_float12(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0);\n" - "}\n"; - -ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) { - if (strcmp("op_int", name) == 0) { - return (ACCvoid*) op_int; - } - if (strcmp("op_float12", name) == 0) { - return (ACCvoid*) op_float12; - } - if (strcmp("globalVar", name) == 0) { - return (ACCvoid*) &globalVar; - } - return (ACCvoid*) dlsym(RTLD_DEFAULT, name); -} - -int main(int argc, char** argv) { - ACCscript* script = accCreateScript(); - - accRegisterSymbolCallback(script, symbolLookup, NULL); - - const ACCchar* scriptSource[] = {text}; - accScriptSource(script, 1, scriptSource, NULL); - - accCompileScript(script); - int result = accGetError(script); - ScriptPtr scriptPointer = 0; - if (result != 0) { - char buf[1024]; - accGetScriptInfoLog(script, sizeof(buf), NULL, buf); - fprintf(stderr, "%s", buf); - goto exit; - } - - { - ACCsizei numPragmaStrings; - accGetPragmas(script, &numPragmaStrings, 0, NULL); - if (numPragmaStrings) { - char** strings = new char*[numPragmaStrings]; - accGetPragmas(script, NULL, numPragmaStrings, strings); - for(ACCsizei i = 0; i < numPragmaStrings; i += 2) { - fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]); - } - delete[] strings; - } - } - - accGetScriptLabel(script, "script", (ACCvoid**) & scriptPointer); - - result = accGetError(script); - if (result != ACC_NO_ERROR) { - fprintf(stderr, "Could not find script: %d\n", result); - } else { - fprintf(stderr, "Executing script:\n"); - globalVar = 17; - run(scriptPointer); - fprintf(stderr, "After script globalVar = %d\n", globalVar); - } - - -exit: - - accDeleteScript(script); - - return result; -} diff --git a/libacc/tests/test b/libacc/tests/test deleted file mode 100755 index 8fd6916..0000000 --- a/libacc/tests/test +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -SCRIPT_DIR=`dirname $BASH_SOURCE` -cd $SCRIPT_DIR -python test.py "$@" - diff --git a/libacc/tests/test.py b/libacc/tests/test.py deleted file mode 100644 index 1b444c7..0000000 --- a/libacc/tests/test.py +++ /dev/null @@ -1,517 +0,0 @@ -# -# Test the acc compiler - -import unittest -import subprocess -import os -import sys - -gArmInitialized = False -gUseArm = True -gUseX86 = True -gRunOTCCOutput = True -gCompileOTCCANSI = True - - -def parseArgv(): - global gUseArm - global gUseX86 - global gRunOTCCOutput - for arg in sys.argv[1:]: - if arg == "--noarm": - print "--noarm: not testing ARM" - gUseArm = False - elif arg == "--nox86": - print "--nox86: not testing x86" - gUseX86 = False - elif arg == "--norunotcc": - print "--norunotcc detected, not running OTCC output" - gRunOTCCOutput = False - else: - print "Unknown parameter: ", arg - raise "Unknown parameter" - sys.argv = sys.argv[0:1] - -def compile(args): - proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE) - result = proc.communicate() - return result - -def runCmd(args): - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - result = proc.communicate() - return result[0].strip() - -def uname(): - return runCmd(["uname"]) - -def unameM(): - return runCmd(["uname", "-m"]) - -def which(item): - return runCmd(["which", item]) - -def fileType(item): - return runCmd(["file", item]) - -def outputCanRun(): - ft = fileType(which("acc")) - return ft.find("ELF 32-bit LSB executable, Intel 80386") >= 0 - -def checkEnvironment(): - global gRunOTCCOutput - global gCompileOTCCANSI - osName = uname() - gRunOTCCOutput = osName == "Linux" and unameM() != "x86_64" and outputCanRun() - # OSX doesn't have stdin/stdout/stderr accessible through dll load symbols, so - # we can't compile the ANSI version of the OTCC compiler on OS X. - gCompileOTCCANSI = osName == "Linux" - -def adb(args): - return runCmd(["adb"] + args) - -def setupArm(): - global gArmInitialized - if gArmInitialized: - return - print "Setting up arm" - adb(["remount"]) - adb(["shell", "rm", "/system/bin/acc"]) - adb(["shell", "mkdir", "/system/bin/accdata"]) - adb(["shell", "mkdir", "/system/bin/accdata/data"]) - # Clear out old data TODO: handle recursion - adb(["shell", "rm", "/system/bin/accdata/data/*"]) - # Copy over data - for root, dirs, files in os.walk("data"): - for d in dirs: - adb(["shell", "mkdir", os.path.join(root, d)]) - for f in files: - adb(["push", os.path.join(root, f), os.path.join("/system/bin/accdata", root, f)]) - # Copy over compiler - adb(["sync"]) - gArmInitialized = True - -def compileArm(args): - setupArm() - proc = subprocess.Popen(["adb", "shell", "/system/bin/acc"] + args, stdout=subprocess.PIPE) - result = proc.communicate() - return result[0].replace("\r","") - -def compare(a, b): - if a != b: - firstDiff = firstDifference(a, b) - print "Strings differ at character %d. Common: %s. Difference '%s' != '%s'" % ( - firstDiff, a[0:firstDiff], safeAccess(a, firstDiff), safeAccess(b, firstDiff)) - -def safeAccess(s, i): - if 0 <= i < len(s): - return s[i] - else: - return '?' - -def firstDifference(a, b): - commonLen = min(len(a), len(b)) - for i in xrange(0, commonLen): - if a[i] != b[i]: - return i - return commonLen - -# a1 and a2 are the expected stdout and stderr. -# b1 and b2 are the actual stdout and stderr. -# Compare the two, sets. Allow any individual line -# to appear in either stdout or stderr. This is because -# the way we obtain output on the ARM combines both -# streams into one sequence. - -def compareOuput(a1,a2,b1,b2): - while True: - totalLen = len(a1) + len(a2) + len(b1) + len(b2) - a1, b1 = matchCommon(a1, b1) - a1, b2 = matchCommon(a1, b2) - a2, b1 = matchCommon(a2, b1) - a2, b2 = matchCommon(a2, b2) - newTotalLen = len(a1) + len(a2) + len(b1) + len(b2) - if newTotalLen == 0: - return True - if newTotalLen == totalLen: - print "Failed at %d %d %d %d" % (len(a1), len(a2), len(b1), len(b2)) - print "a1", a1 - print "a2", a2 - print "b1", b1 - print "b2", b2 - return False - -def matchCommon(a, b): - """Remove common items from the beginning of a and b, - return just the tails that are different.""" - while len(a) > 0 and len(b) > 0 and a[0] == b[0]: - a = a[1:] - b = b[1:] - return a, b - -def rewritePaths(args): - return [rewritePath(x) for x in args] - -def rewritePath(p): - """Take a path that's correct on the x86 and convert to a path - that's correct on ARM.""" - if p.startswith("data/"): - p = "/system/bin/accdata/" + p - return p - -class TestACC(unittest.TestCase): - - def checkResult(self, out, err, stdErrResult, stdOutResult=""): - a1 = out.splitlines() - a2 = err.splitlines() - b2 = stdErrResult.splitlines() - b1 = stdOutResult.splitlines() - self.assertEqual(True, compareOuput(a1,a2,b1,b2)) - - def compileCheck(self, args, stdErrResult, stdOutResult="", - targets=['arm', 'x86']): - global gUseArm - global gUseX86 - targetSet = frozenset(targets) - if gUseX86 and 'x86' in targetSet: - out, err = compile(args) - self.checkResult(out, err, stdErrResult, stdOutResult) - if gUseArm and 'arm' in targetSet: - out = compileArm(rewritePaths(args)) - self.checkResult(out, "", stdErrResult, stdOutResult) - - def compileCheckArm(self, args, result): - self.assertEqual(compileArm(args), result) - - def testCompileReturnVal(self): - self.compileCheck(["data/returnval-ansi.c"], "") - - def testCompileOTCCANSI(self): - global gCompileOTCCANSI - if gCompileOTCCANSI: - self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86']) - - def testRunReturnVal(self): - self.compileCheck(["-R", "data/returnval-ansi.c"], - "Executing compiled code:\nresult: 42\n") - - def testContinue(self): - self.compileCheck(["-R", "data/continue.c"], - "Executing compiled code:\nresult: 400\n") - - def testStringLiteralConcatenation(self): - self.compileCheck(["-R", "data/testStringConcat.c"], - "Executing compiled code:\nresult: 13\n", "Hello, world\n") - - def testRunOTCCANSI(self): - global gRunOTCCOutput - if gRunOTCCOutput: - self.compileCheck(["-R", "data/otcc-ansi.c", "data/returnval.c"], - "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\natcc-ansi.c: result: 42\nresult: 42\n", "", - ['x86']) - - def testRunOTCCANSI2(self): - global gRunOTCCOutput - if gRunOTCCOutput: - self.compileCheck(["-R", "data/otcc-ansi.c", "data/otcc.c", "data/returnval.c"], - "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\notcc.c: about to execute compiled code.\natcc-ansi.c: result: 42\nresult: 42\n", "",['x86']) - - def testRunConstants(self): - self.compileCheck(["-R", "data/constants.c"], - "Executing compiled code:\nresult: 12\n", - "0 = 0\n010 = 8\n0x10 = 16\n'\\a' = 7\n'\\b' = 8\n'\\f' = 12\n'\\n' = 10\n'\\r' = 13\n'\\t' = 9\n'\\v' = 11\n'\\\\' = 92\n'\\'' = 39\n" + - "'\\\"' = 34\n'\\?' = 63\n'\\0' = 0\n'\\1' = 1\n'\\12' = 10\n'\\123' = 83\n'\\x0' = 0\n'\\x1' = 1\n'\\x12' = 18\n'\\x123' = 291\n'\\x1f' = 31\n'\\x1F' = 31\n") - - def testRunFloat(self): - self.compileCheck(["-R", "data/float.c"], - "Executing compiled code:\nresult: 0\n", - """Constants: 0 0 0 0.01 0.01 0.1 10 10 0.1 -int: 1 float: 2.2 double: 3.3 - ftoi(1.4f)=1 - dtoi(2.4)=2 - itof(3)=3 - itod(4)=4 -globals: 1 2 3 4 -args: 1 2 3 4 -locals: 1 2 3 4 -cast rval: 2 4 -cast lval: 1.1 2 3.3 4 -""") - - def testRunFlops(self): - self.compileCheck(["-R", "data/flops.c"], - """Executing compiled code: -result: 0""", -"""-1.1 = -1.1 -!1.2 = 0 -!0 = 1 -double op double: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -float op float: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -double op float: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -double op int: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -int op double: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -double op double: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -double op float: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -float op float: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -int op double: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -double op int: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -branching: 1 0 1 -testpassi: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassf: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassd: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassi: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassf: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassd: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassi: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassf: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassd: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassidf: 1 2 3 -""") - def testCasts(self): - self.compileCheck(["-R", "data/casts.c"], - """Executing compiled code: -result: 0""", """Reading from a pointer: 3 3 -Writing to a pointer: 4 -Testing casts: 3 3 4.5 4 -Testing reading (int*): 4 -Testing writing (int*): 8 9 -Testing reading (char*): 0x78 0x56 0x34 0x12 -Testing writing (char*): 0x87654321 -f(10) -Function pointer result: 70 -Testing read/write (float*): 8.8 9.9 -Testing read/write (double*): 8.8 9.9 -""") - - def testChar(self): - self.compileCheck(["-R", "data/char.c"], """Executing compiled code: -result: 0""", """a = 99, b = 41 -ga = 100, gb = 44""") - - def testTypedef(self): - self.compileCheck(["-R", "data/typedef.c"], """Executing compiled code: -result: 0""", """x = 3 -(4, 6) = (1, 2) + (3, 4) -""") - - def testPointerArithmetic(self): - self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code: -result: 0""", """Pointer difference: 1 4 -Pointer addition: 2 -Pointer comparison to zero: 0 0 1 -Pointer comparison: 1 0 0 0 1 -""") - def testRollo3(self): - self.compileCheck(["-R", "data/rollo3.c"], """Executing compiled code: -result: 10""", """""") - - def testFloatDouble(self): - self.compileCheck(["-R", "data/floatdouble.c"], """Executing compiled code: -result: 0""", """0.002 0.1 10""") - - def testIncDec(self): - self.compileCheck(["-R", "data/inc.c"], """Executing compiled code: -0 -1 -2 -1 -1 -2 -1 -0 -result: 0 -""","""""") - - def testIops(self): - self.compileCheck(["-R", "data/iops.c"], """Executing compiled code: -result: 0""", """Literals: 1 -1 -++ -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 --- -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 -0 -""") - - def testFilm(self): - self.compileCheck(["-R", "data/film.c"], """Executing compiled code: -result: 0""", """testing... -Total bad: 0 -""") - - def testMacros(self): - self.compileCheck(["-R", "data/macros.c"], """Executing compiled code: -result: 0""", """A = 6 -A = 10 -""") - - def testpointers2(self): - self.compileCheck(["-R", "data/pointers2.c"], """Executing compiled code: -result: 0""", """a = 0, *pa = 0 -a = 2, *pa = 2 -a = 0, *pa = 0 **ppa = 0 -a = 2, *pa = 2 **ppa = 2 -a = 0, *pa = 0 **ppa = 0 -a = 2, *pa = 2 **ppa = 2 -""") - - def testassignmentop(self): - self.compileCheck(["-R", "data/assignmentop.c"], """Executing compiled code: -result: 0""", """2 *= 5 10 -20 /= 5 4 -17 %= 5 2 -17 += 5 22 -17 -= 5 12 -17<<= 1 34 -17>>= 1 8 -17&= 1 1 -17^= 1 16 -16|= 1 17 -*f() = *f() + 10; -f() -f() -a = 10 -*f() += 10; -f() -a = 10 -""") - - def testcomma(self): - self.compileCheck(["-R", "data/comma.c"], """Executing compiled code: -result: 0""", """statement: 10 -if: a = 0 -while: b = 11 -for: b = 22 -return: 30 -arg: 12 -""") - - def testBrackets(self): - self.compileCheck(["-R", "data/brackets.c"], """Executing compiled code: -Errors: 0 -2D Errors: 0 -result: 0 -""","""""") - - def testShort(self): - self.compileCheck(["-R", "data/short.c"], """Executing compiled code: -result: -2 -""","""""") - - def testAssignment(self): - self.compileCheck(["-R", "data/assignment.c"], """Executing compiled code: -result: 7 -""","""""") - - def testArray(self): - self.compileCheck(["-R", "data/array.c"], """Executing compiled code: -localInt: 3 -localDouble: 3 3 -globalChar: 3 -globalDouble: 3 -testArgs: 0 2 4 -testDecay: Hi! -test2D: -abcdefghijdefghijklm -defghijklmghijklmnop -ghijklmnopjklmnopabc -jklmnopabcmnopabcdef -mnopabcdefpabcdefghi -pabcdefghicdefghijkl -cdefghijklfghijklmno -fghijklmnoijklmnopab -ijklmnopablmnopabcde -lmnopabcdefghijklmno -result: 0 -""","""""") - - def testDefines(self): - self.compileCheck(["-R", "data/defines.c"], """Executing compiled code: -result: 3 -""","""""") - - def testFuncArgs(self): - self.compileCheck(["-R", "data/funcargs.c"], """Executing compiled code: -result: 4 -""","""""") - - def testB2071670(self): - self.compileCheck(["-R", "data/b2071670.c"], """Executing compiled code: -result: 1092616192 -""","""""") - - def testStructs(self): - self.compileCheck(["-R", "data/structs.c"], """Executing compiled code: -testCopying: 37 == 37 -testUnion: 1 == 0x3f800000 -testArgs: (6, 8, 10, 12) -result: 6 -""","""""") - - def testAddressOf(self): - self.compileCheck(["-R", "data/addressOf.c"], """Executing compiled code: -testStruct: 10 10 10 -testArray: 1 1 1 -result: 0 -""","""""") - -def main(): - checkEnvironment() - parseArgv() - unittest.main() - -if __name__ == '__main__': - main() - diff --git a/libusbhost/Android.mk b/libusbhost/Android.mk new file mode 100644 index 0000000..97c1edc --- /dev/null +++ b/libusbhost/Android.mk @@ -0,0 +1,43 @@ +# +# Copyright (C) 2010 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(my-dir) + +# Static library for Linux host +# ======================================================== + +ifeq ($(HOST_OS),linux) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libusbhost +LOCAL_SRC_FILES := usbhost.c + +include $(BUILD_HOST_STATIC_LIBRARY) + +endif + +# Static library for target +# ======================================================== + +include $(CLEAR_VARS) + +LOCAL_MODULE := libusbhost +LOCAL_SRC_FILES := usbhost.c + +LOCAL_CFLAGS := -g -DUSE_LIBLOG + +include $(BUILD_STATIC_LIBRARY) diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c new file mode 100644 index 0000000..98ccf7c --- /dev/null +++ b/libusbhost/usbhost.c @@ -0,0 +1,503 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// #define DEBUG 1 +#if DEBUG + +#ifdef USE_LIBLOG +#define LOG_TAG "usbhost" +#include "utils/Log.h" +#define D LOGD +#else +#define D printf +#endif + +#else +#define D(...) +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/inotify.h> +#include <dirent.h> +#include <fcntl.h> +#include <errno.h> +#include <ctype.h> +#include <pthread.h> + +#include <linux/usbdevice_fs.h> +#include <linux/version.h> +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) +#include <linux/usb/ch9.h> +#else +#include <linux/usb_ch9.h> +#endif +#include <asm/byteorder.h> + +#include "usbhost/usbhost.h" + +#define USB_FS_DIR "/dev/bus/usb" +#define USB_FS_ID_SCANNER "/dev/bus/usb/%d/%d" + + +struct usb_host_context { + int fd; +}; + +struct usb_device { + char dev_name[64]; + unsigned char desc[256]; + int desc_length; + int fd; + int writeable; +}; + +struct usb_endpoint +{ + struct usb_device *dev; + struct usb_endpoint_descriptor desc; + struct usbdevfs_urb urb; +}; + +static inline int badname(const char *name) +{ + while(*name) { + if(!isdigit(*name++)) return 1; + } + return 0; +} + +/* returns true if one of the callbacks indicates we are done */ +static int find_existing_devices(usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + void *client_data) +{ + char busname[32], devname[32]; + DIR *busdir , *devdir ; + struct dirent *de; + int done = 0; + + busdir = opendir(USB_FS_DIR); + if(busdir == 0) return 1; + + while ((de = readdir(busdir)) != 0 && !done) { + if(badname(de->d_name)) continue; + + snprintf(busname, sizeof busname, "%s/%s", USB_FS_DIR, de->d_name); + devdir = opendir(busname); + if(devdir == 0) continue; + + while ((de = readdir(devdir)) && !done) { + if(badname(de->d_name)) continue; + + snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name); + done = added_cb(devname, client_data); + } // end of devdir while + closedir(devdir); + } //end of busdir while + closedir(busdir); + + return done; +} + +struct usb_host_context *usb_host_init() +{ + struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context)); + if (!context) { + fprintf(stderr, "out of memory in usb_host_context\n"); + return NULL; + } + context->fd = inotify_init(); + if (context->fd < 0) { + fprintf(stderr, "inotify_init failed\n"); + free(context); + return NULL; + } + return context; +} + +void usb_host_cleanup(struct usb_host_context *context) +{ + close(context->fd); + free(context); +} + +void usb_host_run(struct usb_host_context *context, + usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + usb_discovery_done_cb discovery_done_cb, + void *client_data) +{ + struct inotify_event* event; + char event_buf[512]; + char path[100]; + int i, ret, done = 0; + int wd, wds[10]; + int wd_count = sizeof(wds) / sizeof(wds[0]); + + D("Created device discovery thread\n"); + + /* watch for files added and deleted within USB_FS_DIR */ + memset(wds, 0, sizeof(wds)); + /* watch the root for new subdirectories */ + wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE); + if (wds[0] < 0) { + fprintf(stderr, "inotify_add_watch failed\n"); + if (discovery_done_cb) + discovery_done_cb(client_data); + return; + } + + /* watch existing subdirectories of USB_FS_DIR */ + for (i = 1; i < wd_count; i++) { + snprintf(path, sizeof(path), "%s/%03d", USB_FS_DIR, i); + ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE); + if (ret > 0) + wds[i] = ret; + } + + /* check for existing devices first, after we have inotify set up */ + done = find_existing_devices(added_cb, removed_cb, client_data); + if (discovery_done_cb) + done |= discovery_done_cb(client_data); + + while (!done) { + ret = read(context->fd, event_buf, sizeof(event_buf)); + if (ret >= (int)sizeof(struct inotify_event)) { + event = (struct inotify_event *)event_buf; + wd = event->wd; + if (wd == wds[0]) { + i = atoi(event->name); + snprintf(path, sizeof(path), "%s/%s", USB_FS_DIR, event->name); + D("new subdirectory %s: index: %d\n", path, i); + if (i > 0 && i < wd_count) { + ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE); + if (ret > 0) + wds[i] = ret; + } + } else { + for (i = 1; i < wd_count && !done; i++) { + if (wd == wds[i]) { + snprintf(path, sizeof(path), "%s/%03d/%s", USB_FS_DIR, i, event->name); + if (event->mask == IN_CREATE) { + D("new device %s\n", path); + done = added_cb(path, client_data); + } else if (event->mask == IN_DELETE) { + D("gone device %s\n", path); + done = removed_cb(path, client_data); + } + } + } + } + } + } +} + +struct usb_device *usb_device_open(const char *dev_name) +{ + struct usb_device *device = calloc(1, sizeof(struct usb_device)); + int fd, length, did_retry = 0; + + strcpy(device->dev_name, dev_name); + device->writeable = 1; + +retry: + fd = open(dev_name, O_RDWR); + if (fd < 0) { + /* if we fail, see if have read-only access */ + fd = open(dev_name, O_RDONLY); + D("usb_device_open open returned %d errno %d\n", fd, errno); + if (fd < 0 && (errno == EACCES || errno == ENOENT) && !did_retry) { + /* work around race condition between inotify and permissions management */ + sleep(1); + did_retry = 1; + goto retry; + } + + if (fd < 0) goto fail; + device->writeable = 0; + D("[ usb open read-only %s fd = %d]\n", dev_name, fd); + } + + length = read(fd, device->desc, sizeof(device->desc)); + D("usb_device_open read returned %d errno %d\n", fd, errno); + if (length < 0) + goto fail; + + device->fd = fd; + device->desc_length = length; + return device; +fail: + close(fd); + free(device); + return NULL; +} + +void usb_device_close(struct usb_device *device) +{ + close(device->fd); + free(device); +} + +const char* usb_device_get_name(struct usb_device *device) +{ + return device->dev_name; +} + +int usb_device_get_unique_id(struct usb_device *device) +{ + int bus = 0, dev = 0; + sscanf(device->dev_name, USB_FS_ID_SCANNER, &bus, &dev); + return bus * 1000 + dev; +} + +int usb_device_get_unique_id_from_name(const char* name) +{ + int bus = 0, dev = 0; + sscanf(name, USB_FS_ID_SCANNER, &bus, &dev); + return bus * 1000 + dev; +} + +uint16_t usb_device_get_vendor_id(struct usb_device *device) +{ + struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc; + return __le16_to_cpu(desc->idVendor); +} + +uint16_t usb_device_get_product_id(struct usb_device *device) +{ + struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc; + return __le16_to_cpu(desc->idProduct); +} + +int usb_device_send_control(struct usb_device *device, + int requestType, + int request, + int value, + int index, + int length, + void* buffer) +{ + struct usbdevfs_ctrltransfer ctrl; + + // this usually requires read/write permission + if (!device->writeable) { + int fd = open(device->dev_name, O_RDWR); + if (fd > 0) { + close(device->fd); + device->fd = fd; + device->writeable = 1; + } else { + return -1; + } + } + + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.bRequestType = requestType; + ctrl.bRequest = request; + ctrl.wValue = value; + ctrl.wIndex = index; + ctrl.wLength = length; + ctrl.data = buffer; + return ioctl(device->fd, USBDEVFS_CONTROL, &ctrl); +} + +char* usb_device_get_string(struct usb_device *device, int id) +{ + char string[256]; + __u16 buffer[128]; + __u16 languages[128]; + int i, result; + int languageCount = 0; + + string[0] = 0; + memset(languages, 0, sizeof(languages)); + + // read list of supported languages + result = usb_device_send_control(device, + USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR, + (USB_DT_STRING << 8) | 0, 0, sizeof(languages), languages); + if (result > 0) + languageCount = (result - 2) / 2; + + for (i = 1; i <= languageCount; i++) { + memset(buffer, 0, sizeof(buffer)); + + result = usb_device_send_control(device, + USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR, + (USB_DT_STRING << 8) | id, languages[i], sizeof(buffer), buffer); + if (result > 0) { + int i; + // skip first word, and copy the rest to the string, changing shorts to bytes. + result /= 2; + for (i = 1; i < result; i++) + string[i - 1] = buffer[i]; + string[i - 1] = 0; + return strdup(string); + } + } + + return NULL; +} + +char* usb_device_get_manufacturer_name(struct usb_device *device) +{ + struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc; + + if (desc->iManufacturer) + return usb_device_get_string(device, desc->iManufacturer); + else + return NULL; +} + +char* usb_device_get_product_name(struct usb_device *device) +{ + struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc; + + if (desc->iProduct) + return usb_device_get_string(device, desc->iProduct); + else + return NULL; +} + +char* usb_device_get_serial(struct usb_device *device) +{ + struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc; + + if (desc->iSerialNumber) + return usb_device_get_string(device, desc->iSerialNumber); + else + return NULL; +} + +int usb_device_is_writeable(struct usb_device *device) +{ + return device->writeable; +} + +void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter) +{ + iter->config = device->desc; + iter->config_end = device->desc + device->desc_length; + iter->curr_desc = device->desc; +} + +struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter) +{ + struct usb_descriptor_header* next; + if (iter->curr_desc >= iter->config_end) + return NULL; + next = (struct usb_descriptor_header*)iter->curr_desc; + iter->curr_desc += next->bLength; + return next; +} + +int usb_device_claim_interface(struct usb_device *device, unsigned int interface) +{ + return ioctl(device->fd, USBDEVFS_CLAIMINTERFACE, &interface); +} + +int usb_device_release_interface(struct usb_device *device, unsigned int interface) +{ + return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface); +} + +struct usb_endpoint *usb_endpoint_open(struct usb_device *dev, + const struct usb_endpoint_descriptor *desc) +{ + struct usb_endpoint *ep = calloc(1, sizeof(struct usb_endpoint)); + memcpy(&ep->desc, desc, sizeof(ep->desc)); + ep->dev = dev; + return ep; +} + +void usb_endpoint_close(struct usb_endpoint *ep) +{ + // cancel IO here? + free(ep); +} + +int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len) +{ + struct usbdevfs_urb *urb = &ep->urb; + int res; + + D("usb_endpoint_queue\n"); + memset(urb, 0, sizeof(*urb)); + urb->type = USBDEVFS_URB_TYPE_BULK; + urb->endpoint = ep->desc.bEndpointAddress; + urb->status = -1; + urb->buffer = data; + urb->buffer_length = len; + + do { + res = ioctl(ep->dev->fd, USBDEVFS_SUBMITURB, urb); + } while((res < 0) && (errno == EINTR)); + + return res; +} + +int usb_endpoint_wait(struct usb_device *dev, int *out_ep_num) +{ + struct usbdevfs_urb *out = NULL; + int res; + + while (1) { + res = ioctl(dev->fd, USBDEVFS_REAPURB, &out); + D("USBDEVFS_REAPURB returned %d\n", res); + if (res < 0) { + if(errno == EINTR) { + continue; + } + D("[ reap urb - error ]\n"); + *out_ep_num = -1; + } else { + D("[ urb @%p status = %d, actual = %d ]\n", + out, out->status, out->actual_length); + res = out->actual_length; + *out_ep_num = out->endpoint; + } + break; + } + return res; +} + +int usb_endpoint_cancel(struct usb_endpoint *ep) +{ + return ioctl(ep->dev->fd, USBDEVFS_DISCARDURB, &ep->urb); +} + +struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep) +{ + return ep->dev; +} + +int usb_endpoint_number(struct usb_endpoint *ep) +{ + return ep->desc.bEndpointAddress; +} + +int usb_endpoint_max_packet(struct usb_endpoint *ep) +{ + return __le16_to_cpu(ep->desc.wMaxPacketSize); +} + diff --git a/logcat/event.logtags b/logcat/event.logtags index f146738..d41f36b 100644 --- a/logcat/event.logtags +++ b/logcat/event.logtags @@ -115,31 +115,20 @@ 50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3) 50001 menu_opened (Menu type where 0 is options and 1 is context|1|5) -# Wi-Fi network state changed: -# [31- 6] Reserved for future use -# [ 5- 0] Detailed state ordinal (as defined by NetworkInfo.DetailedState) -50021 wifi_network_state_changed (network_state|1|5) - -# Wi-Fi supplicant state changed: -# [31- 6] Reserved for future use -# [ 5- 0] Supplicant state ordinal (as defined by SupplicantState) -50022 wifi_supplicant_state_changed (supplicant_state|1|5) - -# Wi-Fi driver state changed: -# [31- 1] Reserved for future use -# [ 0- 0] Driver start (1) or stopped (0) -50023 wifi_driver_state_changed (driver_state|1|5) - -# Wi-Fi interface configuration state changed: -# [31- 1] Reserved for future use -# [ 0- 0] Interface configuration succeeded (1) or failed (0) -50024 wifi_interface_configuration_state_changed (IP_configuration|1|5) - -# Wi-Fi supplicant connection state changed: -# [31- 2] Reserved for future use -# [ 1- 0] Connected to supplicant (1) or disconnected from supplicant (0), -# or supplicant died (2) -50025 wifi_supplicant_connection_state_changed (connected|1|5) +# HSM wifi state change +# Hierarchical state class name (as defined in WifiStateTracker.java) +# Logged on every state change in the hierarchical state machine +50021 wifi_state_changed (wifi_state|3) +# HSM wifi event +# [31-16] Reserved for future use +# [15 - 0] HSM event (as defined in WifiStateTracker.java) +# Logged when an event is handled in a hierarchical state +50022 wifi_event_handled (wifi_event|1|5) +# Supplicant state change +# [31-13] Reserved for future use +# [8 - 0] Supplicant state (as defined in SupplicantState.java) +# Logged when the supplicant switches to a new state +50023 wifi_supplicant_state_changed (supplicant_state|1|5) # Do not change these names without updating tag in: #//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp index 5acdf77..96b68ef 100644 --- a/logcat/logcat.cpp +++ b/logcat/logcat.cpp @@ -402,8 +402,9 @@ static void show_help(const char *cmd) " -d dump the log and then exit (don't block)\n" " -t <count> print only the most recent <count> lines (implies -d)\n" " -g get the size of the log's ring buffer and exit\n" - " -b <buffer> request alternate ring buffer\n" - " ('main' (default), 'radio', 'events')\n" + " -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio'\n" + " or 'events'. Multiple -b parameters are allowed and the\n" + " results are interleaved. The default is -b main -b system.\n" " -B output the log in binary"); diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc index 569555c..6f30843 100644 --- a/rootdir/etc/init.goldfish.rc +++ b/rootdir/etc/init.goldfish.rc @@ -1,3 +1,9 @@ +on early-init + export EXTERNAL_STORAGE /mnt/sdcard + mkdir /mnt/sdcard 0000 system system + # for backwards compatibility + symlink /mnt/sdcard /sdcard + on boot setprop ARGH ARGH setprop net.eth0.dns1 10.0.2.3 diff --git a/rootdir/init.rc b/rootdir/init.rc index 1e3e2d2..fdc36c8 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -1,6 +1,9 @@ on early-init start ueventd +# create mountpoints + mkdir /mnt 0775 root system + on init sysclktz 0 @@ -14,7 +17,6 @@ loglevel 3 export ANDROID_ROOT /system export ANDROID_ASSETS /system/app export ANDROID_DATA /data - export EXTERNAL_STORAGE /mnt/sdcard export ASEC_MOUNTPOINT /mnt/asec export LOOP_MOUNTPOINT /mnt/obb export BOOTCLASSPATH /system/framework/core.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/core-junit.jar @@ -23,18 +25,12 @@ loglevel 3 symlink /system/etc /etc symlink /sys/kernel/debug /d -# create mountpoints - mkdir /mnt 0775 root system - mkdir /mnt/sdcard 0000 system system # Create cgroup mount point for cpu accounting mkdir /acct mount cgroup none /acct cpuacct mkdir /acct/uid -# Backwards Compat - XXX: Going away in G* - symlink /mnt/sdcard /sdcard - mkdir /system mkdir /data 0771 system system mkdir /cache 0770 system cache diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc index 7845eb9..05118bc 100644 --- a/rootdir/ueventd.rc +++ b/rootdir/ueventd.rc @@ -23,7 +23,6 @@ /dev/android_adb 0660 adb adb /dev/android_adb_enable 0660 adb adb /dev/ttyMSM0 0600 bluetooth bluetooth -/dev/ttyHS0 0600 bluetooth bluetooth /dev/uinput 0660 system bluetooth /dev/alarm 0664 system radio /dev/tty0 0660 root system @@ -70,6 +69,7 @@ /dev/qmi1 0640 radio radio /dev/qmi2 0640 radio radio /dev/bus/usb/* 0660 root usb +/dev/mtp_usb 0660 root usb # CDMA radio interface MUX /dev/ts0710mux* 0640 radio radio diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index 82e6354..27cbde2 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -695,7 +695,7 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da out.major = FUSE_KERNEL_VERSION; out.minor = FUSE_KERNEL_MINOR_VERSION; out.max_readahead = req->max_readahead; - out.flags = 0; + out.flags = FUSE_ATOMIC_O_TRUNC; out.max_background = 32; out.congestion_threshold = 32; out.max_write = 256 * 1024; diff --git a/toolbox/mount.c b/toolbox/mount.c index 472c952..82ecc56 100644 --- a/toolbox/mount.c +++ b/toolbox/mount.c @@ -222,9 +222,50 @@ static int print_mounts() return 0; } +static int get_mounts_dev_dir(const char *arg, char **dev, char **dir) +{ + FILE *f; + char mount_dev[256]; + char mount_dir[256]; + char mount_type[256]; + char mount_opts[256]; + int mount_freq; + int mount_passno; + int match; + + f = fopen("/proc/mounts", "r"); + if (!f) { + fprintf(stdout, "could not open /proc/mounts\n"); + return -1; + } + + do { + match = fscanf(f, "%255s %255s %255s %255s %d %d\n", + mount_dev, mount_dir, mount_type, + mount_opts, &mount_freq, &mount_passno); + mount_dev[255] = 0; + mount_dir[255] = 0; + mount_type[255] = 0; + mount_opts[255] = 0; + if (match == 6 && + (strcmp(arg, mount_dev) == 0 || + strcmp(arg, mount_dir) == 0)) { + *dev = strdup(mount_dev); + *dir = strdup(mount_dir); + fclose(f); + return 0; + } + } while (match != EOF); + + fclose(f); + return -1; +} + int mount_main(int argc, char *argv[]) { char *type = NULL; + char *dev = NULL; + char *dir = NULL; int c; int loop = 0; @@ -265,12 +306,19 @@ int mount_main(int argc, char *argv[]) if (rwflag & MS_TYPE) type = "none"; - if (optind + 2 != argc || type == NULL) { + if (optind + 2 == argc) { + dev = argv[optind]; + dir = argv[optind + 1]; + } else if (optind + 1 == argc && rwflag & MS_REMOUNT) { + get_mounts_dev_dir(argv[optind], &dev, &dir); + } + + if (dev == NULL || dir == NULL || type == NULL) { fprintf(stderr, "Usage: %s [-r] [-w] [-o options] [-t type] " "device directory\n", progname); exit(1); } - return do_mount(argv[optind], argv[optind + 1], type, rwflag, - extra.str, loop); + return do_mount(dev, dir, type, rwflag, extra.str, loop); + /* We leak dev and dir in some cases, but we're about to exit */ } diff --git a/toolbox/ps.c b/toolbox/ps.c index bc50cfa..2aa3efb 100644 --- a/toolbox/ps.c +++ b/toolbox/ps.c @@ -27,6 +27,7 @@ static char *nexttok(char **strp) #define SHOW_PRIO 1 #define SHOW_TIME 2 #define SHOW_POLICY 4 +#define SHOW_CPU 8 static int display_flags = 0; @@ -41,7 +42,7 @@ static int ps_line(int pid, int tid, char *namefilter) int ppid, tty; unsigned wchan, rss, vss, eip; unsigned utime, stime; - int prio, nice, rtprio, sched; + int prio, nice, rtprio, sched, psr; struct passwd *pw; sprintf(statline, "/proc/%d", pid); @@ -122,7 +123,7 @@ static int ps_line(int pid, int tid, char *namefilter) nexttok(&ptr); // nswap nexttok(&ptr); // cnswap nexttok(&ptr); // exit signal - nexttok(&ptr); // processor + psr = atoi(nexttok(&ptr)); // processor rtprio = atoi(nexttok(&ptr)); // rt_priority sched = atoi(nexttok(&ptr)); // scheduling policy @@ -142,7 +143,9 @@ static int ps_line(int pid, int tid, char *namefilter) if(!namefilter || !strncmp(name, namefilter, strlen(namefilter))) { printf("%-9s %-5d %-5d %-6d %-5d", user, pid, ppid, vss / 1024, rss * 4); - if(display_flags&SHOW_PRIO) + if (display_flags & SHOW_CPU) + printf(" %-2d", psr); + if (display_flags & SHOW_PRIO) printf(" %-5d %-5d %-5d %-5d", prio, nice, rtprio, sched); if (display_flags & SHOW_POLICY) { SchedPolicy p; @@ -207,6 +210,8 @@ int ps_main(int argc, char **argv) display_flags |= SHOW_POLICY; } else if(!strcmp(argv[1],"-p")) { display_flags |= SHOW_PRIO; + } else if(!strcmp(argv[1],"-c")) { + display_flags |= SHOW_CPU; } else if(isdigit(argv[1][0])){ pidfilter = atoi(argv[1]); } else { @@ -216,7 +221,8 @@ int ps_main(int argc, char **argv) argv++; } - printf("USER PID PPID VSIZE RSS %s %s WCHAN PC NAME\n", + printf("USER PID PPID VSIZE RSS %s%s %s WCHAN PC NAME\n", + (display_flags&SHOW_CPU)?"CPU ":"", (display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"", (display_flags&SHOW_POLICY)?"PCY " : ""); while((de = readdir(d)) != 0){ diff --git a/toolbox/top.c b/toolbox/top.c index daade6d..999c8e1 100644 --- a/toolbox/top.c +++ b/toolbox/top.c @@ -65,6 +65,7 @@ struct proc_info { long unsigned delta_time; long vss; long rss; + int prs; int num_threads; char policy[32]; }; @@ -340,8 +341,9 @@ static int read_stat(char *filename, struct proc_info *proc) { /* Scan rest of string. */ sscanf(close_paren + 1, " %c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " - "%lu %lu %*d %*d %*d %*d %*d %*d %*d %lu %ld", - &proc->state, &proc->utime, &proc->stime, &proc->vss, &proc->rss); + "%lu %lu %*d %*d %*d %*d %*d %*d %*d %lu %ld " + "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d", + &proc->state, &proc->utime, &proc->stime, &proc->vss, &proc->rss, &proc->prs); return 0; } @@ -454,9 +456,9 @@ static void print_procs(void) { total_delta_time); printf("\n"); if (!threads) - printf("%5s %4s %1s %5s %7s %7s %3s %-8s %s\n", "PID", "CPU%", "S", "#THR", "VSS", "RSS", "PCY", "UID", "Name"); + printf("%5s %2s %4s %1s %5s %7s %7s %3s %-8s %s\n", "PID", "PR", "CPU%", "S", "#THR", "VSS", "RSS", "PCY", "UID", "Name"); else - printf("%5s %5s %4s %1s %7s %7s %3s %-8s %-15s %s\n", "PID", "TID", "CPU%", "S", "VSS", "RSS", "PCY", "UID", "Thread", "Proc"); + printf("%5s %5s %2s %4s %1s %7s %7s %3s %-8s %-15s %s\n", "PID", "TID", "PR", "CPU%", "S", "VSS", "RSS", "PCY", "UID", "Thread", "Proc"); for (i = 0; i < num_new_procs; i++) { proc = new_procs[i]; @@ -478,10 +480,10 @@ static void print_procs(void) { group_str = group_buf; } if (!threads) - printf("%5d %3ld%% %c %5d %6ldK %6ldK %3s %-8.8s %s\n", proc->pid, proc->delta_time * 100 / total_delta_time, proc->state, proc->num_threads, + printf("%5d %2d %3ld%% %c %5d %6ldK %6ldK %3s %-8.8s %s\n", proc->pid, proc->prs, proc->delta_time * 100 / total_delta_time, proc->state, proc->num_threads, proc->vss / 1024, proc->rss * getpagesize() / 1024, proc->policy, user_str, proc->name[0] != 0 ? proc->name : proc->tname); else - printf("%5d %5d %3ld%% %c %6ldK %6ldK %3s %-8.8s %-15s %s\n", proc->pid, proc->tid, proc->delta_time * 100 / total_delta_time, proc->state, + printf("%5d %5d %2d %3ld%% %c %6ldK %6ldK %3s %-8.8s %-15s %s\n", proc->pid, proc->tid, proc->prs, proc->delta_time * 100 / total_delta_time, proc->state, proc->vss / 1024, proc->rss * getpagesize() / 1024, proc->policy, user_str, proc->tname, proc->name); } } |