Skip to content

Commit 4eec6de

Browse files
committed
[Heavy] Add define-binding to access heavy::ContextLocal objects
1 parent 18524e5 commit 4eec6de

File tree

16 files changed

+234
-105
lines changed

16 files changed

+234
-105
lines changed

clang/lib/Parse/ParseDeclHeavy.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -319,18 +319,16 @@ bool Parser::ParseHeavyScheme() {
319319

320320
heavy::Context& Context = HeavyScheme->getContext();
321321
heavy::builtins::InitParseSourceFile(Context, ParseSourceFileFn);
322-
HEAVY_CLANG_VAR(diag_error).init(Context,
323-
Context.CreateLambda(diag_error));
324-
HEAVY_CLANG_VAR(diag_warning).init(Context,
325-
Context.CreateLambda(diag_warning));
326-
HEAVY_CLANG_VAR(diag_note).init(Context,
327-
Context.CreateLambda(diag_note));
328-
HEAVY_CLANG_VAR(hello_world).init(Context,
329-
Context.CreateLambda(hello_world));
330-
HEAVY_CLANG_VAR(expr_eval).init(Context,
322+
HEAVY_CLANG_VAR(diag_error).set(Context,
323+
Context.CreateLambda(diag_error));
324+
HEAVY_CLANG_VAR(diag_warning).set(Context,
325+
Context.CreateLambda(diag_warning));
326+
HEAVY_CLANG_VAR(diag_note).set(Context,
327+
Context.CreateLambda(diag_note));
328+
HEAVY_CLANG_VAR(hello_world).set(Context,
329+
Context.CreateLambda(hello_world));
330+
HEAVY_CLANG_VAR(expr_eval).set(Context,
331331
Context.CreateLambda(expr_eval));
332-
HEAVY_CLANG_VAR(write_lexer).init(Context);
333-
HEAVY_CLANG_VAR(lexer_writer).init(Context);
334332
HeavyScheme->RegisterModule(HEAVY_CLANG_LIB_STR, HEAVY_CLANG_LOAD_MODULE);
335333
}
336334

heavy/include/heavy/Clang.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@ inline void HEAVY_CLANG_INIT(heavy::Context& Context) {
7575
inline void HEAVY_CLANG_LOAD_MODULE(heavy::Context& Context) {
7676
HEAVY_CLANG_INIT(Context);
7777
heavy::initModuleNames(Context, HEAVY_CLANG_LIB_STR, {
78-
{"diag-error", HEAVY_CLANG_VAR(diag_error).init(Context)},
79-
{"diag-warning", HEAVY_CLANG_VAR(diag_warning).init(Context)},
80-
{"diag-note", HEAVY_CLANG_VAR(diag_note).init(Context)},
81-
{"hello-world", HEAVY_CLANG_VAR(hello_world).init(Context)},
82-
{"write-lexer", HEAVY_CLANG_VAR(write_lexer).init(Context)},
83-
{"lexer-writer",HEAVY_CLANG_VAR(lexer_writer).init(Context)},
84-
{"expr-eval", HEAVY_CLANG_VAR(expr_eval).init(Context)}
78+
{"diag-error", HEAVY_CLANG_VAR(diag_error).get(Context)},
79+
{"diag-warning", HEAVY_CLANG_VAR(diag_warning).get(Context)},
80+
{"diag-note", HEAVY_CLANG_VAR(diag_note).get(Context)},
81+
{"hello-world", HEAVY_CLANG_VAR(hello_world).get(Context)},
82+
{"write-lexer", HEAVY_CLANG_VAR(write_lexer).get(Context)},
83+
{"lexer-writer",HEAVY_CLANG_VAR(lexer_writer).get(Context)},
84+
{"expr-eval", HEAVY_CLANG_VAR(expr_eval).get(Context)}
8585
});
8686
}
8787
}

heavy/include/heavy/Context.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ struct OpEvalDeleter {
6464
using OpEvalPtr = std::unique_ptr<OpEvalImpl, OpEvalDeleter>;
6565

6666
class ContextLocalLookup {
67-
friend struct ContextLocal;
67+
public:
6868
llvm::DenseMap<uintptr_t, Value> LookupTable;
6969
};
7070

heavy/include/heavy/OpGen.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/Support/Casting.h"
2626
#include <deque>
2727
#include <string>
28+
#include <tuple>
2829
#include <utility>
2930

3031
namespace mlir {
@@ -331,7 +332,9 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
331332
mlir::Value createGlobal(SourceLocation Loc, llvm::StringRef MangledName);
332333
mlir::Value createBinding(Binding *B, mlir::Value Init);
333334
mlir::Value createDefine(Value Id, Value Args, Value OrigCall);
335+
std::tuple<EnvEntry, Symbol*, String*> createTopLevelBindingInfo(Value Id);
334336
mlir::Value createTopLevelDefine(Value Id, Value Args, Value OrigCall);
337+
mlir::Value createExternalBinding(Value Id, Value ExtSymbol);
335338
mlir::Value createUndefined();
336339
mlir::Value createSet(SourceLocation Loc, Value LHS, Value RHS);
337340

heavy/include/heavy/Ops.td

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,19 @@ def heavy_GlobalOp : HeavyOp<"global", [Symbol, IsolatedFromAbove]> {
192192
let arguments = (ins StrAttr:$sym_name);
193193
}
194194

195-
def heav_GlobalSyntaxOp : HeavyOp<"global_syntax",
196-
[Symbol, IsolatedFromAbove]> {
195+
def heavy_GlobalBindingOp : HeavyOp<"global_binding",
196+
[Symbol, IsolatedFromAbove]> {
197+
let description = [{
198+
Create a module top level variable and assign it the binding
199+
encapsulated by a heavy::ContextLocal object that is dynamically
200+
loaded from the provided $ext_sym_name.
201+
}];
202+
203+
let arguments = (ins StrAttr:$sym_name, StrAttr:$ext_sym_name);
204+
}
205+
206+
def heavy_GlobalSyntaxOp : HeavyOp<"global_syntax",
207+
[Symbol, IsolatedFromAbove]> {
197208
let description = [{
198209
GlobalSyntaxOp denotes a module top level syntax object
199210
that is initialized at compile time.

heavy/include/heavy/Value.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,14 +2131,13 @@ struct ExternString : public ExternValue<String::sizeToAlloc(Len)> {
21312131
// as a key for the map to the context specific value.
21322132
// - Point to a Binding by default since values are often
21332133
// loaded lazily.
2134-
struct ContextLocal {
2135-
// Initializes the variable as a Value or
2136-
// as a Binding if Value is not provided.
2137-
heavy::Value init(heavy::Context& C, heavy::Value Value = nullptr);
2134+
class ContextLocal {
2135+
heavy::Value GetSystemSymbolName(heavy::Context& C);
2136+
public:
21382137
uintptr_t key() const { return reinterpret_cast<uintptr_t>(this); }
2139-
heavy::Value get(heavy::ContextLocalLookup const& C) const;
2140-
heavy::Value get_binding(heavy::ContextLocalLookup const& C) const;
2141-
void set(heavy::ContextLocalLookup& C, heavy::Value Value);
2138+
heavy::Value get(heavy::Context& C);
2139+
heavy::Binding* getBinding(heavy::Context& C);
2140+
void set(heavy::Context& C, heavy::Value Value);
21422141
};
21432142

21442143
// ListIterator - Provide ForwardIterator for lists

heavy/lib/Builtins.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ heavy::ContextLocal parse_source_file;
3838

3939
heavy::ExternBuiltinSyntax cond_expand;
4040
heavy::ExternBuiltinSyntax define;
41+
heavy::ExternBuiltinSyntax define_binding;
4142
heavy::ExternBuiltinSyntax define_syntax;
4243
heavy::ExternBuiltinSyntax syntax_rules;
4344
heavy::ExternBuiltinSyntax syntax_fn;
@@ -133,8 +134,8 @@ mlir::Value quasiquote(OpGen& OG, Pair* P);
133134
void op_eval(Context& C, ValueRefs Args);
134135

135136
mlir::Value define(OpGen& OG, Pair* P) {
136-
Pair* P2 = dyn_cast<Pair>(P->Cdr);
137-
Value Id = nullptr;
137+
Pair* P2 = dyn_cast<Pair>(P->Cdr);
138+
Value Id;
138139

139140
if (!P2)
140141
return OG.SetError("invalid syntax for define", P);
@@ -148,6 +149,21 @@ mlir::Value define(OpGen& OG, Pair* P) {
148149
return OG.createDefine(Id, P2, P);
149150
}
150151

152+
// Binds a dynamically loaded heavy::ContextLocal.
153+
mlir::Value define_binding(OpGen& OG, Pair* P) {
154+
Pair* P2 = dyn_cast<Pair>(P->Cdr);
155+
Value Name;
156+
Value ExtName;
157+
158+
if (P2) {
159+
Name = P2->Car;
160+
ExtName = P2->Cdr.car();
161+
}
162+
if (!P2 || !ExtName || !isa<Symbol>(Name) || !isa<Symbol, String>(ExtName))
163+
return OG.SetError("invalid syntax for define-binding", P);
164+
return OG.createExternalBinding(Name, ExtName);
165+
}
166+
151167
mlir::Value define_syntax(OpGen& OG, Pair* P) {
152168
Pair* P2 = dyn_cast<Pair>(P->Cdr);
153169
if (!P2) return OG.SetError("invalid define-syntax syntax", P);
@@ -1299,6 +1315,7 @@ void HEAVY_BASE_INIT(heavy::Context& Context) {
12991315
Context.DialectRegistry->insert<heavy::Dialect>();
13001316
// syntax
13011317
HEAVY_BASE_VAR(define) = heavy::builtins::define;
1318+
HEAVY_BASE_VAR(define_binding) = heavy::builtins::define_binding;
13021319
HEAVY_BASE_VAR(define_syntax) = heavy::builtins::define_syntax;
13031320
HEAVY_BASE_VAR(syntax_rules) = heavy::builtins::syntax_rules;
13041321
HEAVY_BASE_VAR(syntax_fn) = heavy::builtins::syntax_fn;
@@ -1322,7 +1339,6 @@ void HEAVY_BASE_INIT(heavy::Context& Context) {
13221339
HEAVY_BASE_VAR(source_loc) = heavy::builtins::source_loc;
13231340
HEAVY_BASE_VAR(source_loc_valid) = heavy::builtins::source_loc_valid;
13241341
HEAVY_BASE_VAR(dump_source_loc) = heavy::builtins::dump_source_loc;
1325-
HEAVY_BASE_VAR(parse_source_file).init(Context);
13261342

13271343
// functions
13281344
HEAVY_BASE_VAR(add) = heavy::builtins::add;
@@ -1369,7 +1385,6 @@ void HEAVY_BASE_INIT(heavy::Context& Context) {
13691385
HEAVY_BASE_VAR(eval) = heavy::builtins::eval;
13701386
HEAVY_BASE_VAR(op_eval) = heavy::builtins::op_eval;
13711387
HEAVY_BASE_VAR(compile) = heavy::builtins::compile;
1372-
HEAVY_BASE_VAR(module_path).init(Context);
13731388

13741389
HEAVY_BASE_VAR(is_boolean) = heavy::builtins::is_boolean;
13751390
HEAVY_BASE_VAR(is_bytevector) = heavy::builtins::is_bytevector;
@@ -1399,6 +1414,8 @@ void HEAVY_BASE_LOAD_MODULE(heavy::Context& Context) {
13991414
heavy::initModuleNames(Context, HEAVY_BASE_LIB_STR, {
14001415
// syntax
14011416
{"define", HEAVY_BASE_VAR(define)},
1417+
{"define-binding",
1418+
HEAVY_BASE_VAR(define_binding)},
14021419
{"define-syntax", HEAVY_BASE_VAR(define_syntax)},
14031420
{"if", HEAVY_BASE_VAR(if_)},
14041421
{"lambda", HEAVY_BASE_VAR(lambda)},

heavy/lib/Context.cpp

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@
5252
#include <memory>
5353
#include <string>
5454

55+
#if __has_include(<dlfcn.h>)
56+
#include <dlfcn.h>
57+
#define HEAVY_HAS_DLADDR 1
58+
#else
59+
#define HEAVY_HAS_DLADDR 0
60+
#endif
61+
5562
using namespace heavy;
5663

5764
void ValueBase::dump() {
@@ -1512,40 +1519,39 @@ Value Context::RebuildLiteral(Value V, Value Env) {
15121519

15131520
// ContextLocal
15141521

1515-
heavy::Value ContextLocal::init(heavy::Context& C, heavy::Value Value) {
1516-
heavy::ContextLocalLookup& CL = C;
1517-
heavy::Value& Result = CL.LookupTable[key()];
1518-
// Allow init to be called after the user already called init.
1519-
if (Result != nullptr && Value == nullptr)
1520-
return Result;
1521-
assert(Result == nullptr &&
1522-
"context local should be initialized only once");
1523-
Result = Value ? Value : C.CreateBinding(heavy::Undefined());
1524-
return Result;
1525-
}
1526-
1527-
void ContextLocal::set(heavy::ContextLocalLookup& C,
1528-
heavy::Value Value) {
1529-
heavy::Value& Result = C.LookupTable[key()];
1530-
auto* Binding = dyn_cast_or_null<heavy::Binding>(Result);
1531-
assert(Binding && "context local must be initialized as binding");
1522+
void ContextLocal::set(heavy::Context& C, heavy::Value Value) {
1523+
heavy::Binding* Binding = getBinding(C);
15321524
Binding->setValue(Value);
15331525
}
15341526

15351527
// Return the value pointed to by Binding or nullptr.
1536-
heavy::Value ContextLocal::get(heavy::ContextLocalLookup const& C) const {
1537-
heavy::Value Value = C.LookupTable.lookup(key());
1538-
if (auto* Binding = dyn_cast<heavy::Binding>(Value))
1539-
return Binding->getValue();
1540-
return Value;
1528+
heavy::Value ContextLocal::get(heavy::Context& C) {
1529+
return getBinding(C)->getValue();
15411530
}
15421531

1543-
heavy::Value ContextLocal::get_binding(
1544-
heavy::ContextLocalLookup const& C) const {
1545-
heavy::Value Value = C.LookupTable.lookup(key());
1546-
return cast<heavy::Binding>(Value);
1532+
heavy::Binding* ContextLocal::getBinding(heavy::Context& C) {
1533+
heavy::Value& Result = C.LookupTable[key()];
1534+
auto* Binding = dyn_cast_or_null<heavy::Binding>(Result);
1535+
if (!Binding) {
1536+
Value Name = GetSystemSymbolName(C);
1537+
heavy::Value Undef = Name ? heavy::Undefined(Name) : heavy::Undefined();
1538+
Binding = C.CreateBinding(Undef);
1539+
Result = Binding;
1540+
}
1541+
return Binding;
15471542
}
15481543

1544+
heavy::Value ContextLocal::GetSystemSymbolName(heavy::Context& C) {
1545+
#if HEAVY_HAS_DLADDR
1546+
Dl_info Info;
1547+
if (dladdr(this, &Info)) {
1548+
Symbol* S = C.CreateSymbol(llvm::StringRef(Info.dli_sname));
1549+
return S;
1550+
}
1551+
#endif
1552+
1553+
return Value();
1554+
}
15491555

15501556
// Module
15511557

heavy/lib/Heap.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ void Context::CollectGarbage() {
354354
GC.VisitRootNode(DensePair.second);
355355
}
356356

357+
// LookupTable
358+
for (auto& [_, V] : LookupTable)
359+
GC.VisitRootNode(V);
360+
357361
GC.VisitRootNode(Err);
358362
GC.VisitRootNode(ExceptionHandlers);
359363

heavy/lib/Mlir.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -841,8 +841,8 @@ void HEAVY_MLIR_INIT(heavy::Context& C) {
841841
mlir::MLIRContext* MC = C.MLIRContext.get();
842842
heavy::Value MC_Val = C.CreateAny(MC);
843843
heavy::Value BuilderVal = C.CreateAny(mlir::OpBuilder(MC));
844-
HEAVY_MLIR_VAR(current_context).init(C, C.CreateBinding(MC_Val));
845-
HEAVY_MLIR_VAR(current_builder).init(C, C.CreateBinding(BuilderVal));
844+
HEAVY_MLIR_VAR(current_context).set(C, MC_Val);
845+
HEAVY_MLIR_VAR(current_builder).set(C, BuilderVal);
846846

847847
HEAVY_MLIR_VAR(create_op) = heavy::mlir_bind::create_op;
848848
HEAVY_MLIR_VAR(create_op_impl) = heavy::mlir_bind::create_op_impl;
@@ -880,7 +880,7 @@ void HEAVY_MLIR_LOAD_MODULE(heavy::Context& C) {
880880
heavy::initModuleNames(C, HEAVY_MLIR_LIB_STR, {
881881
{"old-create-op", HEAVY_MLIR_VAR(create_op)},
882882
{"%create-op", HEAVY_MLIR_VAR(create_op_impl)},
883-
{"current-builder", HEAVY_MLIR_VAR(current_builder).get_binding(C)},
883+
{"current-builder", HEAVY_MLIR_VAR(current_builder).getBinding(C)},
884884
{"get-region", HEAVY_MLIR_VAR(get_region)},
885885
{"entry-block", HEAVY_MLIR_VAR(entry_block)},
886886
{"add-argument", HEAVY_MLIR_VAR(add_argument)},

0 commit comments

Comments
 (0)