Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions common/build_target.c2
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module build_target;
import file_list local;
import src_loc local;
import string_list;
import string_map;
import string_pool;
import warning_flags;

Expand Down Expand Up @@ -110,7 +111,7 @@ public type Target struct @(opaque) {
bool backend_fast;
bool optional;

string_list.List features;
string_map.Map features;
List libs;
string_list.List exports;
PluginList plugins;
Expand Down Expand Up @@ -152,10 +153,10 @@ public fn u32 Target.numFiles(const Target* t) { return t.files.getCount(); }

public fn u32 Target.numAsmFiles(const Target* t) { return t.asm_files.getCount(); }

public fn const string_list.List* Target.getFeatures(const Target* t) { return &t.features; }
public fn const string_map.Map* Target.getFeatures(const Target* t) { return &t.features; }

public fn void Target.addFeature(Target* t, u32 feature) {
t.features.add(feature);
t.features.addNameValue(feature, "1");
}

public fn void Target.removeFeature(Target* t, u32 feature) {
Expand Down
2 changes: 1 addition & 1 deletion common/string_list.c2
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public fn void List.addStr(List* l, const char* str) {
l.add(l.pool.addStr(str, true));
}

public fn bool List.contains(const List* l, const char* name) {
public fn bool List.contains(const List* l, const char* name) @(unused) {
for (u32 i=0; i<l.count; i++) {
if (strcmp(l.pool.idx2str(l.indexes[i]), name) == 0) return true;
}
Expand Down
153 changes: 153 additions & 0 deletions common/string_map.c2
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/* Copyright 2022-2026 Bas van den Berg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

module string_map;

import string_pool;
import string local;
import stdlib local;

public type Map struct {
string_pool.Pool* pool;
u32* names; // into pool
u32* values; // into pool
u32 count;
u32 capacity;
}

public fn void Map.init(Map* m, string_pool.Pool* pool) {
memset(m, 0, sizeof(Map));
m.pool = pool;
m.resize(16);
}

public fn void Map.free(Map* m) {
free(m.names);
free(m.values);
m.names = nil;
m.values = nil;
m.count = 0;
m.capacity = 0;
}

public fn void Map.clear(Map* m) @(unused) {
m.count = 0;
}

fn void Map.resize(Map* m, u32 capacity) {
m.capacity = capacity;
u32* names2 = malloc(capacity * sizeof(u32));
u32* values2 = malloc(capacity * sizeof(u32));
if (m.count) {
memcpy(names2, m.names, m.count * sizeof(u32));
memcpy(values2, m.values, m.count * sizeof(u32));
free(m.names);
free(m.values);
}
m.names = names2;
m.values = values2;
}

public fn void Map.add(Map* m, u32 name_idx, u32 value_idx) @(unused) {
if (m.count == m.capacity) m.resize(m.capacity * 2);

m.names[m.count] = name_idx;
m.values[m.count] = value_idx;
m.count++;
}

// remove an index from the string map
// return number of items removed.
public fn u32 Map.del(Map* m, u32 name_idx) {
u32 j = 0;
u32 count = m.count;
for (u32 i = 0; i < count; i++) {
if (m.names[i] != name_idx) {
m.names[j] = m.names[i];
m.values[j] = m.values[i];
j++;
}
}
m.count = j;
return count - j;
}

public fn void Map.addStr(Map* m, const char* str, const char* val) @(unused) {
m.add(m.pool.addStr(str, true), m.pool.addStr(val, true));
}

public fn void Map.addNameValue(Map* m, u32 idx, const char* def) {
const char* str = m.pool.idx2str(idx);
u32 len;
const char* value = def;
for (len = 0; str[len]; len++) {
if (str[len] == '=') {
u32 new_idx = m.pool.add(str, len, true);
// reload from pool in case block was reallocated
value = m.pool.idx2str(idx) + len + 1;
idx = new_idx;
break;
}
}
m.add(idx, m.pool.addStr(value, true));
}

public fn bool Map.contains(const Map* m, const char* name, u32* indexp = nil) {
for (u32 i = 0; i < m.count; i++) {
if (!strcmp(m.pool.idx2str(m.names[i]), name)) {
if (indexp) *indexp = i;
return true;
}
}
return false;
}

public fn bool Map.contains_idx(const Map* m, u32 name_idx, u32* indexp = nil) @(unused) {
for (u32 i = 0; i < m.count; i++) {
if (m.names[i] == name_idx) {
if (indexp) *indexp = i;
return true;
}
}
return false;
}

public fn u32 Map.length(const Map* m) @(unused) {
return m.count;
}

public fn u32 Map.getNameIdx(const Map* m, u32 i) @(unused) {
return m.names[i];
}

public fn const char* Map.getName(const Map* m, u32 i) @(unused) {
return m.pool.idx2str(m.names[i]);
}

public fn u32 Map.getValueIdx(const Map* m, u32 i) @(unused) {
return m.values[i];
}

public fn const char* Map.getValue(const Map* m, u32 i) @(unused) {
return m.pool.idx2str(m.values[i]);
}

public fn u32* Map.getNames(const Map* m) @(unused) {
return m.names;
}

public fn u32* Map.getValues(const Map* m) @(unused) {
return m.values;
}
26 changes: 16 additions & 10 deletions compiler/compiler.c2
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,13 @@ public fn void build(string_pool.Pool* auxPool,
build_file.Info* build_info, // can be nil
build_target.Target* target,
const Options* opts,
string_list.List* features,
PluginHandler* pluginHandler)
{
Compiler c = {}
plugin_info.Info info = {}

c.build(auxPool, sm, diags, build_info, target, opts, pluginHandler, &info);
c.build(auxPool, sm, diags, build_info, target, opts, features, pluginHandler, &info);

if (opts.print_reports) {
c.sm.report(opts.print_reports > 1);
Expand Down Expand Up @@ -174,6 +175,7 @@ fn void Compiler.build(Compiler* c,
build_file.Info* build_info, // can be nil
build_target.Target* target,
const Options* opts,
string_list.List* features,
PluginHandler* pluginHandler,
plugin_info.Info* info)
{
Expand All @@ -192,7 +194,7 @@ fn void Compiler.build(Compiler* c,
c.target.disableWarnings();
c.target.disableAsserts();
c.removeFeature("AstStatistics");
c.addFeature("BOOTSTRAP", "1");
c.addFeature("BOOTSTRAP");
}

if (opts.no_build) {
Expand Down Expand Up @@ -278,16 +280,20 @@ fn void Compiler.build(Compiler* c,
c.addGlobalDefine("SYSTEM", c.targetInfo.getSystemName());
c.addGlobalDefine("ARCH", c.targetInfo.getArchName());
if (c.targetInfo.intWidth == 64) {
c.addFeature("ARCH_64BIT", "1");
c.addFeature("ARCH_64BIT");
} else {
c.addFeature("ARCH_32BIT", "1");
c.addFeature("ARCH_32BIT");
}
if (opts.asan) c.addFeature("__ASAN__");
if (opts.msan) c.addFeature("__MSAN__");
if (opts.ubsan) c.addFeature("__UBSAN__");

for (u32 i = 0; i < features.length(); i++) {
c.addFeature(features.get(i));
}
if (opts.asan) c.addFeature("__ASAN__", "1");
if (opts.msan) c.addFeature("__MSAN__", "1");
if (opts.ubsan) c.addFeature("__UBSAN__", "1");

#ifndef BOOTSTRAP
c.addFeature("EXPERIMENTAL", "1");
c.addFeature("EXPERIMENTAL");
#endif
c.parser = c2_parser.create(sm,
diags,
Expand Down Expand Up @@ -489,7 +495,7 @@ fn void Compiler.findTopModule(void* arg, ast.Module* m) {
c.mainFunc = c.analyser.findMain(m, c.main_idx);
}

fn void Compiler.addFeature(Compiler* c, const char* str, const char* value) {
fn void Compiler.addFeature(Compiler* c, const char* str) {
// TODO: handle value
c.target.addFeature(c.auxPool.addStr(str, true));
}
Expand All @@ -506,7 +512,7 @@ fn void Compiler.addGlobalDefine(Compiler* c, const char* prefix, const char* ta
tmp[i] = (ch == '-') ? '_' : (char)ctype.toupper(ch);
}

c.addFeature(tmp, "1");
c.addFeature(tmp);
}

// NOTE: paths are not 0-terminated
Expand Down
19 changes: 15 additions & 4 deletions compiler/main.c2
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,20 @@ type Options struct {
const char* output_name;
string_list.List targets;
string_list.List files;
string_list.List features;
}

fn void Options.init(Options* opts, string_pool.Pool* pool) {
memset(opts, 0, sizeof(Options));
opts.targets.init(pool);
opts.files.init(pool);
opts.features.init(pool);
}

fn void Options.free(Options *opts) {
opts.targets.free();
opts.files.free();
opts.features.free();
}

fn void write_file_or_die(const char* filename, string_buffer.Buf* buf) {
Expand Down Expand Up @@ -181,6 +184,7 @@ const char[] Usage_help =
" -A print Library ASTs\n"
" -b [file] use specified build file\n"
" -d [dir] change to [dir] first\n"
" -Dfeature[=value] define global feature with optional value\n"
" -h print this help\n"
" -i use IR backend\n"
" -I use IR backend and print generated IR\n"
Expand Down Expand Up @@ -326,6 +330,10 @@ fn void parse_arguments(ArgumentParser *ap, compiler.Options* comp_opts, Options
if (arg[1] == '-') {
parse_long_opt(ap, arg, comp_opts, opts);
} else {
const char *argarg = nil;
if (memchr("Ddbo", arg[1], 4)) { // need argument
argarg = arg[2] ? &arg[2] : ap.getOptionArgument(arg);
} else
if (strlen(arg) != 2) {
switch (arg + 1) {
case "help":
Expand All @@ -344,6 +352,9 @@ fn void parse_arguments(ArgumentParser *ap, compiler.Options* comp_opts, Options
case 'A':
comp_opts.print_lib_ast = true;
break;
case 'D':
opts.features.addStr(argarg);
break;
case 'I':
opts.use_ir_backend = true;
comp_opts.print_ir = true;
Expand All @@ -358,10 +369,10 @@ fn void parse_arguments(ArgumentParser *ap, compiler.Options* comp_opts, Options
comp_opts.print_ast = true;
break;
case 'b':
opts.build_file = ap.getOptionArgument(arg);
opts.build_file = argarg;
break;
case 'd':
opts.other_dir = ap.getOptionArgument(arg);
opts.other_dir = argarg;
break;
case '?':
case 'h':
Expand All @@ -374,7 +385,7 @@ fn void parse_arguments(ArgumentParser *ap, compiler.Options* comp_opts, Options
comp_opts.print_modules = true;
break;
case 'o':
opts.output_name = ap.getOptionArgument(arg);
opts.output_name = argarg;
break;
case 'r':
comp_opts.print_reports += 1;
Expand Down Expand Up @@ -639,7 +650,7 @@ fn bool Context.build_target(Context* c,
}
}

compiler.build(c.auxPool, c.sm, c.diags, c.build_info, target, &c.comp_opts, &c.pluginHandler);
compiler.build(c.auxPool, c.sm, c.diags, c.build_info, target, &c.comp_opts, &c.opts.features, &c.pluginHandler);

// TODO unload target-specific plugins?
// TODO fix build_file
Expand Down
6 changes: 3 additions & 3 deletions parser/c2_parser.c2
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import source_mgr local;
import src_loc local;
import stmt_list;
import string_buffer;
import string_list;
import string_map;
import string_pool;
import token local;
import value_type local;
Expand Down Expand Up @@ -59,7 +59,7 @@ public type Parser struct @(opaque) {
diagnostics.Diags* diags;
string_pool.Pool* pool;
Builder* builder;
const string_list.List* features;
const string_map.Map* features;
const keywords.Info* kwinfo;
bool is_interface;
bool is_generated;
Expand All @@ -85,7 +85,7 @@ public fn Parser* create(SourceMgr* sm,
string_pool.Pool* pool,
ast_builder.Builder* builder,
const keywords.Info* kwinfo,
const string_list.List* features,
const string_map.Map* features,
bool has_asserts)
{
Parser* p = calloc(1, sizeof(Parser));
Expand Down
Loading
Loading