zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit a9dd8d75431357a59238da3fd949aa1f11eead84 (tree)
parent c6a0a4e7282d746ebf2b54df16161c5993ea5aa8
Author: Evan Haas <evan@lagerdata.com>
Date:   Tue,  1 Jun 2021 20:00:46 -0700

translate-c: Fix performance hazard in transPreprocessorEntities

Fixes O(N^2) behavior of `transPreprocessorEntities` due to repeated calls to
`mem.len`

Closes #8959

Diffstat:
Msrc/clang.zig | 7+++++++
Msrc/translate_c.zig | 5++++-
Msrc/zig_clang.cpp | 7+++++++
Msrc/zig_clang.h | 2++
4 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/clang.zig b/src/clang.zig @@ -607,6 +607,13 @@ pub const IntegerLiteral = opaque { extern fn ZigClangIntegerLiteral_isZero(*const IntegerLiteral, *bool, *const ASTContext) bool; }; +/// This is just used as a namespace for a static method on clang's Lexer class; we don't directly +/// deal with Lexer objects +pub const Lexer = struct { + pub const getLocForEndOfToken = ZigClangLexer_getLocForEndOfToken; + extern fn ZigClangLexer_getLocForEndOfToken(SourceLocation, *const SourceManager, *const ASTUnit) SourceLocation; +}; + pub const MacroDefinitionRecord = opaque { pub const getName_getNameStart = ZigClangMacroDefinitionRecord_getName_getNameStart; extern fn ZigClangMacroDefinitionRecord_getName_getNameStart(*const MacroDefinitionRecord) [*:0]const u8; diff --git a/src/translate_c.zig b/src/translate_c.zig @@ -4688,6 +4688,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { const macro = @ptrCast(*clang.MacroDefinitionRecord, entity); const raw_name = macro.getName_getNameStart(); const begin_loc = macro.getSourceRange_getBegin(); + const end_loc = clang.Lexer.getLocForEndOfToken(macro.getSourceRange_getEnd(), c.source_manager, unit); const name = try c.str(raw_name); // TODO https://github.com/ziglang/zig/issues/3756 @@ -4698,7 +4699,9 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { } const begin_c = c.source_manager.getCharacterData(begin_loc); - const slice = begin_c[0..mem.len(begin_c)]; + const end_c = c.source_manager.getCharacterData(end_loc); + const slice_len = @ptrToInt(end_c) - @ptrToInt(begin_c); + const slice = begin_c[0..slice_len]; var tokenizer = std.c.Tokenizer{ .buffer = slice, diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp @@ -3100,6 +3100,13 @@ struct ZigClangSourceLocation ZigClangMacroDefinitionRecord_getSourceRange_getEn return bitcast(casted->getSourceRange().getEnd()); } +struct ZigClangSourceLocation ZigClangLexer_getLocForEndOfToken(ZigClangSourceLocation loc, const ZigClangSourceManager *sm, const ZigClangASTUnit *unit) { + const clang::SourceManager *casted_sm = reinterpret_cast<const clang::SourceManager *>(sm); + const clang::ASTUnit *casted_unit = reinterpret_cast<const clang::ASTUnit *>(unit); + clang::SourceLocation endloc = clang::Lexer::getLocForEndOfToken(bitcast(loc), 0, *casted_sm, casted_unit->getLangOpts()); + return bitcast(endloc); +} + ZigClangRecordDecl_field_iterator ZigClangRecordDecl_field_begin(const struct ZigClangRecordDecl *self) { auto casted = reinterpret_cast<const clang::RecordDecl *>(self); return bitcast(casted->field_begin()); diff --git a/src/zig_clang.h b/src/zig_clang.h @@ -966,6 +966,8 @@ ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const struct Zig ZIG_EXTERN_C struct ZigClangQualType ZigClangASTContext_getPointerType(const struct ZigClangASTContext*, struct ZigClangQualType T); +ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangLexer_getLocForEndOfToken(struct ZigClangSourceLocation, + const ZigClangSourceManager *, const ZigClangASTUnit *); // Can return null. ZIG_EXTERN_C struct ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end,