mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add a new "target" command line option to set the target without the need for a full target triple. Add debug command line options. Fix bug with coerce for x64 SysV ABI.
This commit is contained in:
committed by
Christoffer Lerno
parent
1057432913
commit
162bb9dac8
@@ -16,6 +16,16 @@
|
||||
static const int DEFAULT_SYMTAB_SIZE = 64 * 1024;
|
||||
static const int MAX_SYMTAB_SIZE = 1024 * 1024;
|
||||
|
||||
static char *arch_os_target[ARCH_OS_TARGET_LAST + 1] = {
|
||||
[X86_DARWIN] = "x86_darwin",
|
||||
[X86_LINUX] = "x86_linux",
|
||||
[X64_DARWIN] = "x64_darwin",
|
||||
[X64_LINUX] = "x64_linux",
|
||||
[X64_WINDOWS] = "x64_windows",
|
||||
[AARCH64_LINUX] = "aarch64_linux",
|
||||
[AARCH64_DARWIN] = "aarch64_darwin",
|
||||
};
|
||||
|
||||
BuildOptions build_options;
|
||||
static int arg_index;
|
||||
static int arg_count;
|
||||
@@ -23,6 +33,7 @@ static const char** args;
|
||||
static const char* current_arg;
|
||||
|
||||
|
||||
#define EOUTPUT(string, ...) fprintf(stderr, string "\n", ##__VA_ARGS__)
|
||||
#define OUTPUT(string, ...) fprintf(stdout, string "\n", ##__VA_ARGS__)
|
||||
#define FAIL_WITH_ERR(string, ...) do { fprintf(stderr, "Error: " string "\n\n", ##__VA_ARGS__); usage(); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
@@ -57,6 +68,12 @@ static void usage(void)
|
||||
OUTPUT(" -Os - Optimize for size.");
|
||||
OUTPUT(" -O3 - Aggressive optimization.");
|
||||
OUTPUT(" --emit-llvm - Emit LLVM IR as a .ll file per module.");
|
||||
OUTPUT(" --target <target> - Compile for a particular architecture + OS target.");
|
||||
OUTPUT(" --target-list - List all architectures the compiler supports.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" -g - Emit full debug info.");
|
||||
OUTPUT(" -g0 - Emit no debug info.");
|
||||
OUTPUT(" -gline-tables-only - Only emit line tables for debugging.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" -freg-struct-return - Override default ABI to return small structs in registers.");
|
||||
OUTPUT(" -fpcc-struct-return - Override default ABI to return small structs on the stack.");
|
||||
@@ -129,11 +146,11 @@ static void parse_optional_target()
|
||||
{
|
||||
if (at_end() || next_is_opt())
|
||||
{
|
||||
build_options.target = NULL;
|
||||
build_options.target_select = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
build_options.target = next_arg();
|
||||
build_options.target_select = next_arg();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,10 +222,36 @@ static void parse_command(void)
|
||||
}
|
||||
FAIL_WITH_ERR("Cannot process the unknown command \"%s\".", current_arg);
|
||||
}
|
||||
static void parse_option()
|
||||
static void print_all_targets(void)
|
||||
{
|
||||
OUTPUT("Available targets:");
|
||||
for (unsigned i = 0; i <= ARCH_OS_TARGET_LAST; i++)
|
||||
{
|
||||
OUTPUT(" %s", arch_os_target[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_option(void)
|
||||
{
|
||||
switch (current_arg[1])
|
||||
{
|
||||
case 'g':
|
||||
if (match_shortopt("gline-tables-only"))
|
||||
{
|
||||
build_options.debug_info = DEBUG_INFO_LINE_TABLES;
|
||||
FATAL_ERROR("Line tables only are currently not available");
|
||||
}
|
||||
if (match_shortopt("g") || match_shortopt("g1"))
|
||||
{
|
||||
build_options.debug_info = DEBUG_INFO_FULL;
|
||||
return;
|
||||
}
|
||||
if (match_shortopt("g0"))
|
||||
{
|
||||
build_options.debug_info = DEBUG_INFO_NONE;
|
||||
return;
|
||||
}
|
||||
FAIL_WITH_ERR("Unknown debug argument -%s.", ¤t_arg[1]);
|
||||
case 'h':
|
||||
break;
|
||||
case 'f':
|
||||
@@ -299,6 +342,37 @@ static void parse_option()
|
||||
OUTPUT("C3 is low level programming language based on C.");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
if (match_longopt("target"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --target needs a arch+os definition.");
|
||||
const char *target = next_arg();
|
||||
for (unsigned i = 1; i <= ARCH_OS_TARGET_LAST; i++)
|
||||
{
|
||||
if (strcasecmp(arch_os_target[i], target) == 0)
|
||||
{
|
||||
build_options.arch_os_target = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
OUTPUT("Available targets:");
|
||||
EOUTPUT("Invalid target %s.", target);
|
||||
EOUTPUT("These targets are supported:");
|
||||
for (unsigned i = 1; i <= ARCH_OS_TARGET_LAST; i++)
|
||||
{
|
||||
EOUTPUT(" %s", arch_os_target[i]);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (match_longopt("target-list"))
|
||||
{
|
||||
print_all_targets();
|
||||
OUTPUT("Available targets:");
|
||||
for (unsigned i = 1; i <= ARCH_OS_TARGET_LAST; i++)
|
||||
{
|
||||
OUTPUT(" %s", arch_os_target[i]);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
if (match_longopt("emit-llvm"))
|
||||
{
|
||||
build_options.emit_llvm = true;
|
||||
@@ -361,7 +435,7 @@ void parse_arguments(int argc, const char *argv[])
|
||||
build_options.emit_bitcode = true;
|
||||
build_options.optimization_level = OPTIMIZATION_NOT_SET;
|
||||
build_options.size_optimization_level = SIZE_OPTIMIZATION_NOT_SET;
|
||||
build_options.debug_info = DEBUG_INFO_FULL;
|
||||
build_options.debug_info = DEBUG_INFO_NONE;
|
||||
build_options.debug_mode = false;
|
||||
build_options.command = COMMAND_MISSING;
|
||||
build_options.symtab_size = DEFAULT_SYMTAB_SIZE;
|
||||
|
||||
@@ -93,13 +93,27 @@ typedef enum
|
||||
DEBUG_INFO_FULL
|
||||
} DebugInfo;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ARCH_OS_TARGET_DEFAULT = 0,
|
||||
X86_DARWIN,
|
||||
X86_LINUX,
|
||||
X64_DARWIN,
|
||||
X64_LINUX,
|
||||
X64_WINDOWS,
|
||||
AARCH64_LINUX,
|
||||
AARCH64_DARWIN,
|
||||
ARCH_OS_TARGET_LAST = AARCH64_DARWIN
|
||||
} ArchOsTarget;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* lib_dir[MAX_LIB_DIRS];
|
||||
int lib_count;
|
||||
const char** files;
|
||||
const char* project_name;
|
||||
const char* target;
|
||||
ArchOsTarget arch_os_target;
|
||||
const char* target_select;
|
||||
const char* path;
|
||||
const char* cpu;
|
||||
const char* target_triple;
|
||||
@@ -127,6 +141,7 @@ typedef struct
|
||||
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TARGET_TYPE_EXECUTABLE,
|
||||
|
||||
@@ -16,7 +16,7 @@ void build(void)
|
||||
file_find_top_dir();
|
||||
// Parse it
|
||||
Project *project = project_load();
|
||||
BuildTarget *target = project_select_target(project, build_options.target);
|
||||
BuildTarget *target = project_select_target(project, build_options.target_select);
|
||||
|
||||
if (!target->target_triple && build_options.target_triple)
|
||||
{
|
||||
|
||||
@@ -122,7 +122,7 @@ static void gencontext_verify_ir(GenContext *context)
|
||||
void gencontext_emit_object_file(GenContext *context)
|
||||
{
|
||||
char *err = "";
|
||||
LLVMSetTarget(context->module, build_options.target);
|
||||
LLVMSetTarget(context->module, build_options.target_triple);
|
||||
char *layout = LLVMCopyStringRepOfTargetData(target_data_layout());
|
||||
LLVMSetDataLayout(context->module, layout);
|
||||
LLVMDisposeMessage(layout);
|
||||
|
||||
@@ -174,7 +174,7 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsig
|
||||
{
|
||||
LLVMValueRef param = llvm_get_next_param(c, index);
|
||||
// Store it with the alignment of the decl.
|
||||
llvm_store_aligned_decl(c, decl, param);
|
||||
llvm_store_aligned(c, cast, param, decl->alignment);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ void gencontext_begin_module(GenContext *context)
|
||||
LLVMSetModuleDataLayout(context->module, target_data_layout());
|
||||
LLVMSetSourceFileName(context->module, full_path, strlen(context->ast_context->file->full_path));
|
||||
|
||||
LLVMSetTarget(context->module, build_options.target);
|
||||
LLVMSetTarget(context->module, build_target.target_triple);
|
||||
if (build_options.debug_info != DEBUG_INFO_NONE)
|
||||
{
|
||||
const char *filename = context->ast_context->file->name;
|
||||
|
||||
@@ -344,6 +344,16 @@ static inline void target_setup_x64_abi(void)
|
||||
}
|
||||
}
|
||||
|
||||
static char *arch_to_target_triple[ARCH_OS_TARGET_LAST + 1] = {
|
||||
[X86_DARWIN] = "i386-apple-darwin",
|
||||
[X86_LINUX] = "i386-pc-linux",
|
||||
[X64_DARWIN] = "x86_64-apple-darwin",
|
||||
[X64_LINUX] = "x86_64-pc-linux",
|
||||
[X64_WINDOWS] = "x86_64-pc-win32",
|
||||
[AARCH64_LINUX] = "aarch64-pc-linux",
|
||||
[AARCH64_DARWIN] = "aarch64-apple-darwin",
|
||||
};
|
||||
|
||||
void target_setup(void)
|
||||
{
|
||||
assert(!build_target.target);
|
||||
@@ -355,13 +365,19 @@ void target_setup(void)
|
||||
LLVMInitializeAllAsmParsers();
|
||||
|
||||
build_target.target = NULL;
|
||||
if (!build_options.target)
|
||||
{
|
||||
build_options.target = LLVMGetDefaultTargetTriple();
|
||||
}
|
||||
char *err = NULL;
|
||||
|
||||
if (LLVMGetTargetFromTriple(build_options.target, ((LLVMTargetRef *)&build_target.target), &err) != 0)
|
||||
const char *triple;
|
||||
if (build_options.arch_os_target == ARCH_OS_TARGET_DEFAULT)
|
||||
{
|
||||
triple = LLVMGetDefaultTargetTriple();
|
||||
}
|
||||
else
|
||||
{
|
||||
triple = arch_to_target_triple[build_options.arch_os_target];
|
||||
}
|
||||
|
||||
char *err = NULL;
|
||||
if (LLVMGetTargetFromTriple(triple, ((LLVMTargetRef *)&build_target.target), &err) != 0)
|
||||
{
|
||||
error_exit("Could not create target: %s", err);
|
||||
// Usually we would dispose of err, but no need to do it due to exit.
|
||||
@@ -369,7 +385,7 @@ void target_setup(void)
|
||||
|
||||
build_target.alloca_address_space = 0;
|
||||
|
||||
DEBUG_LOG("Target set to %s.", build_options.target);
|
||||
DEBUG_LOG("Target set to %s.", triple);
|
||||
// Create a specific target machine
|
||||
LLVMCodeGenOptLevel level;
|
||||
LLVMRelocMode reloc_mode = LLVMRelocDefault;
|
||||
@@ -403,7 +419,7 @@ void target_setup(void)
|
||||
{
|
||||
opt->features = "";
|
||||
}*/
|
||||
if (!(build_target.machine = LLVMCreateTargetMachine(build_target.target, build_options.target, "", "", level, reloc_mode,
|
||||
if (!(build_target.machine = LLVMCreateTargetMachine(build_target.target, triple, "", "", level, reloc_mode,
|
||||
LLVMCodeModelDefault))) {
|
||||
error_exit("Failed to create target machine.");
|
||||
}
|
||||
@@ -412,22 +428,19 @@ void target_setup(void)
|
||||
|
||||
char *target_triple = LLVMGetTargetMachineTriple(build_target.machine);
|
||||
|
||||
build_target.arch_name = strdup(strtok(target_triple, "-"));
|
||||
build_target.vendor_name = strdup(strtok(NULL, "-"));
|
||||
build_target.os_name = strdup(strtok(NULL, "-"));
|
||||
char *env = strtok(NULL, "0123456789");
|
||||
build_target.environment_name = env ? strdup(env) : "unknown";
|
||||
|
||||
LLVMDisposeMessage(target_triple);
|
||||
|
||||
build_target.arch = arch_from_llvm_string(build_target.arch_name);
|
||||
build_target.target_triple = strdup(target_triple);
|
||||
build_target.arch = arch_from_llvm_string(strtok(target_triple, "-"));
|
||||
if (!arch_is_supported(build_target.arch))
|
||||
{
|
||||
printf("WARNING! This architecture is not supported.\n");
|
||||
}
|
||||
build_target.environment_type = environment_type_from_llvm_string(build_target.environment_name);
|
||||
build_target.os = os_from_llvm_string(build_target.os_name);
|
||||
build_target.vendor = vendor_from_llvm_string(build_target.vendor_name);
|
||||
build_target.vendor = vendor_from_llvm_string(strtok(NULL, "-"));
|
||||
build_target.os = os_from_llvm_string(strtok(NULL, "-"));
|
||||
char *env = strtok(NULL, "0123456789");
|
||||
build_target.environment_type = env ? environment_type_from_llvm_string(env) : ENV_TYPE_UNKNOWN;
|
||||
|
||||
LLVMDisposeMessage(target_triple);
|
||||
|
||||
build_target.float_abi = false;
|
||||
build_target.width_pointer = arch_pointer_bit_width(build_target.os, build_target.arch);
|
||||
assert(build_target.width_pointer == LLVMPointerSize(build_target.llvm_data_layout) * 8);
|
||||
@@ -512,7 +525,7 @@ void target_setup(void)
|
||||
case ARCH_TYPE_ARC:
|
||||
case ARCH_TYPE_SPIR64:
|
||||
case ARCH_TYPE_SPIR:
|
||||
FATAL_ERROR("Unsupported arch %s.", build_target.arch_name);
|
||||
UNREACHABLE
|
||||
break;
|
||||
case ARCH_TYPE_AARCH64:
|
||||
case ARCH_TYPE_AARCH64_BE:
|
||||
|
||||
@@ -220,14 +220,11 @@ typedef struct
|
||||
void *target;
|
||||
void *machine;
|
||||
void *llvm_data_layout;
|
||||
const char *target_triple;
|
||||
ArchType arch;
|
||||
const char *arch_name;
|
||||
OsType os;
|
||||
const char *os_name;
|
||||
VendorType vendor;
|
||||
const char *vendor_name;
|
||||
EnvironmentType environment_type;
|
||||
const char *environment_name;
|
||||
ObjectFormatType object_format;
|
||||
int alloca_address_space;
|
||||
ABI abi;
|
||||
|
||||
Reference in New Issue
Block a user