authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-13 11:53:20-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-13 11:53:20-05:00
loge7ab2bc5534a53c57c900618ec2411542dc50f69
tree42c572bf7414f59a98cd40a37e7d2f5d94955084
parent7903a758a44d1a253f17a4a2383f36b5fdad8545
parentc721354b73508ec53bf72d8e7fb304147676625d

Merge remote-tracking branch 'origin/master' into llvm6


4 files changed, 146 insertions(+), 57 deletions(-)

src/zig_llvm.cpp+8-27
......@@ -43,31 +43,8 @@
4343
4444#include <stdlib.h>
4545
46#if defined(_MSC_VER)
47#define ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
48#else
49#define ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
50#endif
51
5246using namespace llvm;
5347
54template<typename T, typename... Args>
55ATTRIBUTE_RETURNS_NOALIAS static inline T * create(Args... args) {
56 T * ptr = reinterpret_cast<T*>(malloc(sizeof(T)));
57 if (ptr == nullptr)
58 return nullptr;
59 new (ptr) T(args...);
60 return ptr;
61}
62
63template<typename T>
64static inline void destroy(T * ptr) {
65 if (ptr != nullptr) {
66 ptr[0].~T();
67 }
68 free(ptr);
69}
70
7148void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) {
7249 initializeLoopStrengthReducePass(*unwrap(R));
7350}
......@@ -116,7 +93,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
11693
11794 Module* module = unwrap(module_ref);
11895
119 PassManagerBuilder *PMBuilder = create<PassManagerBuilder>();
96 PassManagerBuilder *PMBuilder = new(std::nothrow) PassManagerBuilder();
97 if (PMBuilder == nullptr) {
98 *error_message = strdup("memory allocation failure");
99 return true;
100 }
120101 PMBuilder->OptLevel = target_machine->getOptLevel();
121102 PMBuilder->SizeLevel = 0;
122103
......@@ -150,7 +131,8 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
150131
151132 // Set up the per-function pass manager.
152133 legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module);
153 FPM.add(create<TargetLibraryInfoWrapperPass>(tlii));
134 auto tliwp = new(std::nothrow) TargetLibraryInfoWrapperPass(tlii);
135 FPM.add(tliwp);
154136 FPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
155137 if (assertions_on) {
156138 FPM.add(createVerifierPass());
......@@ -446,10 +428,9 @@ unsigned ZigLLVMTag_DW_union_type(void) {
446428}
447429
448430ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) {
449 DIBuilder *di_builder = reinterpret_cast<DIBuilder*>(malloc(sizeof(DIBuilder)));
431 DIBuilder *di_builder = new(std::nothrow) DIBuilder(*unwrap(module), allow_unresolved);
450432 if (di_builder == nullptr)
451433 return nullptr;
452 new (di_builder) DIBuilder(*unwrap(module), allow_unresolved);
453434 return reinterpret_cast<ZigLLVMDIBuilder *>(di_builder);
454435}
455436
std/zig/ast.zig+17-15
......@@ -18,6 +18,7 @@ pub const Node = struct {
1818 PrefixOp,
1919 IntegerLiteral,
2020 FloatLiteral,
21 BuiltinCall,
2122 };
2223
2324 pub fn iterate(base: &Node, index: usize) ?&Node {
......@@ -32,21 +33,7 @@ pub const Node = struct {
3233 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
3334 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index),
3435 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index),
35 };
36 }
37
38 pub fn destroy(base: &Node, allocator: &mem.Allocator) void {
39 return switch (base.id) {
40 Id.Root => allocator.destroy(@fieldParentPtr(NodeRoot, "base", base)),
41 Id.VarDecl => allocator.destroy(@fieldParentPtr(NodeVarDecl, "base", base)),
42 Id.Identifier => allocator.destroy(@fieldParentPtr(NodeIdentifier, "base", base)),
43 Id.FnProto => allocator.destroy(@fieldParentPtr(NodeFnProto, "base", base)),
44 Id.ParamDecl => allocator.destroy(@fieldParentPtr(NodeParamDecl, "base", base)),
45 Id.Block => allocator.destroy(@fieldParentPtr(NodeBlock, "base", base)),
46 Id.InfixOp => allocator.destroy(@fieldParentPtr(NodeInfixOp, "base", base)),
47 Id.PrefixOp => allocator.destroy(@fieldParentPtr(NodePrefixOp, "base", base)),
48 Id.IntegerLiteral => allocator.destroy(@fieldParentPtr(NodeIntegerLiteral, "base", base)),
49 Id.FloatLiteral => allocator.destroy(@fieldParentPtr(NodeFloatLiteral, "base", base)),
36 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
5037 };
5138 }
5239};
......@@ -269,3 +256,18 @@ pub const NodeFloatLiteral = struct {
269256 return null;
270257 }
271258};
259
260pub const NodeBuiltinCall = struct {
261 base: Node,
262 builtin_token: Token,
263 params: ArrayList(&Node),
264
265 pub fn iterate(self: &NodeBuiltinCall, index: usize) ?&Node {
266 var i = index;
267
268 if (i < self.params.len) return self.params.at(i);
269 i -= self.params.len;
270
271 return null;
272 }
273};
std/zig/parser.zig+2-1
......@@ -95,7 +95,8 @@ pub const Parser = struct {
9595 };
9696
9797 /// Returns an AST tree, allocated with the parser's allocator.
98 /// Result should be freed with `freeAst` when done.
98 /// Result should be freed with tree.deinit() when there are
99 /// no more references to any AST nodes of the tree.
99100 pub fn parse(self: &Parser) !Tree {
100101 var stack = self.initUtilityArrayList(State);
101102 defer self.deinitUtilityArrayList(stack);
std/zig/tokenizer.zig+119-14
......@@ -68,9 +68,12 @@ pub const Token = struct {
6868 Invalid,
6969 Identifier,
7070 StringLiteral: StrLitKind,
71 StringIdentifier,
7172 Eof,
7273 Builtin,
7374 Bang,
75 Pipe,
76 PipeEqual,
7477 Equal,
7578 EqualEqual,
7679 BangEqual,
......@@ -192,6 +195,7 @@ pub const Tokenizer = struct {
192195 StringLiteralBackslash,
193196 Equal,
194197 Bang,
198 Pipe,
195199 Minus,
196200 Slash,
197201 LineComment,
......@@ -205,6 +209,7 @@ pub const Tokenizer = struct {
205209 Ampersand,
206210 Period,
207211 Period2,
212 SawAtSign,
208213 };
209214
210215 pub fn next(self: &Tokenizer) Token {
......@@ -238,8 +243,7 @@ pub const Tokenizer = struct {
238243 result.id = Token.Id.Identifier;
239244 },
240245 '@' => {
241 state = State.Builtin;
242 result.id = Token.Id.Builtin;
246 state = State.SawAtSign;
243247 },
244248 '=' => {
245249 state = State.Equal;
......@@ -247,6 +251,9 @@ pub const Tokenizer = struct {
247251 '!' => {
248252 state = State.Bang;
249253 },
254 '|' => {
255 state = State.Pipe;
256 },
250257 '(' => {
251258 result.id = Token.Id.LParen;
252259 self.index += 1;
......@@ -313,6 +320,20 @@ pub const Tokenizer = struct {
313320 break;
314321 },
315322 },
323
324 State.SawAtSign => switch (c) {
325 '"' => {
326 result.id = Token.Id.StringIdentifier;
327 state = State.StringLiteral;
328 },
329 else => {
330 // reinterpret as a builtin
331 self.index -= 1;
332 state = State.Builtin;
333 result.id = Token.Id.Builtin;
334 },
335 },
336
316337 State.Ampersand => switch (c) {
317338 '=' => {
318339 result.id = Token.Id.AmpersandEqual;
......@@ -379,6 +400,18 @@ pub const Tokenizer = struct {
379400 },
380401 },
381402
403 State.Pipe => switch (c) {
404 '=' => {
405 result.id = Token.Id.PipeEqual;
406 self.index += 1;
407 break;
408 },
409 else => {
410 result.id = Token.Id.Pipe;
411 break;
412 },
413 },
414
382415 State.Equal => switch (c) {
383416 '=' => {
384417 result.id = Token.Id.EqualEqual;
......@@ -510,9 +543,62 @@ pub const Tokenizer = struct {
510543 else => break,
511544 },
512545 }
513 }
514 result.end = self.index;
546 } else if (self.index == self.buffer.len) {
547 switch (state) {
548 State.Start,
549 State.C,
550 State.IntegerLiteral,
551 State.IntegerLiteralWithRadix,
552 State.FloatFraction,
553 State.FloatExponentNumber,
554 State.StringLiteral, // find this error later
555 State.Builtin => {},
556
557 State.Identifier => {
558 if (Token.getKeyword(self.buffer[result.start..self.index])) |id| {
559 result.id = id;
560 }
561 },
562 State.LineComment => {
563 result.id = Token.Id.Eof;
564 },
565
566 State.NumberDot,
567 State.FloatExponentUnsigned,
568 State.SawAtSign,
569 State.StringLiteralBackslash => {
570 result.id = Token.Id.Invalid;
571 },
515572
573 State.Equal => {
574 result.id = Token.Id.Equal;
575 },
576 State.Bang => {
577 result.id = Token.Id.Bang;
578 },
579 State.Minus => {
580 result.id = Token.Id.Minus;
581 },
582 State.Slash => {
583 result.id = Token.Id.Slash;
584 },
585 State.Zero => {
586 result.id = Token.Id.IntegerLiteral;
587 },
588 State.Ampersand => {
589 result.id = Token.Id.Ampersand;
590 },
591 State.Period => {
592 result.id = Token.Id.Period;
593 },
594 State.Period2 => {
595 result.id = Token.Id.Ellipsis2;
596 },
597 State.Pipe => {
598 result.id = Token.Id.Pipe;
599 },
600 }
601 }
516602 if (result.id == Token.Id.Eof) {
517603 if (self.pending_invalid_token) |token| {
518604 self.pending_invalid_token = null;
......@@ -520,6 +606,7 @@ pub const Tokenizer = struct {
520606 }
521607 }
522608
609 result.end = self.index;
523610 return result;
524611 }
525612
......@@ -551,7 +638,7 @@ pub const Tokenizer = struct {
551638 } else {
552639 // check utf8-encoded character.
553640 const length = std.unicode.utf8ByteSequenceLength(c0) catch return 1;
554 if (self.index + length >= self.buffer.len) {
641 if (self.index + length > self.buffer.len) {
555642 return u3(self.buffer.len - self.index);
556643 }
557644 const bytes = self.buffer[self.index..self.index + length];
......@@ -632,15 +719,32 @@ test "tokenizer - illegal unicode codepoints" {
632719 testTokenize("//\xe2\x80\xaa", []Token.Id{});
633720}
634721
722test "tokenizer - string identifier and builtin fns" {
723 testTokenize(
724 \\const @"if" = @import("std");
725 ,
726 []Token.Id{
727 Token.Id.Keyword_const,
728 Token.Id.StringIdentifier,
729 Token.Id.Equal,
730 Token.Id.Builtin,
731 Token.Id.LParen,
732 Token.Id {.StringLiteral = Token.StrLitKind.Normal},
733 Token.Id.RParen,
734 Token.Id.Semicolon,
735 }
736 );
737}
738
739test "tokenizer - pipe and then invalid" {
740 testTokenize("||=", []Token.Id{
741 Token.Id.Pipe,
742 Token.Id.PipeEqual,
743 });
744}
745
635746fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
636 // (test authors, just make this bigger if you need it)
637 var padded_source: [0x100]u8 = undefined;
638 std.mem.copy(u8, padded_source[0..source.len], source);
639 padded_source[source.len + 0] = '\n';
640 padded_source[source.len + 1] = '\n';
641 padded_source[source.len + 2] = '\n';
642
643 var tokenizer = Tokenizer.init(padded_source[0..source.len + 3]);
747 var tokenizer = Tokenizer.init(source);
644748 for (expected_tokens) |expected_token_id| {
645749 const token = tokenizer.next();
646750 std.debug.assert(@TagType(Token.Id)(token.id) == @TagType(Token.Id)(expected_token_id));
......@@ -651,5 +755,6 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
651755 else => {},
652756 }
653757 }
654 std.debug.assert(tokenizer.next().id == Token.Id.Eof);
758 const last_token = tokenizer.next();
759 std.debug.assert(last_token.id == Token.Id.Eof);
655760}