Ver código fonte

Change ternary expression precedence

Ginger Bill 8 anos atrás
pai
commit
d2f9d20833
6 arquivos alterados com 271 adições e 197 exclusões
  1. 2 3
      code/demo.odin
  2. 2 10
      core/fmt.odin
  3. 182 126
      src/ir.c
  4. 45 9
      src/ir_print.c
  5. 5 4
      src/main.c
  6. 35 45
      src/parser.c

+ 2 - 3
code/demo.odin

@@ -5,12 +5,10 @@
 #import "mem.odin";
 #import "opengl.odin";
 #import "os.odin";
-#import "utf8.odin";
+#import "halloc.odin";
 
 
 main :: proc() {
-	x: f32 = false ? 123 : 55;
-	fmt.println("Ternary:", x);
 /*
 /*
 	Version 0.1.1
@@ -29,6 +27,7 @@ main :: proc() {
 	 * immutable variables are "completely immutable" - rules need a full explanation
 	 * `slice_to_bytes` - convert any slice to a slice of bytes
 	 * `union_cast` allows for optional ok check
+	 * ?: ternary operator
 
 	Removed:
 	 * Maybe/option types

+ 2 - 10
core/fmt.odin

@@ -116,11 +116,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
 		case ti == type_info(int):  buffer_write_string(buf, "int");
 		case ti == type_info(uint): buffer_write_string(buf, "uint");
 		default:
-			if info.signed {
-				buffer_write_string(buf, "i");
-			} else {
-				buffer_write_string(buf, "u");
-			}
+			buffer_write_string(buf, info.signed ? "i" : "u");
 			fi := Fmt_Info{buf = buf};
 			fmt_int(^fi, cast(u64)(8*info.size), false, 'd');
 		}
@@ -396,11 +392,7 @@ fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) {
 fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) {
 	match verb {
 	case 't', 'v':
-		if b {
-			buffer_write_string(buf, "true");
-		} else {
-			buffer_write_string(buf, "false");
-		}
+		buffer_write_string(buf, b ? "true" : "false");
 	default:
 		fmt_bad_verb(fi, verb);
 	}

+ 182 - 126
src/ir.c

@@ -15,13 +15,14 @@ typedef Array(irValue *) irValueArray;
 #define MAP_NAME MapIrDebugInfo
 #include "map.c"
 
+
 typedef struct irModule {
 	CheckerInfo * info;
 	gbArena       arena;
 	gbArena       tmp_arena;
 	gbAllocator   allocator;
 	gbAllocator   tmp_allocator;
-	bool generate_debug_info;
+	// bool generate_debug_info;
 
 	u32 stmt_state_flags;
 
@@ -29,20 +30,20 @@ typedef struct irModule {
 	String layout;
 	// String triple;
 
-	MapEntity       min_dep_map; // Key: Entity *
-	MapIrValue      values;      // Key: Entity *
-	MapIrValue      members;     // Key: String
-	MapString       type_names;  // Key: Type *
-	MapIrDebugInfo  debug_info;  // Key: Unique pointer
-	i32             global_string_index;
-	i32             global_array_index; // For ConstantSlice
+	MapEntity             min_dep_map; // Key: Entity *
+	MapIrValue            values;      // Key: Entity *
+	MapIrValue            members;     // Key: String
+	MapString             type_names;  // Key: Type *
+	MapIrDebugInfo        debug_info;  // Key: Unique pointer
+	i32                   global_string_index;
+	i32                   global_array_index; // For ConstantSlice
 
-	Entity *        entry_point_entity;
+	Entity *              entry_point_entity;
 
-	Array(irProcedure *) procs;             // NOTE(bill): All procedures with bodies
-	irValueArray         procs_to_generate; // NOTE(bill): Procedures to generate
+	Array(irProcedure *)  procs;             // NOTE(bill): All procedures with bodies
+	irValueArray          procs_to_generate; // NOTE(bill): Procedures to generate
 
-	Array(String) foreign_library_paths; // Only the ones that were used
+	Array(String)         foreign_library_paths; // Only the ones that were used
 } irModule;
 
 // NOTE(bill): For more info, see https://en.wikipedia.org/wiki/Dominator_(graph_theory)
@@ -121,6 +122,7 @@ struct irProcedure {
 	irTargetList *       target_list;
 	irValueArray         referrers;
 
+
 	i32                  local_count;
 	i32                  instr_count;
 	i32                  block_count;
@@ -134,90 +136,99 @@ struct irProcedure {
 
 
 #define IR_INSTR_KINDS \
-	IR_INSTR_KIND(Comment, struct { String text; }) \
-	IR_INSTR_KIND(Local,   struct { \
-		Entity *      entity; \
-		Type *        type; \
-		bool          zero_initialized; \
-		irValueArray referrers; \
-	}) \
-	IR_INSTR_KIND(ZeroInit, struct { irValue *address; }) \
-	IR_INSTR_KIND(Store,    struct { irValue *address, *value; }) \
+	IR_INSTR_KIND(Comment, struct { String text; })                   \
+	IR_INSTR_KIND(Local,   struct {                                   \
+		Entity *      entity;                                         \
+		Type *        type;                                           \
+		bool          zero_initialized;                               \
+		irValueArray referrers;                                       \
+	})                                                                \
+	IR_INSTR_KIND(ZeroInit, struct { irValue *address; })             \
+	IR_INSTR_KIND(Store,    struct { irValue *address, *value; })     \
 	IR_INSTR_KIND(Load,     struct { Type *type; irValue *address; }) \
-	IR_INSTR_KIND(PtrOffset, struct { \
-		irValue *address; \
-		irValue *offset; \
-	}) \
-	IR_INSTR_KIND(ArrayElementPtr, struct { \
-		irValue *address; \
-		Type *   result_type; \
-		irValue *elem_index; \
-	}) \
-	IR_INSTR_KIND(StructElementPtr, struct {  \
-		irValue *address; \
-		Type *    result_type; \
-		i32       elem_index; \
-	}) \
-	IR_INSTR_KIND(StructExtractValue, struct { \
-		irValue *address; \
-		Type *    result_type; \
-		i32       index; \
-	}) \
-	IR_INSTR_KIND(UnionTagPtr, struct { \
-		irValue *address; \
-		Type     *type; /* ^int */  \
-	}) \
-	IR_INSTR_KIND(UnionTagValue, struct { \
-		irValue *address; \
-		Type     *type; /* int */ \
-	}) \
-	IR_INSTR_KIND(Conv, struct { \
-		irConvKind kind; \
-		irValue *value; \
-		Type *from, *to; \
-	}) \
-	IR_INSTR_KIND(Jump, struct { irBlock *block; }) \
-	IR_INSTR_KIND(If, struct { \
-		irValue *cond; \
-		irBlock *true_block; \
-		irBlock *false_block; \
+	IR_INSTR_KIND(PtrOffset, struct {                                 \
+		irValue *address;                                             \
+		irValue *offset;                                              \
+	})                                                                \
+	IR_INSTR_KIND(ArrayElementPtr, struct {                           \
+		irValue *address;                                             \
+		Type *   result_type;                                         \
+		irValue *elem_index;                                          \
+	})                                                                \
+	IR_INSTR_KIND(StructElementPtr, struct {                          \
+		irValue *address;                                             \
+		Type *    result_type;                                        \
+		i32       elem_index;                                         \
+	})                                                                \
+	IR_INSTR_KIND(StructExtractValue, struct {                        \
+		irValue *address;                                             \
+		Type *    result_type;                                        \
+		i32       index;                                              \
+	})                                                                \
+	IR_INSTR_KIND(UnionTagPtr, struct {                               \
+		irValue *address;                                             \
+		Type     *type; /* ^int */                                    \
+	})                                                                \
+	IR_INSTR_KIND(UnionTagValue, struct {                             \
+		irValue *address;                                             \
+		Type     *type; /* int */                                     \
+	})                                                                \
+	IR_INSTR_KIND(Conv, struct {                                      \
+		irConvKind kind;                                              \
+		irValue *value;                                               \
+		Type *from, *to;                                              \
+	})                                                                \
+	IR_INSTR_KIND(Jump, struct { irBlock *block; })                   \
+	IR_INSTR_KIND(If, struct {                                        \
+		irValue *cond;                                                \
+		irBlock *true_block;                                          \
+		irBlock *false_block;                                         \
+	})                                                                \
+	IR_INSTR_KIND(Return, struct { irValue *value; })                 \
+	IR_INSTR_KIND(Select, struct {                                    \
+		irValue *cond;                                                \
+		irValue *true_value;                                          \
+		irValue *false_value;                                         \
+	})                                                                \
+	IR_INSTR_KIND(Phi, struct { irValueArray edges; Type *type; })    \
+	IR_INSTR_KIND(Unreachable, i32)                                   \
+	IR_INSTR_KIND(UnaryOp, struct {                                   \
+		Type *    type;                                               \
+		TokenKind op;                                                 \
+		irValue * expr;                                               \
+	})                                                                \
+	IR_INSTR_KIND(BinaryOp, struct {                                  \
+		Type *    type;                                               \
+		TokenKind op;                                                 \
+		irValue * left, *right;                                       \
+	})                                                                \
+	IR_INSTR_KIND(Call, struct {                                      \
+		Type *    type; /* return type */                             \
+		irValue * value;                                              \
+		irValue **args;                                               \
+		isize     arg_count;                                          \
+	})                                                                \
+	IR_INSTR_KIND(StartupRuntime, i32)                                \
+	IR_INSTR_KIND(BoundsCheck, struct {                               \
+		TokenPos pos;                                                 \
+		irValue *index;                                               \
+		irValue *len;                                                 \
+	})                                                                \
+	IR_INSTR_KIND(SliceBoundsCheck, struct {                          \
+		TokenPos pos;                                                 \
+		irValue *low;                                                 \
+		irValue *high;                                                \
+		bool     is_substring;                                        \
+	})                                                                \
+	IR_INSTR_KIND(DebugDeclare, struct { \
+		irDebugInfo *debug_info; \
+		AstNode *    expr; \
+		Entity *     entity; \
+		bool         is_addr; \
+		irValue *    value; \
 	}) \
-	IR_INSTR_KIND(Return, struct { irValue *value; }) \
-	IR_INSTR_KIND(Select, struct { \
-		irValue *cond; \
-		irValue *true_value; \
-		irValue *false_value; \
-	}) \
-	IR_INSTR_KIND(Phi, struct { irValueArray edges; Type *type; }) \
-	IR_INSTR_KIND(Unreachable, i32) \
-	IR_INSTR_KIND(UnaryOp, struct { \
-		Type *    type; \
-		TokenKind op; \
-		irValue *expr; \
-	}) \
-	IR_INSTR_KIND(BinaryOp, struct { \
-		Type *    type; \
-		TokenKind op; \
-		irValue *left, *right; \
-	}) \
-	IR_INSTR_KIND(Call, struct { \
-		Type *    type; /* return type */  \
-		irValue *value; \
-		irValue **args; \
-		isize      arg_count; \
-	}) \
-	IR_INSTR_KIND(StartupRuntime, i32) \
-	IR_INSTR_KIND(BoundsCheck, struct { \
-		TokenPos  pos; \
-		irValue *index; \
-		irValue *len; \
-	}) \
-	IR_INSTR_KIND(SliceBoundsCheck, struct { \
-		TokenPos  pos; \
-		irValue *low; \
-		irValue *high; \
-		bool      is_substring; \
-	})
+
+
 
 #define IR_CONV_KINDS \
 	IR_CONV_KIND(trunc) \
@@ -394,7 +405,6 @@ irAddr ir_make_addr_map(irValue *addr, irValue *map_key, Type *map_type, Type *m
 	return v;
 }
 
-
 typedef enum irDebugEncoding {
 	irDebugBasicEncoding_Invalid       = 0,
 
@@ -519,14 +529,19 @@ struct irDebugInfo {
 	};
 };
 
+
+
 typedef struct irGen {
 	irModule module;
-	gbFile    output_file;
-	bool       opt_called;
+	gbFile   output_file;
+	bool     opt_called;
 } irGen;
 
 
 
+
+
+
 Type *ir_type(irValue *value);
 Type *ir_instr_type(irInstr *instr) {
 	switch (instr->kind) {
@@ -948,6 +963,16 @@ irValue *ir_make_instr_slice_bounds_check(irProcedure *p, TokenPos pos, irValue
 	v->Instr.SliceBoundsCheck.is_substring = is_substring;
 	return v;
 }
+irValue *ir_make_instr_debug_declare(irProcedure *p, irDebugInfo *debug_info, AstNode *expr, Entity *entity, bool is_addr, irValue *value) {
+	irValue *v = ir_alloc_instr(p, irInstr_DebugDeclare);
+	v->Instr.DebugDeclare.debug_info = debug_info;
+	v->Instr.DebugDeclare.expr       = expr;
+	v->Instr.DebugDeclare.entity     = entity;
+	v->Instr.DebugDeclare.is_addr    = is_addr;
+	v->Instr.DebugDeclare.value      = value;
+	return v;
+
+}
 
 
 
@@ -967,6 +992,23 @@ irValue *ir_make_value_constant_slice(gbAllocator a, Type *type, irValue *backin
 	return v;
 }
 
+
+
+irValue *ir_emit(irProcedure *proc, irValue *instr) {
+	GB_ASSERT(instr->kind == irValue_Instr);
+	irBlock *b = proc->curr_block;
+	instr->Instr.parent = b;
+	if (b != NULL) {
+		irInstr *i = ir_get_last_instr(b);
+		if (!ir_is_instr_terminating(i)) {
+			array_add(&b->instrs, instr);
+		}
+	}
+	return instr;
+}
+
+
+
 irValue *ir_make_const_int(gbAllocator a, i64 i) {
 	return ir_make_value_constant(a, t_int, make_exact_value_integer(i));
 }
@@ -1166,7 +1208,7 @@ irValue *ir_add_global_string_array(irModule *m, String string) {
 
 
 
-irValue *ir_add_local(irProcedure *proc, Entity *e) {
+irValue *ir_add_local(irProcedure *proc, Entity *e, AstNode *expr) {
 	irBlock *b = proc->decl_block; // all variables must be in the first block
 	irValue *instr = ir_make_instr_local(proc, e, true);
 	instr->Instr.parent = b;
@@ -1178,6 +1220,11 @@ irValue *ir_add_local(irProcedure *proc, Entity *e) {
 		ir_emit_zero_init(proc, instr);
 	// }
 
+	if (expr != NULL) {
+		irDebugInfo *di = *map_ir_debug_info_get(&proc->module->debug_info, hash_pointer(proc->entity));
+		ir_emit(proc, ir_make_instr_debug_declare(proc, di, expr, e, true, instr));
+	}
+
 	return instr;
 }
 
@@ -1186,7 +1233,7 @@ irValue *ir_add_local_for_identifier(irProcedure *proc, AstNode *name, bool zero
 	if (found) {
 		Entity *e = *found;
 		ir_emit_comment(proc, e->token.string);
-		return ir_add_local(proc, e);
+		return ir_add_local(proc, e, name);
 	}
 	return NULL;
 }
@@ -1202,14 +1249,14 @@ irValue *ir_add_local_generated(irProcedure *proc, Type *type) {
 	                                 scope,
 	                                 empty_token,
 	                                 type, false);
-	return ir_add_local(proc, e);
+	return ir_add_local(proc, e, NULL);
 }
 
 
-irValue *ir_add_param(irProcedure *proc, Entity *e) {
+irValue *ir_add_param(irProcedure *proc, Entity *e, AstNode *expr) {
 	irValue *v = ir_make_value_param(proc->module->allocator, proc, e);
 #if 1
-	irValue *l = ir_add_local(proc, e);
+	irValue *l = ir_add_local(proc, e, expr);
 	ir_emit_store(proc, l, v);
 
 #else
@@ -1227,9 +1274,9 @@ irValue *ir_add_param(irProcedure *proc, Entity *e) {
 ////////////////////////////////////////////////////////////////
 
 irDebugInfo *ir_add_debug_info_file(irProcedure *proc, AstFile *file) {
-	if (!proc->module->generate_debug_info) {
-		return NULL;
-	}
+	// if (!proc->module->generate_debug_info) {
+	// 	return NULL;
+	// }
 
 	GB_ASSERT(file != NULL);
 	irDebugInfo *di = ir_alloc_debug_info(proc->module->allocator, irDebugInfo_File);
@@ -1259,9 +1306,9 @@ irDebugInfo *ir_add_debug_info_file(irProcedure *proc, AstFile *file) {
 
 
 irDebugInfo *ir_add_debug_info_proc(irProcedure *proc, Entity *entity, String name, irDebugInfo *file) {
-	if (!proc->module->generate_debug_info) {
-		return NULL;
-	}
+	// if (!proc->module->generate_debug_info) {
+	// 	return NULL;
+	// }
 
 	GB_ASSERT(entity != NULL);
 	irDebugInfo *di = ir_alloc_debug_info(proc->module->allocator, irDebugInfo_Proc);
@@ -1281,18 +1328,7 @@ irDebugInfo *ir_add_debug_info_proc(irProcedure *proc, Entity *entity, String na
 ////////////////////////////////////////////////////////////////
 
 
-irValue *ir_emit(irProcedure *proc, irValue *instr) {
-	GB_ASSERT(instr->kind == irValue_Instr);
-	irBlock *b = proc->curr_block;
-	instr->Instr.parent = b;
-	if (b != NULL) {
-		irInstr *i = ir_get_last_instr(b);
-		if (!ir_is_instr_terminating(i)) {
-			array_add(&b->instrs, instr);
-		}
-	}
-	return instr;
-}
+
 irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value) {
 #if 1
 	// NOTE(bill): Sanity check
@@ -5357,7 +5393,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 
 				irValue *tag_var = NULL;
 				if (tag_var_entity != NULL) {
-					tag_var = ir_add_local(proc, tag_var_entity);
+					tag_var = ir_add_local(proc, tag_var_entity, NULL);
 				} else {
 					tag_var = ir_add_local_generated(proc, tag_var_type);
 				}
@@ -5385,7 +5421,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 
 				irValue *tag_var = NULL;
 				if (tag_var_entity != NULL) {
-					tag_var = ir_add_local(proc, tag_var_entity);
+					tag_var = ir_add_local(proc, tag_var_entity, NULL);
 				} else {
 					tag_var = ir_add_local_generated(proc, tag_var_type);
 				}
@@ -5558,12 +5594,24 @@ void ir_begin_procedure_body(irProcedure *proc) {
 	ir_start_block(proc, proc->entry_block);
 
 	if (proc->type->Proc.params != NULL) {
+		ast_node(pt, ProcType, proc->type_expr);
+		isize param_index = 0;
+		isize q_index = 0;
+
 		TypeTuple *params = &proc->type->Proc.params->Tuple;
 		for (isize i = 0; i < params->variable_count; i++) {
+			GB_ASSERT(pt->params.e[0]->kind == AstNode_Field);
+			if (q_index == pt->params.e[param_index]->Field.names.count) {
+				q_index = 0;
+				param_index++;
+			}
+			ast_node(field, Field, pt->params.e[param_index]);
+			AstNode *name = field->names.e[q_index++];
+
 			Entity *e = params->variables[i];
 			if (!str_eq(e->token.string, str_lit("")) &&
 			    !str_eq(e->token.string, str_lit("_"))) {
-				irValue *param = ir_add_param(proc, e);
+				irValue *param = ir_add_param(proc, e, name);
 				array_add(&proc->params, param);
 			}
 		}
@@ -5790,7 +5838,7 @@ bool ir_gen_init(irGen *s, Checker *c) {
 	}
 
 	ir_init_module(&s->module, c);
-	s->module.generate_debug_info = false;
+	// s->module.generate_debug_info = false;
 
 	// TODO(bill): generate appropriate output name
 	int pos = cast(int)string_extension_position(c->parser->init_fullpath);
@@ -6025,7 +6073,9 @@ void ir_gen_tree(irGen *s) {
 				name = pd->link_name;
 			}
 
-			irValue *p = ir_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name);
+			AstNode *type_expr = decl->proc_lit->ProcLit.type;
+
+			irValue *p = ir_make_value_procedure(a, m, e, e->type, type_expr, body, name);
 			p->Proc.tags = pd->tags;
 
 			ir_module_add_value(m, e, p);
@@ -6067,7 +6117,6 @@ void ir_gen_tree(irGen *s) {
 	for_array(i, m->debug_info.entries) {
 		MapIrDebugInfoEntry *entry = &m->debug_info.entries.e[i];
 		irDebugInfo *di = entry->value;
-		di->id = i;
 		if (di->kind == irDebugInfo_Proc) {
 			array_add(&all_procs->AllProcs.procs, di);
 		}
@@ -6619,6 +6668,13 @@ void ir_gen_tree(irGen *s) {
 		ir_build_proc(m->procs_to_generate.e[i], m->procs_to_generate.e[i]->Proc.parent);
 	}
 
+	// Number debug info
+	for_array(i, m->debug_info.entries) {
+		MapIrDebugInfoEntry *entry = &m->debug_info.entries.e[i];
+		irDebugInfo *di = entry->value;
+		di->id = i;
+	}
+
 
 	// m->layout = str_lit("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
 }

+ 45 - 9
src/ir_print.c

@@ -1254,6 +1254,29 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_fprintf(f, ")\n");
 	} break;
 
+	case irInstr_DebugDeclare: {
+		/* irInstrDebugDeclare *dd = &instr->DebugDeclare;
+		Type *vt = ir_type(dd->value);
+		irDebugInfo *di = dd->debug_info;
+		Entity *e = dd->entity;
+		String name = e->token.string;
+		TokenPos pos = e->token.pos;
+		// gb_printf("debug_declare %.*s\n", LIT(dd->entity->token.string));
+		ir_fprintf(f, "call void @llvm.dbg.declare(");
+		ir_fprintf(f, "metadata ");
+		ir_print_type(f, m, vt);
+		ir_fprintf(f, " ");
+		ir_print_value(f, m, dd->value, vt);
+		ir_fprintf(f, ", metadata !DILocalVariable(name: \"");
+		ir_print_escape_string(f, name, false);
+		ir_fprintf(f, "\", scope: !%d, line: %td)", di->id, pos.line);
+		ir_fprintf(f, ", metadata !DIExpression()");
+		ir_fprintf(f, ")");
+		ir_fprintf(f, ", !dbg !DILocation(line: %td, column: %td, scope: !%d)", pos.line, pos.column, di->id);
+
+		ir_fprintf(f, "\n"); */
+	} break;
+
 
 	default: {
 		GB_PANIC("<unknown instr> %d\n", instr->kind);
@@ -1326,11 +1349,14 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 	}
 
 
-	if (proc->module->generate_debug_info && proc->entity != NULL) {
+	if (proc->entity != NULL) {
 		if (proc->body != NULL) {
-			irDebugInfo *di = *map_ir_debug_info_get(&proc->module->debug_info, hash_pointer(proc->entity));
-			GB_ASSERT(di->kind == irDebugInfo_Proc);
-			ir_fprintf(f, "!dbg !%d ", di->id);
+			irDebugInfo **di_ = map_ir_debug_info_get(&proc->module->debug_info, hash_pointer(proc->entity));
+			if (di_ != NULL) {
+				irDebugInfo *di = *di_;
+				GB_ASSERT(di->kind == irDebugInfo_Proc);
+				// ir_fprintf(f, "!dbg !%d ", di->id);
+			}
 		}
 	}
 
@@ -1396,6 +1422,8 @@ void print_llvm_ir(irGen *ir) {
 	ir_print_type(f, m, t_rawptr);
 	ir_fprintf(f, "} ; Basic_any\n");
 
+	ir_fprintf(f, "declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone \n");
+
 
 	for_array(member_index, m->members.entries) {
 		MapIrValueEntry *entry = &m->members.entries.e[member_index];
@@ -1482,9 +1510,18 @@ void print_llvm_ir(irGen *ir) {
 
 
 #if 0
-	if (m->generate_debug_info) {
+	// if (m->generate_debug_info) {
+	{
 		ir_fprintf(f, "\n");
+
+		i32 diec = m->debug_info.entries.count;
+
 		ir_fprintf(f, "!llvm.dbg.cu = !{!0}\n");
+		ir_fprintf(f, "!llvm.ident = !{!%d}\n", diec+3);
+		ir_fprintf(f, "!%d = !{i32 2, !\"Dwarf Version\", i32 4}\n", diec+0);
+		ir_fprintf(f, "!%d = !{i32 2, !\"Debug Info Version\", i32 3}\n", diec+1);
+		ir_fprintf(f, "!%d = !{i32 1, !\"PIC Level\", i32 2}\n", diec+2);
+		ir_fprintf(f, "!%d = !{!\"clang version 3.9.0 (branches/release_39)\"}\n", diec+3);
 
 		for_array(di_index, m->debug_info.entries) {
 			MapIrDebugInfoEntry *entry = &m->debug_info.entries.e[di_index];
@@ -1493,19 +1530,18 @@ void print_llvm_ir(irGen *ir) {
 
 			switch (di->kind) {
 			case irDebugInfo_CompileUnit: {
-				auto *cu = &di->CompileUnit;
-				irDebugInfo *file = *map_ir_debug_info_get(&m->debug_info, hash_pointer(cu->file));
+				irDebugInfo *file = *map_ir_debug_info_get(&m->debug_info, hash_pointer(di->CompileUnit.file));
 				ir_fprintf(f,
 				            "distinct !DICompileUnit("
 				            "language: DW_LANG_Go, " // Is this good enough?
 				            "file: !%d, "
-				            "producer: \"%.*s\", "
+				            "producer: \"clang version 3.9.0 (branches/release_39)\", "
 				            "flags: \"\", "
 				            "runtimeVersion: 0, "
 				            "isOptimized: false, "
 				            "emissionKind: FullDebug"
 				            ")",
-				            file->id, LIT(cu->producer));
+				            file->id);
 
 			} break;
 			case irDebugInfo_File:

+ 5 - 4
src/main.c

@@ -2,6 +2,7 @@
 extern "C" {
 #endif
 
+
 #include "common.c"
 #include "timings.c"
 #include "build_settings.c"
@@ -216,10 +217,10 @@ int main(int argc, char **argv) {
 		return 1;
 	}
 
-	ssa_generate(&checker.info, &build_context);
-#endif
-#if 1
-
+	if (!ssa_generate(&checker.info)) {
+		return 1;
+	}
+#else
 	irGen ir_gen = {0};
 	if (!ir_gen_init(&ir_gen, &checker)) {
 		return 1;

+ 35 - 45
src/parser.c

@@ -1949,19 +1949,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
 			}
 			break;
 
-		case Token_Question:
-			if (!lhs && operand != NULL && f->expr_level >= 0) {
-				AstNode *cond = operand;
-				Token token_q = expect_token(f, Token_Question);
-				AstNode *x = parse_expr(f, false);
-				Token token_c = expect_token(f, Token_Colon);
-				AstNode *y = parse_expr(f, false);
-				operand = ast_ternary_expr(f, cond, x, y);
-			} else {
-				loop = false;
-			}
-			break;
-
 		default:
 			loop = false;
 			break;
@@ -2016,22 +2003,24 @@ AstNode *parse_unary_expr(AstFile *f, bool lhs) {
 // NOTE(bill): result == priority
 i32 token_precedence(TokenKind t) {
 	switch (t) {
-	case Token_CmpOr:
+	case Token_Question:
 		return 1;
-	case Token_CmpAnd:
+	case Token_CmpOr:
 		return 2;
+	case Token_CmpAnd:
+		return 3;
 	case Token_CmpEq:
 	case Token_NotEq:
 	case Token_Lt:
 	case Token_Gt:
 	case Token_LtEq:
 	case Token_GtEq:
-		return 3;
+		return 4;
 	case Token_Add:
 	case Token_Sub:
 	case Token_Or:
 	case Token_Xor:
-		return 4;
+		return 5;
 	case Token_Mul:
 	case Token_Quo:
 	case Token_Mod:
@@ -2039,51 +2028,42 @@ i32 token_precedence(TokenKind t) {
 	case Token_AndNot:
 	case Token_Shl:
 	case Token_Shr:
-		return 5;
-	// case Token_as:
-	// case Token_transmute:
-	// case Token_down_cast:
-	// case Token_union_cast:
-		// return 6;
+		return 6;
 	}
 	return 0;
 }
 
 AstNode *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
-	AstNode *expression = parse_unary_expr(f, lhs);
+	AstNode *expr = parse_unary_expr(f, lhs);
 	for (i32 prec = token_precedence(f->curr_token.kind); prec >= prec_in; prec--) {
 		for (;;) {
-			AstNode *right;
 			Token op = f->curr_token;
 			i32 op_prec = token_precedence(op.kind);
 			if (op_prec != prec) {
+				// NOTE(bill): This will also catch operators that are not valid "binary" operators
 				break;
 			}
 			expect_operator(f); // NOTE(bill): error checks too
-			if (lhs) {
-				// TODO(bill): error checking
-				lhs = false;
-			}
 
-			switch (op.kind) {
-			/* case Token_as:
-			case Token_transmute:
-			case Token_down_cast:
-			case Token_union_cast:
-				right = parse_type(f);
-				break; */
-
-			default:
-				right = parse_binary_expr(f, false, prec+1);
+			if (op.kind == Token_Question) {
+				AstNode *cond = expr;
+				// Token_Question
+				AstNode *x = parse_expr(f, lhs);
+				Token token_c = expect_token(f, Token_Colon);
+				AstNode *y = parse_expr(f, lhs);
+				expr = ast_ternary_expr(f, cond, x, y);
+			} else {
+				AstNode *right = parse_binary_expr(f, false, prec+1);
 				if (!right) {
-					syntax_error(op, "Expected expression on the right hand side of the binary operator");
+					syntax_error(op, "Expected expression on the right-hand side of the binary operator");
 				}
-				break;
+				expr = ast_binary_expr(f, op, expr, right);
 			}
-			expression = ast_binary_expr(f, op, expression, right);
+
+			lhs = false;
 		}
 	}
-	return expression;
+	return expr;
 }
 
 AstNode *parse_expr(AstFile *f, bool lhs) {
@@ -3458,8 +3438,18 @@ AstNode *parse_stmt(AstFile *f) {
 			return s;
 		}
 
-		expect_semicolon(f, s);
-		return ast_tag_stmt(f, hash_token, name, parse_stmt(f));
+
+		if (str_eq(tag, str_lit("include"))) {
+			syntax_error(token, "#include is not a valid import declaration kind. Use #load instead");
+			s = ast_bad_stmt(f, token, f->curr_token);
+		} else {
+			syntax_error(token, "Unknown tag used: `%.*s`", LIT(tag));
+			s = ast_bad_stmt(f, token, f->curr_token);
+		}
+
+		fix_advance_to_next_stmt(f);
+
+		return s;
 	} break;
 
 	case Token_OpenBrace: