Skip to content

Commit f4e0148

Browse files
committed
feat: Access references to globals through a custom GOT
This commit introduces the association of GOT indices to the LLVM index, which then allows us to utilise that when generating references to variables to check if a given variable has an entry in the GOT. If so, we obtain its index, and generate the necessary LLVM IR to access the address contained within the GOT rather than accessing the variable directly.
1 parent d9c4561 commit f4e0148

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

src/codegen/generators/expression_generator.rs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,40 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
282282
self.generate_expression_value(const_expression)
283283
}
284284

285+
/// Generate an access to the appropriate GOT entry to achieve an access to the given base
286+
/// lvalue.
287+
pub fn generate_got_access(
288+
&self,
289+
context: &AstNode,
290+
llvm_type: &BasicTypeEnum<'ink>,
291+
) -> Result<Option<PointerValue<'ink>>, Diagnostic> {
292+
match self.annotations.get(context) {
293+
Some(StatementAnnotation::Variable { qualified_name, .. }) => {
294+
// We will generate a GEP, which has as its base address the magic constant which
295+
// will eventually be replaced by the location of the GOT.
296+
let base = self
297+
.llvm
298+
.context
299+
.i64_type()
300+
.const_int(0xdeadbeef00000000, false)
301+
.const_to_pointer(llvm_type.ptr_type(0.into()).ptr_type(0.into()));
302+
303+
self.llvm_index
304+
.find_got_index(qualified_name)
305+
.map(|idx| {
306+
let ptr = self.llvm.load_array_element(
307+
base,
308+
&[self.llvm.context.i32_type().const_int(idx, false)],
309+
"",
310+
)?;
311+
Ok(self.llvm.load_pointer(&ptr, "").into_pointer_value())
312+
})
313+
.transpose()
314+
}
315+
_ => Ok(None),
316+
}
317+
}
318+
285319
/// generates a binary expression (e.g. a + b, x AND y, etc.) and returns the resulting `BasicValueEnum`
286320
/// - `left` the AstStatement left of the operator
287321
/// - `right` the AstStatement right of the operator
@@ -1218,13 +1252,17 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
12181252
}
12191253
}
12201254

1255+
let ctx_type =
1256+
self.annotations.get_type_or_void(context, self.index).get_type_information();
1257+
12211258
// no context ... so just something like 'x'
12221259
match self.annotations.get(context) {
12231260
Some(StatementAnnotation::Variable { qualified_name, .. })
1224-
| Some(StatementAnnotation::Program { qualified_name, .. }) => self
1225-
.llvm_index
1226-
.find_loaded_associated_variable_value(qualified_name)
1227-
.ok_or_else(|| Diagnostic::unresolved_reference(name, offset.clone())),
1261+
| Some(StatementAnnotation::Program { qualified_name, .. }) =>
1262+
self.generate_got_access(context, &self.llvm_index.get_associated_type(ctx_type.get_name())?)?.map_or(self
1263+
.llvm_index
1264+
.find_loaded_associated_variable_value(qualified_name)
1265+
.ok_or_else(|| Diagnostic::unresolved_reference(name, offset.clone())), Ok),
12281266
_ => Err(Diagnostic::unresolved_reference(name, offset.clone())),
12291267
}
12301268
}

src/codegen/generators/variable_generator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ impl<'ctx, 'b> VariableGenerator<'ctx, 'b> {
149149
for (name, _) in &globals {
150150
if let Some(idx) = got_entries.get(&name.to_string()) {
151151
new_got_entries.insert(name.to_string(), *idx);
152+
index.associate_got_index(name, *idx);
152153
new_got.insert(*idx, name.to_string());
153154
} else {
154155
new_globals.push(name.to_string());
@@ -162,6 +163,7 @@ impl<'ctx, 'b> VariableGenerator<'ctx, 'b> {
162163
idx += 1;
163164
}
164165
new_got_entries.insert(name.to_string(), idx);
166+
index.associate_got_index(name, idx);
165167
new_got.insert(idx, name.to_string());
166168
}
167169

src/codegen/llvm_index.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub struct LlvmTypedIndex<'ink> {
1414
type_associations: FxHashMap<String, BasicTypeEnum<'ink>>,
1515
pou_type_associations: FxHashMap<String, BasicTypeEnum<'ink>>,
1616
global_values: FxHashMap<String, GlobalValue<'ink>>,
17+
got_indices: FxHashMap<String, u64>,
1718
initial_value_associations: FxHashMap<String, BasicValueEnum<'ink>>,
1819
loaded_variable_associations: FxHashMap<String, PointerValue<'ink>>,
1920
implementations: FxHashMap<String, FunctionValue<'ink>>,
@@ -29,6 +30,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
2930
type_associations: FxHashMap::default(),
3031
pou_type_associations: FxHashMap::default(),
3132
global_values: FxHashMap::default(),
33+
got_indices: FxHashMap::default(),
3234
initial_value_associations: FxHashMap::default(),
3335
loaded_variable_associations: FxHashMap::default(),
3436
implementations: FxHashMap::default(),
@@ -51,6 +53,9 @@ impl<'ink> LlvmTypedIndex<'ink> {
5153
for (name, value) in other.global_values.drain() {
5254
self.global_values.insert(name, value);
5355
}
56+
for (name, index) in other.got_indices.drain() {
57+
self.got_indices.insert(name, index);
58+
}
5459
for (name, assocication) in other.initial_value_associations.drain() {
5560
self.initial_value_associations.insert(name, assocication);
5661
}
@@ -110,6 +115,13 @@ impl<'ink> LlvmTypedIndex<'ink> {
110115
.or_else(|| self.parent_index.and_then(|it| it.find_global_value(name)))
111116
}
112117

118+
pub fn find_got_index(&self, name: &str) -> Option<u64> {
119+
self.got_indices
120+
.get(&name.to_lowercase())
121+
.copied()
122+
.or_else(|| self.parent_index.and_then(|it| it.find_got_index(name)))
123+
}
124+
113125
pub fn find_associated_type(&self, type_name: &str) -> Option<BasicTypeEnum<'ink>> {
114126
self.type_associations
115127
.get(&type_name.to_lowercase())
@@ -153,6 +165,15 @@ impl<'ink> LlvmTypedIndex<'ink> {
153165
Ok(())
154166
}
155167

168+
pub fn associate_got_index(
169+
&mut self,
170+
variable_name: &str,
171+
index: u64,
172+
) -> Result<(), Diagnostic> {
173+
self.got_indices.insert(variable_name.to_lowercase(), index);
174+
Ok(())
175+
}
176+
156177
pub fn associate_implementation(
157178
&mut self,
158179
callable_name: &str,

0 commit comments

Comments
 (0)