Browse Source

Move out some intrinsics into separate procedures in llvm_backend.cpp; Rename `InlineRangeStmt` to `UnrollRangeStmt` (eventually merge the two AST nodes)

gingerBill 4 years ago
parent
commit
c29b643a58
6 changed files with 108 additions and 73 deletions
  1. 4 4
      src/check_stmt.cpp
  2. 2 2
      src/ir.cpp
  3. 72 43
      src/llvm_backend.cpp
  4. 6 0
      src/llvm_backend.hpp
  5. 22 22
      src/parser.cpp
  6. 2 2
      src/parser.hpp

+ 4 - 4
src/check_stmt.cpp

@@ -217,7 +217,7 @@ bool check_is_terminating(Ast *node, String const &label) {
 		}
 	case_end;
 
-	case_ast_node(rs, InlineRangeStmt, node);
+	case_ast_node(rs, UnrollRangeStmt, node);
 		return false;
 	case_end;
 
@@ -675,7 +675,7 @@ void add_constant_switch_case(CheckerContext *ctx, Map<TypeAndToken> *seen, Oper
 }
 
 void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
-	ast_node(irs, InlineRangeStmt, node);
+	ast_node(irs, UnrollRangeStmt, node);
 	check_open_scope(ctx, node);
 
 	Type *val0 = nullptr;
@@ -1303,7 +1303,7 @@ void check_block_stmt_for_errors(CheckerContext *ctx, Ast *body)  {
 			case Ast_IfStmt:
 			case Ast_ForStmt:
 			case Ast_RangeStmt:
-			case Ast_InlineRangeStmt:
+			case Ast_UnrollRangeStmt:
 			case Ast_SwitchStmt:
 			case Ast_TypeSwitchStmt:
 				// TODO(bill): Is this a correct checking system?
@@ -1903,7 +1903,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 		check_close_scope(ctx);
 	case_end;
 
-	case_ast_node(irs, InlineRangeStmt, node);
+	case_ast_node(irs, UnrollRangeStmt, node);
 		check_inline_range_stmt(ctx, node, mod_flags);
 	case_end;
 

+ 2 - 2
src/ir.cpp

@@ -10892,8 +10892,8 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
 		ir_start_block(proc, done);
 	case_end;
 
-	case_ast_node(rs, InlineRangeStmt, node);
-		ir_emit_comment(proc, str_lit("InlineRangeStmt"));
+	case_ast_node(rs, UnrollRangeStmt, node);
+		ir_emit_comment(proc, str_lit("UnrollRangeStmt"));
 		ir_open_scope(proc); // Open scope here
 
 		irBlock *done = ir_new_block(proc, node, "inline.for.done");

+ 72 - 43
src/llvm_backend.cpp

@@ -4295,7 +4295,7 @@ void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *scope) {
 	lb_start_block(p, done);
 }
 
