Commit d121ed961a

Andrew Kelley <superjoe30@gmail.com>
2016-01-14 06:18:10
fix noalias codegen
also make some parsing error messages better
1 parent 95a7f35
src/analyze.cpp
@@ -2914,6 +2914,11 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
         AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl;
         TypeTableEntry *type = unwrapped_node_type(param_decl->type);
 
+        if (param_decl->is_noalias && type->id != TypeTableEntryIdPointer) {
+            add_node_error(g, param_decl_node,
+                buf_sprintf("noalias on non-pointer parameter"));
+        }
+
         if (is_exported && type->id == TypeTableEntryIdStruct) {
             add_node_error(g, param_decl_node,
                 buf_sprintf("byvalue struct parameters not yet supported on exported functions"));
src/codegen.cpp
@@ -2034,9 +2034,8 @@ static void do_code_gen(CodeGen *g) {
             AstNode *type_node = param_node->data.param_decl.type;
             TypeTableEntry *param_type = fn_proto_type_from_type_node(g, type_node);
             LLVMValueRef argument_val = LLVMGetParam(fn, gen_param_index);
-            if (param_type->id == TypeTableEntryIdPointer &&
-                false) // TODO test if parameter is noalias
-            {
+            bool param_is_noalias = param_node->data.param_decl.is_noalias;
+            if (param_type->id == TypeTableEntryIdPointer && param_is_noalias) {
                 LLVMAddAttribute(argument_val, LLVMNoAliasAttribute);
             } else if (param_type->id == TypeTableEntryIdPointer &&
                        param_type->data.pointer.is_const)
src/parser.cpp
@@ -913,9 +913,13 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
 static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory);
 
 static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
-    if (token->id != token_id) {
-        ast_invalid_token_error(pc, token);
+    if (token->id == token_id) {
+        return;
     }
+
+    Buf token_value = BUF_INIT;
+    ast_buf_from_token(pc, token, &token_value);
+    ast_error(pc, token, "expected token '%s', found '%s'", token_name(token_id), token_name(token->id));
 }
 
 static Token *ast_eat_token(ParseContext *pc, int *token_index, TokenId token_id) {
src/tokenizer.cpp
@@ -994,94 +994,101 @@ void tokenize(Buf *buf, Tokenization *out) {
             break;
     }
     if (t.state != TokenizeStateError) {
-        t.pos = -1;
+        if (t.tokens->length > 0) {
+            Token *last_token = &t.tokens->last();
+            t.line = last_token->start_line;
+            t.column = last_token->start_column;
+            t.pos = last_token->start_pos;
+        } else {
+            t.pos = 0;
+        }
         begin_token(&t, TokenIdEof);
         end_token(&t);
         assert(!t.cur_tok);
     }
 }
 
-static const char * token_name(Token *token) {
-    switch (token->id) {
+const char * token_name(TokenId id) {
+    switch (id) {
         case TokenIdEof: return "EOF";
         case TokenIdSymbol: return "Symbol";
-        case TokenIdKeywordFn: return "Fn";
-        case TokenIdKeywordConst: return "Const";
-        case TokenIdKeywordVar: return "Var";
-        case TokenIdKeywordReturn: return "Return";
-        case TokenIdKeywordExtern: return "Extern";
-        case TokenIdKeywordPub: return "Pub";
-        case TokenIdKeywordExport: return "Export";
-        case TokenIdKeywordAs: return "As";
-        case TokenIdKeywordUse: return "Use";
-        case TokenIdKeywordTrue: return "True";
-        case TokenIdKeywordFalse: return "False";
-        case TokenIdKeywordIf: return "If";
-        case TokenIdKeywordElse: return "Else";
-        case TokenIdKeywordGoto: return "Goto";
-        case TokenIdKeywordVolatile: return "Volatile";
-        case TokenIdKeywordAsm: return "Asm";
-        case TokenIdKeywordStruct: return "Struct";
-        case TokenIdKeywordEnum: return "Enum";
-        case TokenIdKeywordWhile: return "While";
-        case TokenIdKeywordContinue: return "Continue";
-        case TokenIdKeywordBreak: return "Break";
-        case TokenIdKeywordNull: return "Null";
-        case TokenIdKeywordNoAlias: return "NoAlias";
-        case TokenIdLParen: return "LParen";
-        case TokenIdRParen: return "RParen";
-        case TokenIdComma: return "Comma";
-        case TokenIdStar: return "Star";
-        case TokenIdLBrace: return "LBrace";
-        case TokenIdRBrace: return "RBrace";
-        case TokenIdLBracket: return "LBracket";
-        case TokenIdRBracket: return "RBracket";
+        case TokenIdKeywordFn: return "fn";
+        case TokenIdKeywordConst: return "const";
+        case TokenIdKeywordVar: return "var";
+        case TokenIdKeywordReturn: return "return";
+        case TokenIdKeywordExtern: return "extern";
+        case TokenIdKeywordPub: return "pub";
+        case TokenIdKeywordExport: return "export";
+        case TokenIdKeywordAs: return "as";
+        case TokenIdKeywordUse: return "use";
+        case TokenIdKeywordTrue: return "true";
+        case TokenIdKeywordFalse: return "false";
+        case TokenIdKeywordIf: return "if";
+        case TokenIdKeywordElse: return "else";
+        case TokenIdKeywordGoto: return "goto";
+        case TokenIdKeywordVolatile: return "volatile";
+        case TokenIdKeywordAsm: return "asm";
+        case TokenIdKeywordStruct: return "struct";
+        case TokenIdKeywordEnum: return "enum";
+        case TokenIdKeywordWhile: return "while";
+        case TokenIdKeywordContinue: return "continue";
+        case TokenIdKeywordBreak: return "break";
+        case TokenIdKeywordNull: return "null";
+        case TokenIdKeywordNoAlias: return "noalias";
+        case TokenIdLParen: return "(";
+        case TokenIdRParen: return ")";
+        case TokenIdComma: return ",";
+        case TokenIdStar: return "*";
+        case TokenIdLBrace: return "{";
+        case TokenIdRBrace: return "}";
+        case TokenIdLBracket: return "[";
+        case TokenIdRBracket: return "]";
         case TokenIdStringLiteral: return "StringLiteral";
         case TokenIdCharLiteral: return "CharLiteral";
-        case TokenIdSemicolon: return "Semicolon";
+        case TokenIdSemicolon: return ";";
         case TokenIdNumberLiteral: return "NumberLiteral";
-        case TokenIdPlus: return "Plus";
-        case TokenIdColon: return "Colon";
-        case TokenIdArrow: return "Arrow";
-        case TokenIdFatArrow: return "FatArrow";
-        case TokenIdDash: return "Dash";
-        case TokenIdNumberSign: return "NumberSign";
-        case TokenIdBinOr: return "BinOr";
-        case TokenIdAmpersand: return "Ampersand";
-        case TokenIdBinXor: return "BinXor";
-        case TokenIdBoolOr: return "BoolOr";
-        case TokenIdBoolAnd: return "BoolAnd";
-        case TokenIdEq: return "Eq";
-        case TokenIdTimesEq: return "TimesEq";
-        case TokenIdDivEq: return "DivEq";
-        case TokenIdModEq: return "ModEq";
-        case TokenIdPlusEq: return "PlusEq";
-        case TokenIdMinusEq: return "MinusEq";
-        case TokenIdBitShiftLeftEq: return "BitShiftLeftEq";
-        case TokenIdBitShiftRightEq: return "BitShiftRightEq";
-        case TokenIdBitAndEq: return "BitAndEq";
-        case TokenIdBitXorEq: return "BitXorEq";
-        case TokenIdBitOrEq: return "BitOrEq";
-        case TokenIdBoolAndEq: return "BoolAndEq";
-        case TokenIdBoolOrEq: return "BoolOrEq";
-        case TokenIdBang: return "Bang";
-        case TokenIdTilde: return "Tilde";
-        case TokenIdCmpEq: return "CmpEq";
-        case TokenIdCmpNotEq: return "CmpNotEq";
-        case TokenIdCmpLessThan: return "CmpLessThan";
-        case TokenIdCmpGreaterThan: return "CmpGreaterThan";
-        case TokenIdCmpLessOrEq: return "CmpLessOrEq";
-        case TokenIdCmpGreaterOrEq: return "CmpGreaterOrEq";
-        case TokenIdBitShiftLeft: return "BitShiftLeft";
-        case TokenIdBitShiftRight: return "BitShiftRight";
-        case TokenIdSlash: return "Slash";
-        case TokenIdPercent: return "Percent";
-        case TokenIdDot: return "Dot";
-        case TokenIdEllipsis: return "Ellipsis";
-        case TokenIdMaybe: return "Maybe";
-        case TokenIdDoubleQuestion: return "DoubleQuestion";
-        case TokenIdMaybeAssign: return "MaybeAssign";
-        case TokenIdAtSign: return "AtSign";
+        case TokenIdPlus: return "+";
+        case TokenIdColon: return ":";
+        case TokenIdArrow: return "->";
+        case TokenIdFatArrow: return "=>";
+        case TokenIdDash: return "-";
+        case TokenIdNumberSign: return "#";
+        case TokenIdBinOr: return "|";
+        case TokenIdAmpersand: return "&";
+        case TokenIdBinXor: return "^";
+        case TokenIdBoolOr: return "||";
+        case TokenIdBoolAnd: return "&&";
+        case TokenIdEq: return "=";
+        case TokenIdTimesEq: return "*=";
+        case TokenIdDivEq: return "/=";
+        case TokenIdModEq: return "%=";
+        case TokenIdPlusEq: return "+=";
+        case TokenIdMinusEq: return "-=";
+        case TokenIdBitShiftLeftEq: return "<<=";
+        case TokenIdBitShiftRightEq: return ">>=";
+        case TokenIdBitAndEq: return "&=";
+        case TokenIdBitXorEq: return "^=";
+        case TokenIdBitOrEq: return "|=";
+        case TokenIdBoolAndEq: return "&&=";
+        case TokenIdBoolOrEq: return "||=";
+        case TokenIdBang: return "!";
+        case TokenIdTilde: return "~";
+        case TokenIdCmpEq: return "==";
+        case TokenIdCmpNotEq: return "!=";
+        case TokenIdCmpLessThan: return "<";
+        case TokenIdCmpGreaterThan: return ">";
+        case TokenIdCmpLessOrEq: return "<=";
+        case TokenIdCmpGreaterOrEq: return ">=";
+        case TokenIdBitShiftLeft: return "<<";
+        case TokenIdBitShiftRight: return ">>";
+        case TokenIdSlash: return "/";
+        case TokenIdPercent: return "%";
+        case TokenIdDot: return ".";
+        case TokenIdEllipsis: return "...";
+        case TokenIdMaybe: return "?";
+        case TokenIdDoubleQuestion: return "??";
+        case TokenIdMaybeAssign: return "?=";
+        case TokenIdAtSign: return "@";
     }
     return "(invalid token)";
 }
@@ -1089,7 +1096,7 @@ static const char * token_name(Token *token) {
 void print_tokens(Buf *buf, ZigList<Token> *tokens) {
     for (int i = 0; i < tokens->length; i += 1) {
         Token *token = &tokens->at(i);
-        fprintf(stderr, "%s ", token_name(token));
+        fprintf(stderr, "%s ", token_name(token->id));
         if (token->start_pos >= 0) {
             fwrite(buf_ptr(buf) + token->start_pos, 1, token->end_pos - token->start_pos, stderr);
         }
src/tokenizer.hpp
@@ -122,4 +122,6 @@ void print_tokens(Buf *buf, ZigList<Token> *tokens);
 bool is_printable(uint8_t c);
 int get_digit_value(uint8_t c);
 
+const char * token_name(TokenId id);
+
 #endif
test/run_tests.cpp
@@ -1396,6 +1396,10 @@ fn f() @bogus(foo) => {
 const a : @typeof(b) = 0;
 const b : @typeof(a) = 0;
     )SOURCE", 1, ".tmp_source.zig:3:19: error: use of undeclared identifier 'a'");
+
+    add_compile_fail_case("noalias on non pointer param", R"SOURCE(
+fn f(noalias x: i32) => {}
+    )SOURCE", 1, ".tmp_source.zig:2:6: error: noalias on non-pointer parameter");
 }
 
 static void print_compiler_invocation(TestCase *test_case) {