about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/codegen.pry27
-rw-r--r--src/bootstrap/llvm.pry5
-rw-r--r--src/bootstrap/parser.pry46
3 files changed, 77 insertions, 1 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry
index 57f5472..be2ee5c 100644
--- a/src/bootstrap/codegen.pry
+++ b/src/bootstrap/codegen.pry
@@ -95,6 +95,7 @@ let codegen = struct {
 	whil_block: LLVMBasicBlockRef,
 	current_function: LLVMValueRef,
 	current_function_retur_type: *Node,
+	llvm_target_data: LLVMTargetDataRef,
 };
 
 let codegen_init = (alloc: *arena) => *codegen {
@@ -111,6 +112,7 @@ let codegen_init = (alloc: *arena) => *codegen {
 	let c = cast(*codegen, arena_alloc(alloc, sizeof(codegen)));
 	
 	(*c).llvm_module = module;
+	(*c).llvm_target_data = LLVMGetModuleDataLayout(module);
 	(*c).llvm_context = context;
 	(*c).builder = builder;
 	(*c).arena = alloc;
@@ -693,7 +695,6 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		v.stack_level = cast(*i64, null);
 		v.node = expression;
 		v.node_type = expression;
-		printf("RET\n");
 		return codegen_create_variable(c, v);
 	};
 	
@@ -713,6 +714,30 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		v.node_type = exp.typ;
 		return codegen_create_variable(c, v);
 	};
+	
+	if ((*expression).type == NODE_SIZEOF_STATEMENT) {
+		let exp = *cast(*NODE_SIZEOF_STATEMENT_DATA, (*expression).data);
+		let typ = codegen_get_llvm_type(c, exp.typ);
+		assert(typ != cast(*LLVMTypeRef, null));
+		let size_in_bytes = LLVMStoreSizeOfType((*c).llvm_target_data, *typ);
+		let size_val = LLVMConstInt(LLVMInt64Type(), size_in_bytes, 0);
+
+		let node_type = Node{};
+		node_type.type = NODE_TYPE_SIMPLE_TYPE;
+
+		let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA)));
+		(*d).name = "i64";
+		(*d).underlying_type = cast(*Node, null);
+		node_type.data = cast(*void, d);
+
+		let v = Variable{};
+		v.value = size_val;
+		v.type = cast(LLVMTypeRef, null);
+		v.stack_level = cast(*i64, null);
+		v.node = expression;
+		v.node_type = create_node(c, node_type);
+		return codegen_create_variable(c, v);
+	};
 
 	printf("ASSERT 1: %d\n", (*expression).type);
 	assert(false);
diff --git a/src/bootstrap/llvm.pry b/src/bootstrap/llvm.pry
index 3f794e3..1771908 100644
--- a/src/bootstrap/llvm.pry
+++ b/src/bootstrap/llvm.pry
@@ -252,6 +252,7 @@ let LLVMInitializeAllDisassemblers = () => void {
 
 let LLVMBuilderRef = newtype *void;
 let LLVMModuleRef = newtype *void;
+let LLVMTargetDataRef = newtype *void;
 let LLVMTargetMachineRef = newtype *void;
 let LLVMContextRef = newtype *void;
 let LLVMTargetRef = newtype *void;
@@ -262,6 +263,7 @@ let LLVMValueKind = newtype i64;
 let LLVMTypeRef = newtype *void;
 let LLVMBasicBlockRef = newtype *void;
 
+extern LLVMGetModuleDataLayout = (LLVMModuleRef) => LLVMTargetDataRef;
 extern LLVMConstInt = (LLVMTypeRef, i64, i64) => LLVMValueRef;
 extern LLVMInt64Type = () => LLVMTypeRef;
 extern LLVMInt1Type = () => LLVMTypeRef;
@@ -341,3 +343,6 @@ let LLVMIntSGT = 38;
 let LLVMIntSGE = 39;
 let LLVMIntSLT = 40;
 let LLVMIntSLE = 41;
+
+extern LLVMStoreSizeOfType = (LLVMTargetDataRef, LLVMTypeRef) => i64;
+
diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry
index 5c34edb..355b54d 100644
--- a/src/bootstrap/parser.pry
+++ b/src/bootstrap/parser.pry
@@ -345,6 +345,40 @@ let parser_parse_cast_statement = (p: *parser) => *Node {
 	return create_node(p, r);
 };
 
+/* SizeOfStatement ::= "sizeof" LPAREN TYPE RPAREN */
+let parser_parse_sizeof_statement = (p: *parser) => *Node {
+	let ident = parser_accept_token(p, TOKEN_IDENTIFIER);
+	if ident == cast(*token, null) {
+		return cast(*Node, null);
+	};
+
+	if !strcmp(cast(*i8, (*ident).data), "sizeof") {
+		return cast(*Node, null);
+	};
+
+	if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) {
+		return cast(*Node, null);
+	};
+	
+	let typ = parser_parse_type(p);
+	if typ == cast(*Node, null) {
+		return cast(*Node, null);
+	};
+	
+	if parser_accept_token(p, TOKEN_RPAREN) == cast(*token, null) {
+		return cast(*Node, null);
+	};
+
+	let d = cast(*NODE_SIZEOF_STATEMENT_DATA , arena_alloc((*p).arena, sizeof(NODE_SIZEOF_STATEMENT_DATA )));
+	(*d).typ = typ;
+
+	let r = Node{};
+	r.type = NODE_SIZEOF_STATEMENT;
+	r.data = cast(*void, d);
+
+	return create_node(p, r);
+};
+
 /* FunctionType ::= LPAREN (Type ("," Type)*)? RPAREN ARROW Type */
 let parser_parse_function_type = (p: *parser) => *Node {
 	if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) {
@@ -824,6 +858,10 @@ let parser_parse_postfix_expression = (p: *parser) => *Node {
 	if ex != cast(*Node, null) {
 		return ex;
 	};
+	let ex = parser_accept_parse(p, parser_parse_sizeof_statement);
+	if ex != cast(*Node, null) {
+		return ex;
+	};
 	let ex = parser_accept_parse(p, parse_function_call_statement);
 	if ex != cast(*Node, null) {
 		return ex;
@@ -1136,6 +1174,14 @@ let parser_parse_statement = (p: *parser) => *Node {
 		};
 	    return fn_call;
 	};
+	
+	let fn_call = parser_accept_parse(p, parser_parse_sizeof_statement);
+	if fn_call != cast(*Node, null) {
+		if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) {
+		    return cast(*Node, null);
+		};
+	    return fn_call;
+	};
 
 	let fn_call = parser_accept_parse(p, parse_function_call_statement);
 	if fn_call != cast(*Node, null) {