-void lb_build_inline_range_stmt(lbProcedure *p, AstInlineRangeStmt *rs, Scope *scope) {
+void lb_build_inline_range_stmt(lbProcedure *p, AstUnrollRangeStmt *rs, Scope *scope) {
 	lbModule *m = p->module;
 
 	lb_open_scope(p, scope); // Open scope here
@@ -5288,7 +5288,7 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
 		lb_build_range_stmt(p, rs, node->scope);
 	case_end;
 
-	case_ast_node(rs, InlineRangeStmt, node);
+	case_ast_node(rs, UnrollRangeStmt, node);
 		lb_build_inline_range_stmt(p, rs, node->scope);
 	case_end;
 
@@ -9103,50 +9103,13 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 		}
 
 	case BuiltinProc_trailing_zeros:
-		{
-			lbValue x = lb_build_expr(p, ce->args[0]);
-			x = lb_emit_conv(p, x, tv.type);
-
-			char const *name = "llvm.cttz";
-			LLVMTypeRef types[1] = {lb_type(p->module, tv.type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-
-			LLVMValueRef args[2] = {};
-			args[0] = x.value;
-			args[1] = LLVMConstNull(LLVMInt1TypeInContext(p->module->ctx));
-
-			lbValue res = {};
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
-			res.type = tv.type;
-			return res;
-		}
+		return lb_emit_trailing_zeros(p, lb_build_expr(p, ce->args[0]), tv.type);
 
 	case BuiltinProc_count_ones:
-	case BuiltinProc_reverse_bits:
-		{
-			lbValue x = lb_build_expr(p, ce->args[0]);
-			x = lb_emit_conv(p, x, tv.type);
+		return lb_emit_count_ones(p, lb_build_expr(p, ce->args[0]), tv.type);
 
-			char const *name = nullptr;
-			switch (id) {
-			case BuiltinProc_count_ones:     name = "llvm.ctpop";      break;
-			case BuiltinProc_reverse_bits:   name = "llvm.bitreverse"; break;
-			}
-			LLVMTypeRef types[1] = {lb_type(p->module, tv.type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-
-			LLVMValueRef args[1] = {};
-			args[0] = x.value;
-
-			lbValue res = {};
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
-			res.type = tv.type;
-			return res;
-		}
+	case BuiltinProc_reverse_bits:
+		return lb_emit_reverse_bits(p, lb_build_expr(p, ce->args[0]), tv.type);
 
 	case BuiltinProc_byte_swap:
 		{
@@ -9985,6 +9948,72 @@ lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *end_type) {
 }
 
 
+lbValue lb_emit_count_ones(lbProcedure *p, lbValue x, Type *type) {
+	x = lb_emit_conv(p, x, type);
+
+	char const *name = "llvm.ctpop";
+	LLVMTypeRef types[1] = {lb_type(p->module, type)};
+	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
+	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
+	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
+
+	LLVMValueRef args[1] = {};
+	args[0] = x.value;
+
+	lbValue res = {};
+	res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+	res.type = type;
+	return res;
+}
+
+
+lbValue lb_emit_trailing_zeros(lbProcedure *p, lbValue x, Type *type) {
+	x = lb_emit_conv(p, x, type);
+
+	char const *name = "llvm.cttz";
+	LLVMTypeRef types[1] = {lb_type(p->module, type)};
+	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
+	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
+	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
+
+	LLVMValueRef args[2] = {};
+	args[0] = x.value;
+	args[1] = LLVMConstNull(LLVMInt1TypeInContext(p->module->ctx));
+
+	lbValue res = {};
+	res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+	res.type = type;
+	return res;
+}
+
+
+lbValue lb_emit_reverse_bits(lbProcedure *p, lbValue x, Type *type) {
+	x = lb_emit_conv(p, x, type);
+
+	char const *name = "llvm.bitreverse";
+	LLVMTypeRef types[1] = {lb_type(p->module, type)};
+	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
+	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
+	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
+
+	LLVMValueRef args[1] = {};
+	args[0] = x.value;
+
+	lbValue res = {};
+	res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+	res.type = type;
+	return res;
+}
+
+
+lbValue lb_emit_bit_set_card(lbProcedure *p, lbValue x) {
+	GB_ASSERT(is_type_bit_set(x.type));
+	Type *underlying = bit_set_to_int(x.type);
+	lbValue card = lb_emit_count_ones(p, x, underlying);
+	return lb_emit_conv(p, card, t_int);
+}
+
+
 lbLoopData lb_loop_start(lbProcedure *p, isize count, Type *index_type) {
 	lbLoopData data = {};
 

+ 6 - 0
src/llvm_backend.hpp

@@ -396,6 +396,12 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t);
 
 LLVMMetadataRef lb_debug_type(lbModule *m, Type *type);
 
+lbValue lb_emit_count_ones(lbProcedure *p, lbValue x, Type *type);
+lbValue lb_emit_trailing_zeros(lbProcedure *p, lbValue x, Type *type);
+lbValue lb_emit_reverse_bits(lbProcedure *p, lbValue x, Type *type);
+
+lbValue lb_emit_bit_set_card(lbProcedure *p, lbValue x);
+
 
 
 #define LB_STARTUP_RUNTIME_PROC_NAME   "__$startup_runtime"

+ 22 - 22
src/parser.cpp

@@ -58,7 +58,7 @@ Token ast_token(Ast *node) {
 	case Ast_ReturnStmt:         return node->ReturnStmt.token;
 	case Ast_ForStmt:            return node->ForStmt.token;
 	case Ast_RangeStmt:          return node->RangeStmt.token;
-	case Ast_InlineRangeStmt:    return node->InlineRangeStmt.inline_token;
+	case Ast_UnrollRangeStmt:    return node->UnrollRangeStmt.unroll_token;
 	case Ast_CaseClause:         return node->CaseClause.token;
 	case Ast_SwitchStmt:         return node->SwitchStmt.token;
 	case Ast_TypeSwitchStmt:     return node->TypeSwitchStmt.token;
@@ -319,11 +319,11 @@ Ast *clone_ast(Ast *node) {
 		n->RangeStmt.expr  = clone_ast(n->RangeStmt.expr);
 		n->RangeStmt.body  = clone_ast(n->RangeStmt.body);
 		break;
-	case Ast_InlineRangeStmt:
-		n->InlineRangeStmt.val0  = clone_ast(n->InlineRangeStmt.val0);
-		n->InlineRangeStmt.val1  = clone_ast(n->InlineRangeStmt.val1);
-		n->InlineRangeStmt.expr  = clone_ast(n->InlineRangeStmt.expr);
-		n->InlineRangeStmt.body  = clone_ast(n->InlineRangeStmt.body);
+	case Ast_UnrollRangeStmt:
+		n->UnrollRangeStmt.val0  = clone_ast(n->UnrollRangeStmt.val0);
+		n->UnrollRangeStmt.val1  = clone_ast(n->UnrollRangeStmt.val1);
+		n->UnrollRangeStmt.expr  = clone_ast(n->UnrollRangeStmt.expr);
+		n->UnrollRangeStmt.body  = clone_ast(n->UnrollRangeStmt.body);
 		break;
 	case Ast_CaseClause:
 		n->CaseClause.list  = clone_ast_array(n->CaseClause.list);
@@ -851,15 +851,15 @@ Ast *ast_range_stmt(AstFile *f, Token token, Slice<Ast *> vals, Token in_token,
 	return result;
 }
 
-Ast *ast_inline_range_stmt(AstFile *f, Token inline_token, Token for_token, Ast *val0, Ast *val1, Token in_token, Ast *expr, Ast *body) {
-	Ast *result = alloc_ast_node(f, Ast_InlineRangeStmt);
-	result->InlineRangeStmt.inline_token = inline_token;
-	result->InlineRangeStmt.for_token = for_token;
-	result->InlineRangeStmt.val0 = val0;
-	result->InlineRangeStmt.val1 = val1;
-	result->InlineRangeStmt.in_token = in_token;
-	result->InlineRangeStmt.expr  = expr;
-	result->InlineRangeStmt.body  = body;
+Ast *ast_unroll_range_stmt(AstFile *f, Token unroll_token, Token for_token, Ast *val0, Ast *val1, Token in_token, Ast *expr, Ast *body) {
+	Ast *result = alloc_ast_node(f, Ast_UnrollRangeStmt);
+	result->UnrollRangeStmt.unroll_token = unroll_token;
+	result->UnrollRangeStmt.for_token = for_token;
+	result->UnrollRangeStmt.val0 = val0;
+	result->UnrollRangeStmt.val1 = val1;
+	result->UnrollRangeStmt.in_token = in_token;
+	result->UnrollRangeStmt.expr  = expr;
+	result->UnrollRangeStmt.body  = body;
 	return result;
 }
 
@@ -4258,9 +4258,9 @@ Ast *parse_attribute(AstFile *f, Token token, TokenKind open_kind, TokenKind clo
 }
 
 
-Ast *parse_unrolled_for_loop(AstFile *f, Token inline_token) {
-	if (inline_token.kind == Token_inline) {
-		syntax_warning(inline_token, "'inline for' is deprecated in favour of `#unroll for'");
+Ast *parse_unrolled_for_loop(AstFile *f, Token unroll_token) {
+	if (unroll_token.kind == Token_inline) {
+		syntax_warning(unroll_token, "'inline for' is deprecated in favour of `#unroll for'");
 	}
 	Token for_token = expect_token(f, Token_for);
 	Ast *val0 = nullptr;
@@ -4308,9 +4308,9 @@ Ast *parse_unrolled_for_loop(AstFile *f, Token inline_token) {
 		body = parse_block_stmt(f, false);
 	}
 	if (bad_stmt) {
-		return ast_bad_stmt(f, inline_token, f->curr_token);
+		return ast_bad_stmt(f, unroll_token, f->curr_token);
 	}
-	return ast_inline_range_stmt(f, inline_token, for_token, val0, val1, in_token, expr, body);
+	return ast_unroll_range_stmt(f, unroll_token, for_token, val0, val1, in_token, expr, body);
 }
 
 Ast *parse_stmt(AstFile *f) {
@@ -4320,8 +4320,8 @@ Ast *parse_stmt(AstFile *f) {
 	// Operands
 	case Token_inline:
 		if (peek_token_kind(f, Token_for)) {
-			Token inline_token = expect_token(f, Token_inline);
-			return parse_unrolled_for_loop(f, inline_token);
+			Token unroll_token = expect_token(f, Token_inline);
+			return parse_unrolled_for_loop(f, unroll_token);
 		}
 		/* fallthrough */
 	case Token_no_inline:

+ 2 - 2
src/parser.hpp

@@ -415,8 +415,8 @@ AST_KIND(_ComplexStmtBegin, "", bool) \
 		Ast *expr; \
 		Ast *body; \
 	}) \
-	AST_KIND(InlineRangeStmt, "inline range statement", struct { \
-		Token inline_token; \
+	AST_KIND(UnrollRangeStmt, "#unroll range statement", struct { \
+		Token unroll_token; \
 		Token for_token; \
 		Ast *val0; \
 		Ast *val1; \